Moving an Object in relation to another

I (naively?) assumed that you could just set an object’s position in relation to another like this: this.rect2.x = this.rect1.x - 100; But that results in the second object lagging behind. Meaning that the distance between them is sometimes less than 100 and sometimes more than 100. What is going on here? Example:

import { Scene } from 'phaser';

export class Game extends Scene {
  private rect1!: Phaser.Physics.Arcade.Sprite; // Physics sprite
  private rect2!: Phaser.GameObjects.Rectangle; // Regular rectangle
  private speed: number = 1000; // Speed in pixels per second

  constructor() {
    super({ key: 'Game' });
  }

  create() {
    // Enable arcade physics
    this.physics.world.setBounds(0, 0, this.scale.width, this.scale.height);

    // Create the first rectangle as a physics sprite
    this.rect1 = this.physics.add.sprite(100, 200, 'rectangleTexture'); // Placeholder texture
    this.rect1.setDisplaySize(50, 100); // Set size
    this.rect1.setTint(0xff0000); // Red tint

    // Create the second rectangle
    this.rect2 = this.add.rectangle(0, 0, 50, 100, 0x0000ff); // Blue rectangle

    // Initial position for rect2
    this.updateRect2Position();

    // Enable arrow key inputs
    this.input.keyboard.on('keydown', this.handleKeyDown, this);
    this.input.keyboard.on('keyup', this.handleKeyUp, this);
  }

  update() {
    // Keep updating the position of rect2 based on rect1's position
    this.updateRect2Position();
  }

  private handleKeyDown(event: KeyboardEvent) {
    if (event.key === 'ArrowRight') {
      this.rect1.setVelocityX(this.speed); // Move right
    } else if (event.key === 'ArrowLeft') {
      this.rect1.setVelocityX(-this.speed); // Move left
    } else if (event.key === 'ArrowUp') {
      this.rect1.setVelocityY(-this.speed); // Move up
    } else if (event.key === 'ArrowDown') {
      this.rect1.setVelocityY(this.speed); // Move down
    }
  }

  private handleKeyUp(event: KeyboardEvent) {
    if (
      event.key === 'ArrowRight' ||
      event.key === 'ArrowLeft' ||
      event.key === 'ArrowUp' ||
      event.key === 'ArrowDown'
    ) {
      this.rect1.setVelocity(0); // Stop movement when keys are released
    }
  }

  private updateRect2Position() {
    this.rect2.x = this.rect1.x - 100; // Set rect2's X position relative to rect1
    this.rect2.y = this.rect1.y - 20;  // Set rect2's Y position relative to rect1
  }
}

:wave:

Game objects with a body get a final physics position after update(). So you can either

1 Like

Thanks, I’ve looked at the examples and apparently it comes down to replacing
this.rect2.x = this.rect1.x - 10;
this.rect2.y = this.rect1.y - 10;
with this:
Phaser.Display.Bounds.SetCenterX(…);
Phaser.Display.Bounds.SetBottom(…);

That fixes the issue, although I don’t really understand why.

The Bounds functions aren’t important, those are just a convenient way to align to the body’s geometry. It’s which position you’re reading during update() that’s important.

The physics engines moves all the bodies before scene update(), then it moves all the game objects attached to those bodies after scene update(), then the scene renders all the game objects. So during scene update(), this.rect2.body coordinates are accurate but this.rect2 coordinates are not — they’re a step behind until later.

1 Like