• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

GameMaker [SOLVED] Player Movement Momentum

king javo

Member
Hi, I'm trying to figure out the best way to have my top-down player lag when changing opposite direction (180 degrees) before moving the other direction to give the appearance of momentum. So when you're running left and the move the gamepad right, I want my player to stumble and cutback left a little (basically decelerate) before starting to move right.

Anyone know how to do this? Below is my movement code with my quick attempt at trying to do it on the xaxis by comparing previous xaxis with the current xaxis.

Code:
deadzone_limit = argument0;
acc = att_acceleration;
dec = att_agility;
maxSpeed = att_maxSpeed;
global.xaxis_previous = xaxis;
global.yaxis_previous = yaxis;

//if inside deadzone then decelerate
if (yaxis >= -deadzone_limit && yaxis <= deadzone_limit
&& xaxis >= -deadzone_limit && xaxis <= deadzone_limit)
{   
    if speed > dec
    {   
        speed -= dec;
    }
    else
    {
        speed = 0;
    }
}
else if (global.xaxis_previous != xaxis && global.xaxis_previous - xaxis == 2)
{       
    state = scrCutbackState;
    //set time to dash
    alarm[0] = room_speed/6;
}
else
{
    //Player still hasn't reached top speed
    if speed < maxSpeed
    {   
        speed += acc;
    }
    else
    {
        speed = maxSpeed;
    }
    
    //point player in correct direction
    direction = point_direction(0, 0, xaxis, yaxis);
}

//Control the sprite
image_speed = .2;
if (speed == 0) image_index = 0;
 

Mazey

Member
In the End Step event you could save direction in a new variable direction_old. Then do something like if (angle_difference(direction,direction_old) > 180) { speed = 0; } in your movement code. Make sure to update direction or it will be the same as direction_old. Hope that makes sense!
 
what I do is I have the vector that the character is actually moving (hspeed, vspeed)

and then I have the vector that I want them to move (whatever keys are pressed)

and then I have the character accelerate in the direction that is the difference betweeen the desired and the actual movement vectors.

This should work no matter what the actual or desired movement directions or speeds may be.
Code:
    var _xd = desired_hspeed - hspeed;
    var _yd = desired_vspeed - vspeed;
    var _length = sqrt( _xd * _xd + _yd * _yd );
    if ( _length > 0 ) { /
        var _acceleration = min( _length, acceleration ) / _length;
        hspeed += _xd * _acceleration;
        vspeed += _yd * _acceleration;
    }
 

king javo

Member
In the End Step event you could save direction in a new variable direction_old. Then do something like if (angle_difference(direction,direction_old) > 180) { speed = 0; } in your movement code. Make sure to update direction or it will be the same as direction_old. Hope that makes sense!
I tried this last night and it's not hitting the >180 check for some reason. I can look more and let you know. Thanks for the help!
 

king javo

Member
what I do is I have the vector that the character is actually moving (hspeed, vspeed)

and then I have the vector that I want them to move (whatever keys are pressed)

and then I have the character accelerate in the direction that is the difference betweeen the desired and the actual movement vectors.

This should work no matter what the actual or desired movement directions or speeds may be.
Code:
    var _xd = desired_hspeed - hspeed;
    var _yd = desired_vspeed - vspeed;
    var _length = sqrt( _xd * _xd + _yd * _yd );
    if ( _length > 0 ) { /
        var _acceleration = min( _length, acceleration ) / _length;
        hspeed += _xd * _acceleration;
        vspeed += _yd * _acceleration;
    }
I can kind of follow your logic, but will this just accelerate correctly or actually behave like I was asking in my post? Where the player will move one way and then stumble to move the opposite direction if you change the direction from right to left as an example. Similar to a football player running left and immediately cutting to the opposite right direction. There should be a slow down going left and then cutback and start moving right.

What does
Code:
desired_hspeed
and
Code:
desired_vspeed
actually resemble here?
 
desired_hspeed and desired_vspeed is just the vector you would be moving if you accelerated instantly. It's the direction and speed you are trying to move. Whereas hspeed and vspeed are the actual movement.

