[SOLVED] 8 Direction Sprites, ensure last direction

G

GrandFree

Guest
So basically I have a character that moves in 8 directions (each direction has a sprite).

Let's say I'm moving in the top-left direction. I want it so when I stop moving, if the last general direction I was going in was top-left, then set the sprite to the top left sprite.

The problem is, if I don't release both the up and left keys in the same frame, then the character's last sprite will be set to either left or up. Aesthetically, it just feels strange when my player stops moving and he's not facing the direction that my brain knew he was facing when I released both keys. I'd like it so the last sprite is set to the last general direction I was going in for the longest period of time.

What's the best way to combat this? Should I just measure how long a certain direction was held for? Or is there a better way?

Code:
if(keyboard_check(ord("A"))) {
    sprite_index = spr_move_left;
  
    if(keyboard_check(ord("W"))) {
        sprite_index = spr_move_leftup;
    }
  
    else if(keyboard_check(ord("S"))) {
        sprite_index = spr_move_leftdown;
    }
}

else if(keyboard_check(ord("D"))) {
    sprite_index = spr_move_right;
  
    if(keyboard_check(ord("W"))) {
        sprite_index = spr_move_rightup;
    }
  
    else if(keyboard_check(ord("S"))) {
        sprite_index = spr_move_rightdown;
    }
}

else if(keyboard_check(ord("W"))) {
    sprite_index = spr_move_up;
  
    if(keyboard_check(ord("A"))) {
        sprite_index = spr_move_leftup;
    }
  
    else if(keyboard_check(ord("D"))) {
        sprite_index = spr_move_rightup;
    }
}

else if(keyboard_check(ord("S"))) {
    sprite_index = spr_move_down;
  
    if(keyboard_check(ord("A"))) {
        sprite_index = spr_move_leftdown;
    }
  
    else if(keyboard_check(ord("D"))) {
        sprite_index = spr_move_rightdown;
    }
}
 
Last edited by a moderator:
L

lord_berto

Guest
wait i typed a reply to you but its actually broken nvm.
 
Last edited by a moderator:
L

lord_berto

Guest
You mean the solution was incorrect?
hey not sure if you have fixed it but I high recommend you look into how to change the sprite image according to
to what direction your player travels to, not by what keys he/she presses. lets say, if direction == 0 spr = right. if direction == 90 spr = up.
this way. even if ur player slows down to 0 speed. it is still considered that he/she is traveling 90 degrees up, there for the image will retain its angle of walking.
 

CMAllen

Member
Change the way you reset movement on a given axis back to 0. Right now, when you release a key, that axis is set to zero instantly. What's missing is inertia. Inertia is what carries motion through even after the force exerting it is removed. Friction then reduces that motion to zero at a set rate. By allowing inertia and friction to do their thing, you no longer need to release the movement keys in the exact same frame -- the direction of travel is based on the angle of the active axis instead of the keys being actively pressed, and the angle of the active axis does not immediately reset back to 0 when its associated keys are released. Even primitive 2d games like the original Super Mario Bros had crude/simplistic implementations of inertia and friction.

This approach also allows for more natural movement, with your character accelerating into and out of walking. As a general rule of thumb, I found about 1/2 a second enough time for a person-sized object to stop moving from a leisurely stroll (1 second from a jog, 2 seconds from a sprint).

Also, though it's personal preference, I prefer the summing approach to input checks. Each axis has 3 input states: 1, 0, and -1. If the value of that axis input is not zero, then it is active, and the 'speed' on that axis should increment, based on its sign and rate of acceleration, until it has reached its maximum value. If the value of the input axis is 0, then it is inactive and the 'speed' of that axis should be reduced, based on friction, back to zero.
 
Last edited:

Bentley

Member
Going off of @CMAllen 's post, you could use your direction to set your sprite.
Ex:
switch (direction)
{
case 0: spr_player_right:
case 45: spr_player_top_right;
etc.
}
Not sure if this is a good solution, but just in case it helps, I threw it out.
 
G

GrandFree

Guest
Change the way you reset movement on a given axis back to 0. Right now, when you release a key, that axis is set to zero instantly. What's missing is inertia. Inertia is what carries motion through even after the force exerting it is removed. Friction then reduces that motion to zero at a set rate. By allowing inertia and friction to do their thing, you no longer need to release the movement keys in the exact same frame -- the direction of travel is based on the angle of the active axis instead of the keys being actively pressed, and the angle of the active axis does not immediately reset back to 0 when its associated keys are released. Even primitive 2d games like the original Super Mario Bros had crude/simplistic implementations of inertia and friction.

This approach also allows for more natural movement, with your character accelerating into and out of walking. As a general rule of thumb, I found about 1/2 a second enough time for a person-sized object to stop moving from a leisurely stroll (1 second from a jog, 2 seconds from a sprint).

Also, though it's personal preference, I prefer the summing approach to input checks. Each axis has 3 input states: 1, 0, and -1. If the value of that axis input is not zero, then it is active, and the 'speed' on that axis should increment, based on its sign and rate of acceleration, until it has reached its maximum value. If the value of the input axis is 0, then it is inactive and the 'speed' of that axis should be reduced, based on friction, back to zero.
Completely forgot about this thread, sorry about that!

Using friction seems to work! Have to give it a bit of leeway to get it just right but yeah this is great!
 
Top