Fixing diagonal movement speed (FIXED)

Firstly, I apologize if this question seems dumb, I’ve only been coding in processing for about 2 months.

I’m trying to create a top-down game, and as of right now, I have a blue square (player) that gets chased around by a red square (enemy). I have fully working movement and collision, but the problem is that the diagonal movement speed is faster than the straight movement speed. I know this is happening because my diagonal code calls both boolean values I have for the two directions for making a diagonal movement, which causes it to move both sideways and up/down simultaneously. It’s something with the Pythagorean theorem, that I don’t understand. Under this paragraph is my code, with the menu portion I have cut out.

boolean[] keyDwn = new boolean[4];

final int _keyA = 65;
final int _keyW = 87;
final int _keyS = 83;
final int _keyD = 68;

boolean gameStart = false;
 
Player p;
Enemy e;

void setup(){
  size(1000,1000);
  p = new Player();
  e = new Enemy();
  keyDwn[0] = false;
  keyDwn[1] = false;
  keyDwn[2] = false;
  keyDwn[3] = false;
}

void draw(){
    game();
}

void game(){
  background(0);
  moveObj();
  p.collide();
  p.render();
  e.update();
  e.collide();
  e.render();
}

void keyPressed(){
  if (keyCode == _keyA) {
    keyDwn[0] = true;
    println("key A pressed = ", keyCode);
  }
  if (keyCode == _keyW) {
    keyDwn[1] = true;
    println("key W pressed = ", keyCode);
  }
  if (keyCode == _keyS) {
    keyDwn[2] = true;
    println("key S pressed = ", keyCode);
  }
  if (keyCode == _keyD) {
    keyDwn[3] = true;
    println("key D pressed = ", keyCode);
  }
}

void keyReleased(){
  if (keyCode == _keyA) {
    keyDwn[0] = false;
  }
  if (keyCode == _keyW) {
    keyDwn[1] = false;
  }
  if (keyCode == _keyS) {
    keyDwn[2] = false;
  }
  if (keyCode == _keyD) {
    keyDwn[3] = false;
  }
}



void moveObj() {
  if (keyDwn[0]) p.x -= 7.5;
  if (keyDwn[1]) p.y -= 7.5;
  if (keyDwn[2]) p.y += 7.5;
  if (keyDwn[3]) p.x += 7.5;
}

class Player{
  
  float x = 500;
  float y = 500;
  
  void player(float x, float y){
    this.x = x;
    this.y = y;
  }
  
  void collide(){
    if(p.y < 50){
      p.y = 50;
    }
    if(p.y > height-50){
      p.y = height-50;
    }
    if(p.x < 50){
      p.x = 50;
    }
    if(p.x > width-50){
      p.x = width-50;
    }
  }
  
  void render(){
    fill(0,0,255);
    rect(x,y,100,100);
  }
}

class Enemy{
  float x = 250;
  float y = 250;
  
  void enemy(float x, float y){
    this.x = x;
    this.y = y;
  }
  
  void collide(){
    if(((x+25.1 > p.x-50 && x-25.1 < p.x+50) && (y-25.1 < p.y+50 && y+25.1 > p.y-50))){
      p.x = 500;
      p.y = 500;
      x = 250;
      y = 250;
      println("CATCH X");
    }
  }
  
  void update(){
    if(x+25 < p.x-50){
      x+=2;
    }
    if(x-25 > p.x+50){
      x-=2;
    }
    if(y+25 < p.y-50){
      y+=2;
    }
    if(y-25 > p.y+50){
      y-=2;
    }
  }
  
  void render(){
    fill(255,0,0);
    rect(x,y,50,50);
  }
}

I read online it has to do with normalizing vectors, but that was for GODOT and I had no clue what any of it meant. Can anyone help me out?

https://www.Reddit.com/r/processing/comments/bshqa8/comment/eor5epo/

1 Like

Unfortunately, that code has the same error as mine. It goes faster when diagonally, but slower when in a straight direction.

1 Like

Instead of keeping a boolean array for each key, store an int array that is one when pressed and zero when not. You can then compute your player velocity as

vel = new PVector( keyDwn[RIGHT] - keyDwn[LEFT], keyDwn[DOWN] - keyDwn[UP] )

where RIGHT, LEFT, UP, and DOWN are whatever index you use for those keys.

But you want to scale the velocity down if it has any variation of both x and y as non-zero. So:

if( vel.x*vel.x + vel.y*vel.y > 1 ) vel.mult( 0.707 );

where 0.707 is 1 / sqrt(2). That is, we scale it down by the length of the diagonal of a square.

It’s just an optical illusion. :eyeglasses:

Just make sure width & height are the same, and also both Player objects have same speed v:

// ...

static final int W = JAVA? 600 : 580;
static final int H = JAVA? 600 : 580;

// ...

static final byte[] DIAMS = { 50, 40 }, SPDS = { 4, 4 };
  • I’ve positioned 1 circle at top left, and the other top right.
  • 1 of them I went straight down, and the other diagonally down.
  • Both reached the bottom at the same time!
  • Same thing if I make the test from left to right.

If the straight down and the diagonal reach the bottom at the same time, then the diagonal one must be travelling at a faster speed. That’s exactly the problem @Np3 is trying to solve.

Essentially, no matter what direction your UI derived velocity is pointing, you want to normalize it and then multiply it by your desired speed to create the final velocity vector that you then add to your position.

When moving along the axes, the length is 1, but when moving along any of the diagonals, the length is sqrt(2), so we divide by that amount to normalize it.