Reputation: 941
I have an animation for a game that I am working on that won't seem to repeat. When the space bar is pressed, it triggers an event that "shoots" a circle to the top of a canvas. The problem is that when the key is pressed again it will not initiate the animation. Here is the sample code that I wrote:
var canvas, ctx,
spaceKey = false,
upKey = false,
downKey = false,
canvas = document.getElementById('canvas'),
ctx = canvas.getContext('2d'),
shotX = 150, shotY = 280;
function loop() {
if (spaceKey) shoot();
}
function keyDown(e) {
if (e.keyCode == 32) spaceKey = true;
}
function keyUp(e) {
if (e.keyCode == 32) spaceKey = false;
}
function shoot() {
setTimeout(function() { if (shotY > 0) {
ctx.clearRect(shotX-5,shotY-5,600,20);
ctx.beginPath();
ctx.arc(shotX, shotY,4,0,Math.PI * 2, false);
ctx.fillStyle = "yellow";
ctx.fill();
ctx.closePath();
shotY = shotY - 1;
shoot();
} else
ctx.clearRect(shotX-5,shotY-5,600,20);
}, 100);
}
(function init() {
setInterval(loop, 10);
document.addEventListener('keydown', keyDown, false);
document.addEventListener('keyup', keyUp, false);
})();
//init();
The reason I use keyUp
and keyDown
is because I have other functions that use different keys. This code was modified to show only this feature. To make it easier to see what I'm talking about, I created a JSFiddle. The other features I have are similarly structured and work, the only difference being that its duration isn't directly controlled by a key press.
Upvotes: 2
Views: 208
Reputation: 1185
You only have one "bullet".
Your bullets should be separate objects that are instantiated on shoot()
.
The way that I usually handle "particles" is to create a singleton object to store each instance and update all of them in the main loop.
Here's a simple Bullet object:
function Bullet(){
this.x = 150;
this.y = 280;
this.velX = 0;
this.velY = -1;
this.update = function(){
this.y += this.velY;
};
this.draw = function(){
ctx.beginPath();
ctx.arc(this.x, this.y,4,0,Math.PI * 2, false);
ctx.fillStyle = "yellow";
ctx.fill();
ctx.closePath();
};
};
And here is a BulletRenderer singleton that handles the bullets:
BulletRenderer = function(){
var bullets = [];
this.push = function(bullet){
bullets.push(bullet);
};
this.render = function(){
for (var i in bullets){
if (bullets[i].active){
bullets[i].update();
bullets[i].draw();
} else {
delete bullets[i];
}
}
};
return this;
}();
In the example I'm just clearing the canvas each frame. The shooting mechanism acts like a laser right now. Personally I would change this behavior.
Upvotes: 2
Reputation: 8966
I don't find your code much re-usable. You should consider using objects to represents the entities on the canvas. I've created simple code which does your job, but it is also not much re-usable (though you can re-use it to create a simple entity like the ball you created). Check this jsFiddle.
The problem with your code is, when that yellow ball reaches the to of the screen, the shotY
is 0, then you erase the ball from the screen, but don't reset the shotY
and don't redraw the ball at its home (original position).
I've created a simple Ball
object to get this done-
function Ball() {
this.x = 150;
this.y = 295;
}
Ball.prototype.draw = function(newx, newy) {
ctx.clearRect(this.x-5,this.y-5,600,20);
newx = newx || this.x;
newy = newy || this.y;
this.x = newx; this.y = newy;
var ball = this;
ctx.beginPath( );
ctx.arc(ball.x, ball.y,4,0,Math.PI * 2, false);
ctx.fillStyle = "yellow";
ctx.fill();
ctx.closePath();
}
Ball.prototype.shootUp = function() {
var ball = this;
inter = setInterval(function () {
if(ball.x <= 0) clearInterval(inter);
ball.draw(ball.x, ball.y-20);
}, 100);
}
and modified your shoot
function -
function shoot() {
var currentBall = new Ball();
currentBall.draw();
currentBall.shootUp();
}
And once again, this was just a simple example. You can make a lot of improvements in it. First of all, you should have an input engine to manage all the inputs. Then you should have a generic entity class to represent all the objects you have on the canvas. Like the Ball
. And finally you should have a game engine to bind all those things.
Upvotes: 2