This seems so simple but my searching as failed to find a good result.

The idea is that you can move in 360 degrees but you aren't faster when you move in a diagonal direction. I know how to do this with trig. The problem is I I want some physics so that if you are traveling north and start traveling south you first need to slow down to zero to go south. (And if going 270 deg to 30 deg it would be a more complicated.) The character has acceleration and a max speed.

I know that vectors are the solution but I can't find how to apply them the current speed to get smooth movement.

I'm doing this in GameMaker Studio 2, but pseudocode should suffice. Here's what I have.

var h,v;
h = key_to_axis(vk_right,vk_left);
v = key_to_axis(vk_down,vk_up);

var dir = point_direction(0,0,h,v)
spd = approach(spd,max_spd,accel);
x+= lengthdir_x(max_spd,dir);
y+= lengthdir_y(max_spd,dir);

Note that this movement is shared by characters that can move in the full 360 degrees.

  • \$\begingroup\$ Are you trying to make a movement control mechanic like the one in asteroids where you only accelerate, decelerate and change direction? Or maybe something like age of empires naval movement where ships have to turn around in place before advancing? \$\endgroup\$
    – Theraot
    Oct 6, 2019 at 5:21
  • \$\begingroup\$ No its more like Nuclear Throne or World's Hardest Game. Actually I am trying to avoid the movement in World's Hardest Game as I think it feels very clunky. But I did forget to say that friction needs to be implemented as well. \$\endgroup\$
    – Adam Berck
    Oct 6, 2019 at 5:23

1 Answer 1


Figured it out. The trick is to make another acceleration vector (or two variables) with the magnitude of acceleration rate and the direction that you want to go. Then to add it to your current velocity (both x speed and y speed). Check the magnitude of the the velocity to ensure its not greater than the top speed. Then apply it to x and y.

I added a friction vector that constantly goes against your velocity. It also can't be larger than your current speed and is stronger if you aren't moving. This mimics reality because when you slow down you get the benefit of friction but when accelerating it works against you.

///Player Movement
not_moving = !mouse_check_button(mb_left) || point_distance(x,y,mouse_x,mouse_y)<30;
goal_dir = point_direction(x,y,mouse_x,mouse_y)
var move_fric = not_moving ? fric+accel : fric; //if not moving then you accel to a stop

var spd = sqrt(sqr(vx)+sqr(vy));
var dir = (point_direction(0,0,vx,vy)+180)%360;
var ax,ay;
    move_fric = spd;
ax = lengthdir_x(move_fric,dir);
ay = lengthdir_y(move_fric,dir);
vx += ax;
vy += ay;

    var dir = goal_dir;
    var ax,ay;
    ax = lengthdir_x(accel,dir);
    ay = lengthdir_y(accel,dir);
    vx += ax;
    vy += ay;
    spd = sqrt(sqr(vx)+sqr(vy));
        vx = lengthdir_x(max_spd,dir);
        vy = lengthdir_y(max_spd,dir);

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .