Skip to content Skip to sidebar Skip to footer

Moving A Triangular Ship In A Canvas Game In Plain Js

I am trying to move a triangle in the direction which the triangle is rotated by. When I press the key to move it, it doesn't move, but when I rotate it, its center of rotation shi

Solution 1:

Nice attempt! This is one of those things that takes some experimentation to get right.

A few suggestions:

  • Encapsulate all relevant data and functions for the ship in one object. This keeps things organized and easy to understand and will simplify your logic and reduce bugs significantly. This makes entity state and rendering functions much easier to manage.
  • Avoid calling ship movement functions directly from the key event callback. Doing so can result in jerky, inconsistent behavior when the keyboard re-triggers. This callback should simply flip key flags, then let the event loop take care of calling the relevant functions based on those flags.
  • Use requestAnimationFrame instead of setInterval for most animations.
  • Something like angle = 2; is too rigid (this may have been temporary). We need to use += here and introduce a velocity variable (and, ideally, acceleration too) for realistic rotation.
  • Math.PI / 180 * angle for Math functions isn't strictly necessary. We can use angle directly in radians. If your game depends on setting angles with degrees, then you can add a conversion function.
  • Use variables for acceleration and velocity if you want the movement to feel realistic. In the sketch below, I've added a few of these, but it's not a definitive approach and is intended to be tweaked to taste.

Here's a simple example of all of this in action. There is much room for improvement, but it should be a decent starter.

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

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

const ship = {
  angle: 0,
  color: "white",
  x: canvas.width / 2,
  y: canvas.height / 2,
  width: 10,
  height: 15,
  drag: 0.9,
  accSpeed: 0.04,
  rotSpeed: 0.012,
  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;
  },
  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.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();
  }
};

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

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

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

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

Post a Comment for "Moving A Triangular Ship In A Canvas Game In Plain Js"