I am making a movement engine for my top-down 2D game, but I got stuck trying to solve the following problem:
- The player can move using the arrow keys, which accelerate you in the respective directions. There is friction so you stop moving after releasing the keys, though not instantly.
- When you hold two perpendicular keys, you accelerate in this 45° direction the same speed as you would on one axis
- There is a maximum speed which above you cannot accelerate by walking, this also limits your maximum walking speed, obviously. You can get knocked away, and thus exceed this speed however.
- If you move faster than max. walkspeed, you can slow down faster if you hold keys in the opposite direction(s)
Pseudocode for the first point, without friction:
gameTick(){
tempX += LeftKeyHeld ? -1 : 0;
tempX += RightKeyHeld ? 1 : 0;
tempY += UpKeyHeld ? -1 : 0;
tempY += DownKeyHeld ? 1 : 0;
ratio = 0.71;
if( |tempX| == |tempY| ) {
tempX =tempX* ratio;
tempY =tempY* ratio;
}
player.x += tempX;
player.y += tempY;
}
I can solve the friction (getting the length of the movement vector, reducing it by the friction, projecting it back with the same x:y ratio), however, I can’t wrap my head around getting the maxSpeed done.
I tried a solution of not allowing the player to walk at all when above maxSpeed, but this violates point 4. Also, it had the nasty side-effect, that when you moved at MaxSpeed to the left, and started pressing down, the movement direction didn’t, or barely changed.
Then I started thinking about numerous products, differences and other stuff with the vectors, but I mostly couldn’t follow it anymore or ran into early problems.
So in conclusion, could someone explain a system which fulfills all the points above, or point to an article which explains how a system like this could be implemented? Don’t worry about suggesting something complex, I can grasp even difficult concepts given some time.
Thanks for your help!
Sorry for not letting you think about this for more than a day, but I managed to solve it, and it ain’t two lines of code. (Though still thanks for everyone for the ideas)
Because I’m lazy and tired, I won’t change it to pseudocode, except the following two methods:
And the code (java):
Could be shorter, could be a bit more optimised, but it works. I hope this’ll help anyone who stumbles upon this problem in the future.