gamer merch
gamer merch

Reputation: 93

How can I move objects along a certain angle in JavaScript?

So I have an integer variable, and it's supposed to represent the angle that I want this object to move along, it looks like this:

const Degree = 90

Now obviously we need a object to move in this angle, so we can easily draw this to the canvas.

const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
document.body.appendChild(canvas);
// ...
ctx.beginPath();
ctx.arc(0, 0, 3.75, 0, 2 * Math.PI);
ctx.fillStyle = 'black';
ctx.fill();

How can I move this little circle along the axis I set in the degrees variable?

I tried to implement John Pavek's code into my code, and the little pebble does not pop up. Here is my code:

const canvas = document.createElement("canvas");
    const ctx = canvas.getContext("2d");
    document.body.appendChild(canvas);
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    var keydown = false

    const kbd = {
      ArrowLeft: false, 
      ArrowUp: false, 
      ArrowRight: false,
      ArrowDown: false,
    };

    const noHoldDown = {
      Space: false,
    }

    const ship = {
      angle: 0,
      color: "white",
      x: canvas.width / 2,
      y: canvas.height / 2,
      width: 10,
      height: 12,
      drag: 0.9,
      accSpeed: 0.025,
      rotSpeed: 0.007,
      rotv: 0,
      ax: 0,
      ay: 0,
      vx: 0,
      vy: 0,
      rotateLeft() {
        this.rotv -= this.rotSpeed;
      },
      rotateRight() {
        this.rotv += this.rotSpeed;
      },
      accelerate() {
        this.ax += this.accSpeed;
        this.ay += this.accSpeed;
      },
      decelerate() {
        this.ax -= this.accSpeed;
        this.ay -= this.accSpeed;
      },
      shoot() {
        var circle = new MovableCircle();
        function DegreesToRadians(degrees) {
          return degrees * (Math.PI / 180);
        }
        setInterval(function() {
          ctx.beginPath();
          ctx.clearRect(0, 0, canvas.width, canvas.height)
          circle.draw();
          circle.x += Math.cos(DegreesToRadians(circle.direction)) * circle.speed;
          circle.y += Math.sin(DegreesToRadians(circle.direction)) * circle.speed;
        }, 1000 / 60)
      },
      move() {
        this.angle += this.rotv;
        this.rotv *= this.drag;
        this.vx += this.ax;
        this.vy += this.ay;
        this.ax *= this.drag;
        this.ay *= this.drag;
        this.vx *= this.drag;
        this.vy *= this.drag;
        this.x += Math.cos(this.angle) * this.vx;
        this.y += Math.sin(this.angle) * this.vy;
      },
      draw(ctx) {
        ctx.save();
        ctx.lineWidth = 3;
        ctx.translate(this.x, this.y);
        ctx.rotate(this.angle);
        ctx.beginPath();
        ctx.moveTo(this.height, 0);
        ctx.lineTo(-this.height, this.width);
        ctx.lineTo(-this.height, -this.width);
        ctx.closePath();
        ctx.strokeStyle = this.color;
        ctx.stroke();
        ctx.restore();
      }
    };

    function MovableCircle() {
          this.x = ship.x;
          this.y = ship.y;
          this.speed = 1;
          this.direction = convertToRadians(ship.angle);
        
          this.draw = () => {
            ctx.arc(this.x, this.y, 20, 0, 2 * Math.PI);
            ctx.fillStyle = 'white';
            ctx.fill();
          }
        }

    document.addEventListener("keydown", event => {
      if (event.code in kbd) {
        event.preventDefault();
        kbd[event.code] = true;
      }
    });

    function convertToRadians(degree) {
      if (((degree / Math.PI) * 180) > 360 || ((degree / Math.PI) * 180) < -360) {
        ship.angle = 0
        return (degree / Math.PI) * 180;
      } else {
        return (degree / Math.PI) * 180;
      }
    }

    document.addEventListener("keydown", event => {
      if (event.code in noHoldDown) {
        if (!keydown) {
          keydown = true;
          ship.shoot();
        }
      }
    });

    document.addEventListener('keyup', event => {
      if (event.code in noHoldDown) {
        keydown = false;
      }
    });

    document.addEventListener("keyup", event => {
      if (event.code in kbd) {
        event.preventDefault();
        kbd[event.code] = false; 
      }
    });

    (function update() {
      ctx.fillStyle = "black";
      ctx.fillRect(0, 0, canvas.width, canvas.height);  

      const shipActions = {
        ArrowLeft: "rotateLeft",
        ArrowUp: "accelerate",
        ArrowDown: "decelerate",
        ArrowRight: "rotateRight",
      };

      for (const key in shipActions) {
        if (kbd[key]) {
          ship[shipActions[key]]();
        }
      }
      ship.move();
      ship.draw(ctx);
      requestAnimationFrame(update);
    })();

Upvotes: 2

Views: 952

Answers (1)

John Pavek
John Pavek

Reputation: 2665

One common option for learning about canvas animations is using Algebra (sin/cos) to calculate the distance to add for each value. Here is a very simple, non interactive example.

const canvas = document.createElement("canvas");
canvas.height = 400;
canvas.width = 400;
const ctx = canvas.getContext("2d");
document.body.appendChild(canvas);


var circle = new MovableCircle();

setInterval(function() {
  // This is our "game loop", the easiest way, not the best way
  ctx.beginPath();
  ctx.clearRect(0, 0, canvas.width, canvas.height)

  circle.draw();

  circle.x += Math.cos(DegreesToRadians(circle.direction)) * circle.speed;
  circle.y += Math.sin(DegreesToRadians(circle.direction)) * circle.speed;

}, 1000 / 60)

function MovableCircle() {
  this.x = 10;
  this.y = 10;
  this.speed = 1;
  this.direction = 45;

  this.draw = () => {
    ctx.arc(this.x, this.y, 20, 0, 2 * Math.PI);
    ctx.fillStyle = 'black';
    ctx.fill();

  }
}

function DegreesToRadians(degrees) {
  return degrees * (Math.PI / 180);
}

Upvotes: 2

Related Questions