My projectile system not working, what's wrong with it, how can I fix it?

gamer merch

I'm making an asteroid shooter system, that can shoot projectiles where the player is facing, however, when you shoot (press space), the projectile does not move.

I've tried to add cosine and sine to the X and Y, but that obviously doesn't work. I tried adding print statements to see where it went wrong and it looks like the X and Y is just not incrementing at all. How can I make it so that it increments properly and exactly how I want it to?

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

Full code:

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

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() {
    projectileArray.push([this.x, this.y, this.angle])
  },
  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();
  }
};

document.addEventListener("keydown", event => {
  if (event.code in kbd) {
    event.preventDefault();
    kbd[event.code] = true;
  }
});
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);
  for (var i = 0; i < projectileArray.length; i++) {
    function MovableCircle() {
      this.x = projectileArray[i][0];
      this.y = projectileArray[i][1];
      this.speed = 1;
      this.direction = projectileArray[i][1];

      this.draw = () => {
        ctx.arc(this.x, this.y, 3.75, 0, 2 * Math.PI);
        ctx.fillStyle = 'white';
        ctx.fill();
      }
    }
    var circle = new MovableCircle();
    ctx.beginPath();
    circle.x += Math.cos(circle.direction) * circle.speed;
    circle.y += Math.sin(circle.direction) * circle.speed;
    circle.draw();
    console.log(circle.x, circle.y)
  }
  requestAnimationFrame(update);
})();

danh

I put so many quarters into Asteroids, I had contribute here! The problem stems from the persistence of projectiles: Rebuilding them at each turn of the update loop forgets any state change made in the prior iteration.

Projectiles should be first-class objects, held onto by either the game or the ship. Below, are two changes to the OP's otherwise fine script:

  1. A Projectile class, using basically the OP code:
function Projectile(x,y,speed,direction,duration) {
  Object.assign(this, {x,y,speed,direction,duration});
  this.draw = ctx => {
    ctx.arc(this.x, this.y, 3.75, 0, 2 * Math.PI);
    ctx.fillStyle = 'white';
    ctx.fill();
  }
  this.update = ctx => {
    ctx.beginPath();
    this.x += Math.cos(this.direction) * this.speed;
    this.y += Math.sin(this.direction) * this.speed;
    this.draw(ctx);
    this.duration--;
  }
  this.isDone = () => this.duration <= 0;
}

Functionally, the only thing I added was a duration, since I think I recall in the original that projectiles which don't hit anything eventually pop out of existence.

  1. Since the ship already has a projectile array, here, it's modified to hold projectile instances:

The shoot method changes to

  shoot() {
    let mySpeed = Math.sqrt(this.vx*this.vx + this.vy*this.vy)
    let bullet = new Projectile(this.x, this.y, 1+mySpeed, this.angle, 500);
    projectileArray.push(bullet);
  },

Side note: I think, in the original game, projectiles' speed was fixed to be greater than the top speed of the ship, but I don't remember clearly. In the above, I set projectile speed to +3 more than the ship's current speed. This is more physically correct (at sub-relativistic speeds :-)), but probably not accurate to the original.

And the draw method cleans up significantly, since we moved the state-forgetting projectile code into its own class

  ship.draw(ctx);
  for (var i = 0; i < projectileArray.length; i++) {
    let bullet = projectileArray[i];
    bullet.update(ctx)
  }
  projectileArray = projectileArray.filter(bullet => !bullet.isDone());

Side note: Javascript classes, starting around ES5/ES6 provide a big improvement in syntax. It's worth getting familiar with this.

Demo

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

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

const noHoldDown = {
  Space: false,
}

function Projectile(x,y,speed,direction,duration) {
  Object.assign(this, {x,y,speed,direction,duration});
  this.draw = ctx => {
    ctx.arc(this.x, this.y, 3.75, 0, 2 * Math.PI);
    ctx.fillStyle = 'white';
    ctx.fill();
  }
  this.update = ctx => {
    ctx.beginPath();
    this.x += Math.cos(this.direction) * this.speed;
    this.y += Math.sin(this.direction) * this.speed;
    this.draw(ctx);
    this.duration--;
  }
  this.isDone = () => this.duration <= 0;
}


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() {
    let mySpeed = Math.sqrt(this.vx*this.vx + this.vy*this.vy)
    let bullet = new Projectile(this.x, this.y, 3+mySpeed, this.angle, 500)
    projectileArray.push(bullet);
    // projectileArray.push([this.x, this.y, this.angle])
  },
  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();
  }
};

document.addEventListener("keydown", event => {
  if (event.code in kbd) {
    event.preventDefault();
    kbd[event.code] = true;
  }
});
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);
  for (var i = 0; i < projectileArray.length; i++) {
    let bullet = projectileArray[i];
    bullet.update(ctx)
  }
  projectileArray = projectileArray.filter(bullet => !bullet.isDone());
  requestAnimationFrame(update);
})();

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

Can't figure out what's wrong with my if statement in JavaScript [Update Sept 1st It appears my for loop is running twice, how do I fix?]

What is wrong with my break command? It's not working

My program is supposed to list player's scores under their team names but prints the wrong ones. How can I fix this?

How can I enable/disable a JTextField with a JCheckBox? or what's wrong with my code?

how can i fix my javascript calculation which is not working?

What exactly does my logcat mean, and how can I fix it?

What is the Unity HUD and how can I install it on my system?

Understanding what went wrong with my git merge, and how can I fix it?

I am encountering multiple "error: missing return statement" errors on a couple of my methods. What have I done wrong and how can I fix it?

How can I fix my Debian's /etc/network/interfaces?

Why is JavaCC not working on my mac and how can I fix it?

My sound stopped working today, how can I fix it?

How can I fix my developer's console?

What's wrong with my codes? When I enter string then the program is stop working. How can I keep work the program even enter strings

what wrong with my system?

How can I find out what's wrong with my RAM?

How can I fix my dotfiles that prevent pulseaudio from working?

Can you fix it or tell me what's wrong with this? I want to get Navigacio upper

Onclick event refuses to work, what's wrong with it, and how to I fix it?

My var_dump stop working, how can i fix it?

How can I log what is going wrong in my controller

What's wrong with this code and how can I show the data on screen

I have these 2 tonnage calculators. The first one is working great. How can I fix the second one? Is something wrong with my Javascript?

How can I set a lifespan for a projectile?

I made my navbar fixed and now it's transparent no matter what I style the background color to be. How can I fix this?

How can I find what video driver is in use on my system?

How can i fix segmentation fault in my code and what is the process I should follow to fix this in the future?

How can I fix my Binary Search code not working as expected?

How can I fix my website's minimization issue?