The effect will be just that the player will appear to have some inertia, meaning they will resist changes in motion.
 

king javo

Member
desired_hspeed and desired_vspeed is just the vector you would be moving if you accelerated instantly. It's the direction and speed you are trying to move. Whereas hspeed and vspeed are the actual movement.

The effect will be just that the player will appear to have some inertia, meaning they will resist changes in motion.
Your code doesn't seem to be working, but it could very well be I'm not getting the desired speed values correctly. Below is the code I'm currently working with to move my player. Your code is at the bottom. The player just moves the exact direction the controller moves without any momentum or lag.

Am I missing something?

Code:
deadzone_limit = argument0;
acc = att_acceleration;
dec = att_agility;
maxSpeed = att_maxSpeed;

//--------------------------------------------------------------------
//Get direction
direction = point_direction(0, 0, xaxis, yaxis);

//Get the length
if (xaxis == 0 && yaxis == 0)
{
    //decelerate
    //spd = lerp(spd, 0, friction_);   
}
else
{
    //increase speed
    spd += att_acceleration;
    //limit to max speed
    spd = clamp(spd, -att_maxSpeed, att_maxSpeed);
    
}

//Get the hspd and vspd
desired_hspeed = lengthdir_x(spd, direction);
desired_vspeed = lengthdir_y(spd, direction);

//Control the sprite
image_speed = .2;
if (spd == 0) image_index = 0;

//--------------------------------------------------------------------
//New Inertia Code for Momentum
var _xd = desired_hspeed - hspeed;
var _yd = desired_vspeed - vspeed;
var _length = sqrt( _xd * _xd + _yd * _yd );
if ( _length > 0 )
{
    var _acceleration = min( _length, acc ) / _length;
    hspeed += _xd * _acceleration;
    vspeed += _yd * _acceleration;
}
 

king javo

Member
Your code doesn't seem to be working, but it could very well be I'm not getting the desired speed values correctly. Below is the code I'm currently working with to move my player. Your code is at the bottom. The player just moves the exact direction the controller moves without any momentum or lag.

Am I missing something?

Code:
deadzone_limit = argument0;
acc = att_acceleration;
dec = att_agility;
maxSpeed = att_maxSpeed;

//--------------------------------------------------------------------
//Get direction
direction = point_direction(0, 0, xaxis, yaxis);

//Get the length
if (xaxis == 0 && yaxis == 0)
{
    //decelerate
    spd = lerp(spd, 0, friction_); 
}
else
{
    //increase speed
    spd += att_acceleration;
    //limit to max speed
    spd = clamp(spd, -att_maxSpeed, att_maxSpeed);
  
}

//Get the hspd and vspd
desired_hspeed = lengthdir_x(spd, direction);
desired_vspeed = lengthdir_y(spd, direction);

//Control the sprite
image_speed = .2;
if (spd == 0) image_index = 0;

//--------------------------------------------------------------------
//New Inertia Code for Momentum
var _xd = desired_hspeed - hspeed;
var _yd = desired_vspeed - vspeed;
var _length = sqrt( _xd * _xd + _yd * _yd );
if ( _length > 0 )
{
    var _acceleration = min( _length, acc ) / _length;
    hspeed += _xd * _acceleration;
    vspeed += _yd * _acceleration;
}
Ok I just figured out I was setting the direction which overwrites your code...

This is what I have now and it seems to be working... just need to tweak. Great help! Love it. Thanks so much.

Code:
deadzone_limit = argument0;
acc = att_acceleration;
dec = att_agility;
maxSpeed = att_maxSpeed;

//--------------------------------------------------------------------
//Get direction
desired_direction = point_direction(0, 0, xaxis, yaxis);

//Get the length
if (xaxis == 0 && yaxis == 0)
{
    //decelerate
    //spd = lerp(spd, 0, friction_);  
}
else
{
    //increase speed
    spd += att_acceleration;
    //limit to max speed
    spd = clamp(spd, -att_maxSpeed, att_maxSpeed);
  
}

//Get the hspd and vspd
desired_hspeed = lengthdir_x(spd, desired_direction);
desired_vspeed = lengthdir_y(spd, desired_direction);


