Inertial movement

R

Resonant Drifter

Guest
I'm looking for a movement system or tutorial using an 8+ directional inertial movement.

I'm toying around with a submarine side-scrolling game and am making the movement system. I came up with a four direction system that works fine on the basic level but falls apart after that. Right now I push the right key and the sub accelerates up to max speed based on a variable; let go and it slows down based on a variable. Like I said, it does this going up, left and down as well. Excellent.

The issues come in when going diagonal and reversing direction. Going diagonally and releasing the keys, the system will pick one of the two (up and right, for example, and it will choose right) directions and go with it alone. Upon reversing, it won't slow down to zero and then pick speed up again. It simply reverses immediately because I'm basing it on speed, no doubt.

I tried looking myself but couldn't find tutorials directly on what I'm looking for. I really only found an Asteroids game that has a simplified version of my control system and I get pointed to the physics engine but I don't want to mess with gravity (which is zero), just my ship's speed.

Anyway, after all that rambling if anyone could point me in the direction of such a thing I would appreciate it!
 

CMAllen

Member
To merge between two different sets of values, you need to store them. In this case, you need a current direction and current velocity, along with new direction and new velocity. But with the way GM does directions, you don't really want to merge directions together directly. What you want are two sets of vertical and horizontal axis -- new_axisH, new_axisV, current_axisH, and current_axisV. The new axis values are going to be based on your user input, (for now, I'm assuming vk_up, vk_down, vk_right, and vk_left), which you then convert into the requisite 8 directions of movement. Left is -1, right is 1. Up is -1, Down is 1. With those, your new_axisH is thus Left+Right, and new_axisV is Up+Down. That gives you the new direction and the new velocity. Now you need to merge the two together. For the sake of simplicity, we'll just say that you'll blend new and current values together at 5% intervals per step event (but this rate is entirely up to you):

Code:
if(abs(max(new_axisH,new_axisV) = 0)
{
    new_velocity-=drag; //No velocity is being added, apply drag.
}
else
{
    new_velocity = min(new_velocity+impulse, max_velocity);
}
current_velocity = current_velocity*0.95 + new_velocity*0.05;
current_direction = point_direction(0, 0, current_axisH*0.95 + new_axisH*0.05, current_axisV*0.95 + new_axisV*0.05);
And believe it or not, that's the the worst of it. Now that you've got a direction and a velocity to move the object, you move your player object using the lengthdir_x and lengthdir_y functions like so:
Code:
x+lengthdir_x(current_velocity, current_direction);
y+lengthdir_y(current_velocity, current_direction);
 
Last edited:

CMAllen

Member
Something was bugging me about the code I suggested. And it's that I vastly over-complicated something that would otherwise be very simple. You still want the axisH and axisV as above from the user input. But that's about it.
Code:
if(abs(hspeed) < max_hspeed)
{
     hspeed += impulse*sign(axisH);
}
else if (axisH = 0)
{
     hspeed *= 0.9; //No horizontal thrust. Reduce speed.
}

if(abs(vspeed) < max_vspeed)
{
     vspeed += impulse*sign(axisV);
}
else if (axisV = 0)
{
     vspeed *= 0.9; //No vertical thrust. Reduce speed.
}
Much simpler. Not perfect. But simpler.
 

GMWolf

aka fel666
The trick is to deal with the x and y input separately. Then merge these values into a single vector.
You can then do all your max_speed, acceleration and restitution calculations on that vector.
 

Avram

Member
Apologies for resurrecting an old thread but does anyone know what the variable impulse is meant to be?
 

Lumenflower

Yellow Dog
This video explains it quite well - should give you all the conceptual guidance you need, and you can easily translate it into GML. Long story short, you have two vectors - one is the vector you'd ideally like to be moving along (defined by the currently held movement buttons), and one is the actual vector you're currently moving along. Then all you do is step the actual vector towards the ideal vector by an amount determined by your acceleration/friction.
 
Top