3
\$\begingroup\$

I am trying to recreate asteroids, but I need the ship to rotate based on user input. I have w,a,s,d keys set to change the [pos] of the ship by 1 in the corresponding direction, but now, I need to spawn the sprite in the appropriate angle based on that, and I am running into two main issues:

  1. how to correctly spawn the image over and over (right now, I can get a copy of the ship to spawn in the exact cetner of the context, rotated at one angle, ALONG with the real ship that I control. I do not know why this is.)
  2. How to calculate the angle of rotation in radians based on the ship's pos.

I have included the entire ship class, but the most relevant code will be the draw method at the bottom.

const Utils = require('./utils.js');
const MovingObject = require('./moving_object.js');
const Bullet = require('./bullet.js');

function Ship(posOptions) {
  let options = {game: posOptions['game'], color: 'green', pos: posOptions['pos'], radius: 20, vel: [0,0], wrappable: true, type: 0}
  MovingObject.call(this, options);
  this.faceingDir = [0,0];
}

Utils.inherits(Ship, MovingObject);

Ship.prototype.relocate = function () {
  this.pos = this.game.randomPosition();
  this.vel = [0,0];
};

Ship.prototype.power = function (impulse) {
  // console.log(this.vel);
  this.vel[0] += impulse[0];
  this.vel[1] += impulse[1];
};

Ship.prototype.fireBullet = function () {
  let bulletVel = [(this.vel[0] * 4), (this.vel[1] * 5) - 10];
  let bullet = new Bullet({pos: this.pos, vel: bulletVel, game: this.game});
  this.game.bullets.push(bullet);
};

Ship.prototype.move = function () {
  if (this.isWrappable) {
    this.pos = this.game.wrap(this.pos);
  }
  this.pos[0] += this.vel[0];
  this.pos[1] += this.vel[1];
  this.vel[0] *= .98;
  this.vel[1] *= .98;
};

Ship.prototype.draw = function (ctx) {
  const img = new Image();
   img.onload = function () {
    ctx.drawImage(img, this.pos[0]-this.radius, this.pos[1]-this.radius)

  };
  img.src = 'galaga_ship.png';
  ctx.drawImage(img, this.pos[0]-this.radius, this.pos[1]-this.radius);
  var x = 800 / 2;
  var y = Math.floor(605 / 2);
  var width = img.width;
  var height = img.height;
  ctx.translate(x, y);
  ctx.rotate(10 * Math.PI / 180);
  ctx.drawImage(img, -width / 2, -height / 2, width, height);
  ctx.rotate(-10 * Math.PI / 180);
  ctx.translate(-x, -y);
};
\$\endgroup\$
2
\$\begingroup\$
  1. You should load your image during initiation, not in the draw function. The draw function should be run over and over again, every "tick" of the game. The problem with your loading algorithm is that it takes time for the image to load, so if your draw function is called many times per second (which it should be), your game is already malfunctioning.

  2. One way to applying a transformation (e.g. rotation) to only one object is like this answer, which is to implement a system that stores transformation matrices on a "stack". You will need to do research on matrix multiplication; translation, scale, and rotation matrices; and javascript stacks (very easy to understand; see this answer).

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ JavaScript already has a built-in matrix stack system in the form of ctx.save() and ctx.restore() \$\endgroup\$ – Bálint Dec 23 '17 at 15:32
-1
\$\begingroup\$

The problem is that you draw the image three times in your code. Put all the drawing code in img.onload and remove the extra, unwanted image drawing:

  const img = new Image();
  img.onload = function () {
    //ctx.drawImage(img, this.pos[0]-this.radius, this.pos[1]-this.radius)
    var x = 800 / 2;
    var y = Math.floor(605 / 2);
    var width = img.width;
    var height = img.height;
    ctx.translate(x, y);
    ctx.rotate(10 * Math.PI / 180);
    ctx.drawImage(img, -width / 2, -height / 2, width, height);
    ctx.rotate(-10 * Math.PI / 180);
    ctx.translate(-x, -y);
  };
  img.src = 'galaga_ship.png';

The illustrative fiddle, just in case: https://jsfiddle.net/simoroshka/ercds9cu/

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.