//Control the sprite
image_speed = .2;
if (spd == 0) image_index = 0;

//--------------------------------------------------------------------
//New Inertia Code for Momentum
var _xd = desired_hspeed - hspeed;
var _yd = desired_vspeed - vspeed;
var _length = sqrt( _xd * _xd + _yd * _yd );
if ( _length > 0 )
{
    var _acceleration = min( _length, acc ) / _length;
    hspeed += _xd * _acceleration;
    vspeed += _yd * _acceleration;
}
 

king javo

Member
This seems to be working, but the players still looks "floaty". I can try to adjust the acceleration and deceleration values to see if that helps. The one thing I'll need to do next though is to lock the x & y axis when they are cutting back. The player should stay in the same direction when cutting back and not be able to move around while cutting back if that makes sense.

I'll probably try to lock the axis values next and will post the code if I figure it out.
 
Your code doesn't seem to be working, but it could very well be I'm not getting the desired speed values correctly. Below is the code I'm currently working with to move my player. Your code is at the bottom. The player just moves the exact direction the controller moves without any momentum or lag.

Am I missing something?

Code:
deadzone_limit = argument0;
acc = att_acceleration;
dec = att_agility;
maxSpeed = att_maxSpeed;

//--------------------------------------------------------------------
//Get direction
direction = point_direction(0, 0, xaxis, yaxis);

//Get the length
if (xaxis == 0 && yaxis == 0)
{
    //decelerate
    //spd = lerp(spd, 0, friction_);  
}
else
{
    //increase speed
    spd += att_acceleration;
    //limit to max speed
    spd = clamp(spd, -att_maxSpeed, att_maxSpeed);
   
}

//Get the hspd and vspd
desired_hspeed = lengthdir_x(spd, direction);
desired_vspeed = lengthdir_y(spd, direction);

//Control the sprite
image_speed = .2;
if (spd == 0) image_index = 0;

//--------------------------------------------------------------------
//New Inertia Code for Momentum
var _xd = desired_hspeed - hspeed;
var _yd = desired_vspeed - vspeed;
var _length = sqrt( _xd * _xd + _yd * _yd );
if ( _length > 0 )
{
    var _acceleration = min( _length, acc ) / _length;
    hspeed += _xd * _acceleration;
    vspeed += _yd * _acceleration;
}
What is the value of acc? If it is too high, it will pretty much just accelerate instantly. Also adding more acceleration code on top of this is kind of redundant.
 

king javo

Member
What is the value of acc? If it is too high, it will pretty much just accelerate instantly. Also adding more acceleration code on top of this is kind of redundant.
The player seems to be floating around the screen like a UFO. I'd also like to keep the player frozen in the same direction/line when cutting back.

Anyways, here's the code I'm using...

Code:
deadzone_limit = argument0;
att_acceleration = .07;
att_agility = .15;
att_maxSpeed = 7;
friction_ = .3;

//--------------------------------------------------------------------
//Get direction
desired_direction = point_direction(0, 0, xaxis, yaxis);

//Get the length
if (xaxis == 0 && yaxis == 0)
{
    //decelerate
    spd = lerp(spd, 0, friction_);  
}
else
{
    //increase speed
    spd += att_acceleration;
    //limit to max speed
    spd = clamp(spd, -att_maxSpeed, att_maxSpeed);
   
}

//Get the hspd and vspd
desired_hspeed = lengthdir_x(spd, desired_direction);
desired_vspeed = lengthdir_y(spd, desired_direction);

//--------------------------------------------------------------------
//New Inertia Code for Cutback Momentum
var _xd = desired_hspeed - hspeed;
var _yd = desired_vspeed - vspeed;
var _length = sqrt( _xd * _xd + _yd * _yd );
if ( _length > 0 )
{
    var _acceleration = min( _length, att_agility ) / _length;
    hspeed += _xd * _acceleration;
    vspeed += _yd * _acceleration;
    image_speed = 1;
}

//Control the sprite
image_speed = speed * .1;
if (speed < 0.5) image_index = 0;
 
Last edited:
Top