Home > OS >  Circular movement when user input left/right arrow
Circular movement when user input left/right arrow

Time:05-06

I am trying to achieve left/right circular movement inside my main circle. I have class Circle and Ball. Circle is responsible for drawing a "circle" where I am placing my Ball, that is moving inside.

class Circle {
  constructor(gameWIdth, gameHeight) {
    this.gameHeight = gameHeight;
    this.gameWIdth = gameWIdth;
    this.circX = 100;
    this.circY = 100;
    this.radius = 55;
  }

  draw(context) {
    context.beginPath();
    context.fillStyle = "white";
    context.arc(
      this.gameWIdth / 2,
      this.gameHeight / 2,
      100,
      0,
      Math.PI * 2,
      false
    ); // outer (filled)
    context.arc(
      this.gameWIdth / 2,
      this.gameHeight / 2,
      this.radius,
      0,
      Math.PI * 2,
      true
    ); // outer (unfills it)
    context.fill();
  }
}

class Ball {
  constructor(gameWIdth, gameHeight) {
    this.gameWIdth = gameWIdth;
    this.gameHeight = gameHeight;
    this.ballX = this.gameWIdth / 2;
    this.ballY = this.gameHeight / 2;
    this.vx = 0.03;
    this.radians = Math.PI * 2;
  }

  draw() {
    context.beginPath();
    context.fillStyle = "green";
    context.arc(this.ballX, this.ballY - 67, 15, 0, Math.PI * 2, false);
    context.fill();
  }

  update(input) {
    if (input.includes("ArrowLeft")) {
      this.ballX = this.ballX   Math.cos(this.radians) * -2;
      this.ballY = this.ballY   Math.sin(this.radians) * -2;
    } else if (input.includes("ArrowRight")) {
      this.ballX = this.ballX   Math.cos(this.radians) * 2;
      this.ballY = this.ballY   Math.sin(this.radians) * 2;
    }
    //circular move
    this.radians  = this.vx;
    this.ballX = this.ballX   Math.cos(this.radians) * 2;
    this.ballY = this.ballY   Math.sin(this.radians) * 2;

    console.log(this.ballX, this.ballY);
  }
}

class Input {
  constructor() {
    this.keys = [];
    window.addEventListener("keydown", (e) => {
      if (
        (e.key === "ArrowLeft" || "ArrowRight") &&
        this.keys.indexOf(e.key) === -1
      ) {
        this.keys.push(e.key);
      }
      console.log(e.key, this.keys);
    });
    window.addEventListener("keyup", (e) => {
      if (e.key === "ArrowLeft" || "ArrowRight") {
        this.keys.splice(this.keys.indexOf(e.key), 1);
      }

      console.log(e.key, this.keys);
    });
  }
}

class Game {
  constructor(context, width, height) {
    this.context = context;
    this.width = width;
    this.height = height;
    this.circle = new Circle(canvas.width, canvas.height);
    this.ball = new Ball(canvas.width, canvas.height);
    this.input = new Input();
  }

  draw() {
    this.circle.draw(context);
    this.ball.draw(context);
  }

  update() {
    this.ball.update(this.input.keys);
  }
}

const game = new Game(context, canvas.width, canvas.height);

const drawCanvas = () => {
  context.fillStyle = "#000";
  context.fillRect(0, 0, canvas.width, canvas.height);
};

const animation = () => {
  drawCanvas();
  game.draw();
  game.update();

  requestAnimationFrame(animation);
};

animation();

For now I am inputing left right arrow press and i do want my ball to change direction based on arrow press. I was playing with

 if (input.includes("ArrowLeft")) {
      this.ballX = this.ballX   Math.cos(this.radians) * -2;
      this.ballY = this.ballY   Math.sin(this.radians) * -2;
    } else if (input.includes("ArrowRight")) {
      this.ballX = this.ballX   Math.cos(this.radians) * 2;
      this.ballY = this.ballY   Math.sin(this.radians) * 2;
    }

where * -2 should revert movement, but it is not working as I thought it will Here is codesandobx I do get that this can be a bit more complicated than I anticipated

CodePudding user response:

Usually you make something change direction by modifying its speed. Here I change the value of this.vx to be either positive or negative.

I also changed the calculations for ball position slightly, I just used numbers like 75 and 66 that seemed to be approximately correct, but you might need to change those for your needs.

  update(input) {
    if (input.includes("ArrowLeft")) {
      if (this.vx > 0) this.vx *= -1;
    } else if (input.includes("ArrowRight")) {
      if (this.vx < 0) this.vx *= -1;
    }
    //circular move
    this.radians  = this.vx;
    this.ballX = Math.cos(this.radians) * 75   this.gameWIdth / 2;
    this.ballY = Math.sin(this.radians) * 75   this.gameHeight / 2   66;
  }

CodePudding user response:

Adding to ballX and ballY is the wrong approach here.

In general, getting a point on a circle, like your ball's position, looks like this.

x = centerX   Math.cos(angle) * radius
y = centerY   Math.sin(angle) * radius

In your case, the only thing that changes is angle. So this is the only thing you need to update.

update() {
  if (input === 'ArrowLeft') {
    velocity = -0.03
  } else if (input === 'ArrowRight') {
    velocity = 0.03
  }
  angle  = velocity
}

draw() {
  const x = centerX   Math.cos(angle) * pathRadius
  const y = centerY   Math.sin(angle) * pathRadius
  ctx.arc(x, y, ballRadius, 0, Math.PI * 2)
}

It's good to think about the minimum information your program needs to keep track of. Here, you only need to store angle, and then you can calculate x and y when you need them.

  • Related