jsBin demo
(Use jQuery's .remove()
method once the bullet is at leftPosition === worldWidth
).
(I would do that all in Canvas, for better performance results, visuals and repainting, but here you go: )
I find a really bad idea to loop constantly uncached $()
class selector elements.
Create among other variables like...
var world = {$el:$("body"), width: $('body').width()};
var $player = $('#player');
var mousePosY = 0;
...an Array that will hold all the created Bullets
var allBullets = [];
to keep track of all the active bullets and to remove them.
Than create a Bullet Object with the bullet properties (with inner handlers for the position, color, shape, speed etc etc...) and append that Object to our Array of bullets and insert it into the DOM:
function Bullet() {
var obj = {
$el : $('<div/>',{'class':'bullet'}),
css : {top: 100, left:0}, // Start at left 0
speed : 10,
move : function() { // This method will be used inside the animation loop!
obj.css.left += obj.speed; // Advance Bullet
if(obj.css.left > world.width){ // Notice this!!!!
var i = allBullets.indexOf(obj); // !! Use of indexOf (xBr. support).
allBullets.splice(i, 1);
obj.$el.remove();
}else{
return obj.$el.css( obj.css );
}
}
};
allBullets.push( obj );
$('body').prepend( obj.$el );
return obj;
}
To remove the bullets (as you can see in the code above) simply:
var i = allBullets.indexOf(obj); // Find the index of that object inside Array
allBullets.splice(i, 1); // Remove it from Array
obj.$el.remove(); // Remove it from the DOM
Note that indexOf()
is introduced in ES5 and not present in old browsers. You might want to use a Polyfill or replace it with an object that will collect Bullets ID... (I'll not cover that topic in this answer).
Once the player clicks to "Fire" you simply create a new
instance of that Bullet like:
$("body").on('click', function(){
new Bullet(); // Create a new Bullet with all the properties, move etc.
});
and it will be immediately collected into the allBullets
Array.
To move the bullets you pass the the window.requestAnimationFrame :
function moveBullets(){
if(allBullets.length>0) // Only if we have bullets in Array!
for(var i=0; i<allBullets.length; i++) allBullets[i].move(); // Move it using
// his own method.
}
I don't see how's that bullet supposed to fly nicely? 20 by 20px every 200ms?
Also for animation purposes I would go with window.requestAnimationFrame
instead of setInterval
, to allow the browser dictate the repainting tempo.
// ::: FRAME RATE
window.requestAnimFrame = (function() {
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
function( callback ){
window.setTimeout(callback, 1000 / 60);
};
}());
// ::: ENGINE
(function engine() {
// ----- Insert here functions you want to loop in framerate:
moveBullets();
// -----
requestAnimFrame(engine); // request a new frame
})();
If you really want to use DOM element, I would also suggest to use enhanced CSS3 transitions and move the element with translate3d(x, y, z)
. You'll not have to move the element every tick, but the browser will move it for you! You can pre-calculate it trajectory in order to keep track of the element position in relation to the animation framerate and an internal clock. (I'll also not cover this examples in my answer.)
The above was for guidance, take a look at the result
in this DEMO (with random bullets speed)