3
\$\begingroup\$

The aim is for the player object to slow down and stop instead of just stopping dead. The following codes works ok when the player is not jumping, but gets stuck in an object if the player is in the air when they do it.

Left key released event:

if hsp = 0 exit;

hspeed = -3;
friction = 0.20;

if obj_Player.hspeed = 0 
{
hspeed = 0;
}

Right key released event:

if hsp = 0 exit;

hspeed = +3;
friction = 0.20;

if obj_Player.hspeed = 0 
{
hspeed = 0;
}

Horizontal collision code for interest:

if (place_meeting(x+hsp,y,obj_bound))
{
while(!place_meeting(x+sign(hsp),y,obj_bound))
{
    x += sign(hsp);
}
hsp = 0;
}

x += hsp;
\$\endgroup\$
1
\$\begingroup\$

So, the way I've implemented similar movement controls in the past is I assign the player to have an x and a y, as well as an xSpeed and ySpeed. X Speed is always constant while the player is holding down left or right, then slowly goes down to zero when they release. Then, instead of directly incrementing player x, you use x speed.

Doing this for both x and y should fix this problem, though if that's not the problem, more context would be appreciated.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Thanks for replying. I think the problem is that when the player releases the left/right key the code will move the character regardless because the collision check happened before the key release event. What I think I need to do is check on the key release if the extra movement will move the character past the start of a collision object and set a max movement distance of between the current location and the location of the object. Im not quite sure how to implement it. \$\endgroup\$ – Dave Jun 7 '14 at 10:21
  • \$\begingroup\$ An easy fix for that is checking after they move, and if they collide, move the player back out of collision either using an oldX/oldY combination or just move them backward a bit. \$\endgroup\$ – Aeolingamenfel Jun 8 '14 at 14:01
0
\$\begingroup\$

Lets break this down into a few cases while only considering movement in a single horizontal direct ion.

Case 1, the user presses and holds the horizontal movement key. In this case our movement is taken by adding the vector V to the objects position.

Case 2, the user releases the horizontal movement key. In this case our movement varies with respect to time since the key has been released. This means we need to parameterize our velocity vector V by time.

Lets modify V by V * F(x), where F(x) = sin(x). Now let x be a real number between 0 and pi/2. Now suppose we want the player to slow down over the course of 1s, so t is a real number between 0 and 1. Then x = pi/2 * t.

Psuedo code for this might be something like this...

func Update:    
  if (t > 0)
    player_vels.push_back(V * sin(pi/2 * t))    
    t -= deltaT


func UserInput:    
  if (horiz_key_press)    
    player_vels.push_back(V)    
    t = 0    
  else if (horiz_key_release)    
    t = 1

This is an example, not guarenteed to be most efficient. I encourage you to think over this.

| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

The best way to implement this would be through utilizing acceleration, which is linked to the controls, as opposed to using methods on button release. On every update loop, apply friction, then acceleration, then cap the speed. Assuming the user is holding down a movement key, acceleration should cancel out the friction and keep the user at maximum speed, but if the user releases the movement key, friction will apply every update until the character comes to a stop.

Example code:

update()
{
    acceleration = getAccelFromButtonsPressed()
    velocity = velocity - friction
    velocity = velocity + acceleration
    if (velocity > maxSpeed)
    {
        velocity = maxSpeed
    }
    position = position + velocity
}
| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.