8-speed constant speed of movement in all directions, how to get the angle of movement from the direction keys?

The top of the morning to people on different surfaces of the earth.

Problem: how to get the direction angle from the arrow keys.

Preamble: The standard way to move in the main game from top to bottom is to add to x and / or y from the update method depending on the direction.

if (moveUp) playerY -= delta * speed; if (moveDown) playerY += delta * speed; if (moveLeft) playerX -= delta * speed; if (moveRight) playerX += delta * speed; 

This is elegant for a 4-directional movement (I believe) because no matter which key combinations are pressed, the direction of movement will be consistent. For example, pressing the up-down-left move left, both up and down, is canceled. But when moving diagonally, the steps will be too large. If the speed is 20, the left movement moves to the left by 20 per second, and up will increase by 20 per second. But the up-left movement will move a little over 28.24 per second.

The solution here is to use cos and sin to get new x and y, which is easy as soon as you know the angle:

 playerX += Math.cos(Math.toRadians(angle)) * delta * speed; playerY -= Math.sin(Math.toRadians(angle)) * delta * speed; //y is inverted 

But for me, at least, a new problem arises: what angle? In my KeyListener, I set / clear a boolean value for each arrow key. I can use a massive set of if statements:

 if (moveUp) angle = 90; if (moveDown) angle = 270; if (moveRight) angle = 0; if (moveLeft) angle = 180; if (moveUp && moveLeft) angle = 135; if (moveUp && moveRight) angle = 45; if (moveDown && moveLeft) angle = 225; if (moveDown && moveRight) angle = 315; //...etc... for all combinations 

In life, I cannot find a sexual way to get the angle of motion from which direction keys are pressed. It seems to me that this should be a common problem, game design 101, but an intensive search on Google did not lead me to anything (more difficult because it is difficult to put the problem into words). In all the examples, either they simply preserved the functionality diagonally - faster (as in my first fragment), either know the angle in advance (i.e., move in the direction of the mouse), or are two-dimensional scrollers.

Of course, is there a sexy matte way (or something else) to sort out a few lines? Or am I approaching this completely wrong?

Edit: code after response (as indicated by korona below):

 double x=0, y=0; if (moveLeft) x -= 1; if (moveRight) x += 1; if (moveUp) y -= 1; if (moveDown) y += 1; double length = Math.sqrt(x * x + y * y); if (length != 0) { x /= length; y /= length; x *= delta*speed; y *= delta*speed; playerX += x; playerY += y; } 
+4
source share
1 answer

Use a two-dimensional vector. Something like that:

 movement = new Vector2D(); if (moveLeft) movement.x += 1; if (moveRight) movement.x -= 1; if (moveUp) movement.y -= 1; if (moveDown) movement.y += 1; movement.normalize(); // Caps the movement vector at a length of one, even when it at an odd angle movement *= desiredMovementSpeed * frameDeltaTime; // Plug in suitable values here // FIXME: Do some collision detection here, probably playerX += movement.x; playerY += movement.y; 

I assume that a suitable 2D class is available to you. If not, normalizing a vector is as simple as dividing all its components by length, as such:

 length = sqrt(this.x * this.x + this.y * this.y); this.x /= length; this.y /= length; 
+9
source

All Articles