LWJGL - Diagonal Movement Speed Limitation Issues (using Math.sqrt(2))

Hey everyone,

I’m using a system where, at each tick/update, the keyboard is checked for state changes (keys being pressed and released). The player is moved according to what keys are pressed (W for up, A for left, etc.) Recently I was trying to limit the speed of diagonal movement and followed instructions from one post, telling me to move the player by

speed / Math.sqrt(2);

. This DID change the speed, but in an unexpected fashion. The player moved slowest when moving up and right, and fastest when moving down and left. Is this a rounding issue or something different?

My code: http://pastebin.com/GBaK435S

Thanks,

Will

It’s actually speed * (sqrt(2) / 2)

Which is equal to speed * sqrt(0.5)

I changed the formula to speed * sqrt(0.5). It had no noticeable effect on the movement speed.

Uh, I have no direct solution for this, but usually I just work with vectors:


// Very simplified class, if you use LWJGL / LibGDX use their Vector classes
public class Vec2 {

  // Make them immutable or not, it's up to you
  public final float x, y;

  public Vec2(float x, float y) {
    this.x = x;
    this.y = y;
  }

  // These are all the methods we need ^^
  public float length() {
    return Math.sqrt(x * x + y * y);
  }

  public Vec2 div(float v) {
    return new Vec2(x / v, y / v);
  }

  public Vec2 mul(float v) {
    return new Vec2(x * v, y * v);
  }

  public Vec2 normalize() {
    return div(length());
  }
}

So now that we have your Vec class, let’s implement the player logic:


float speed = 4f;
Vec2 velocity = new Vec2(0, 0);

// in game logic:
velocity = new Vec2(0, 0); // reset velocity
if (/*pressed left*/) {
  velocity = new Vec2(velocity.x - 1, velocity.y);
} 
if (/*pressed right*/) {
  velocity = new Vec2(velocity.x + 1, velocity.y);
}
if (/*pressed up*/) {
  velocity = new Vec2(velocity.x, velocity.y - 1); // plus or minus depending on y up or y down
}
if (/*pressed down*/) {
  velocity = new Vec2(velocity.x, velocity.y + 1);
}
velocity = velocity.normalize().mul(speed);
// The velocity vector is always going to have the length "speed". 
// Normalize makes the vector have the length 1, mul() does the obvious with the length.
x += velocity.x;
y += velocity.y;
// done.

@mattheus23 I tried that, yields the same results.

VIDEO: https://www.youtube.com/watch?v=3Jj7pU0o5hU

Can you please show me the code?

http://pastebin.com/5iwrM4yz

How are you applying your velocity? I think this maybe due to not using delta time.

The velocity is applied each update (which is limited to 60 per second) when the player is rendered relative to the x and y integers. The same was done with the old method, when this.move(int, int); was called.

Accidental medal there :confused:

Anyways, you shouldn’t be using integers for storing the state of the position of players. Use [icode]float[/icode]s or [icode]double[/icode]s for that purpose and only cast them to integers the moment you need to render your character.

Why not fix the velocities in terms of ppu (Pixels Per Update)? I think the varying speed is due to [icode]Math.sqrt()[/icode] is a native method. Not sure though.

Do you manipulate [icode] this.x [/icode] or [icode] this.y [/icode] in any way before rendering? Obviously this action triggers a lot more moving in a positive direction than in a negative direction. The only explanation for that is that maybe the keyboard handler is biased for up and right…

Did you use an else if ladder to disable and reenable key presses and releases? Can you please show the code for the press and release handler?

Or even better, use the resultant velocity.


float vx, vy;

if (Keyboard.isKeyDown(Keyboard.KEY_LEFT))
{
    vx -= 4;
}

if (Keyboard.isKeyDown(Keyboard.KEY_RIGHT))
{
    vx += 4;
}

if (Keyboard.isKeyDown(Keyboard.KEY_UP))
{
    vy += 4;
}

if (Keyboard.isKeyDown(Keyboard.KEY_DOWN))
{
    vy -= 4;
}

this.x += vx;
this.y += vy;

Hope this helps.