Reputation: 3568
I'm creating a side-scrolling space-shooter in javascript. So far everything seems to be working well. However, there is an odd bug in the canvas rendering that I can't quite figure out (and is difficult to describe, so bear with me!)
I have a player that can shoot projectiles by clicking the left mouse button. When the projectile first leaves the player, there appears to be two of them for a brief second, until they eventually merge in to the one projectile. I'm not creating two, so this seems like an optical illusion (this is most evident if you fire a few projectiles in quick succession).
The really odd thing is, when I try and capture a screenshot of this happening, all looks fine. Can anyone figure out what's going on?
Player code including projectiles (full code in fiddle);
var Player = (function () {
// ------------------------------------------------------------------------------------------------
// PLAYER VARIABLES
// ------------------------------------------------------------------------------------------------
var w = 50;
var h = 50;
var x = 0;
var y = 0;
var projectiles = [];
// ------------------------------------------------------------------------------------------------
// BIND EVENTS TO THE GLOBAL CANVAS
// ------------------------------------------------------------------------------------------------
Canvas.bindEvent('mousemove', function (e) {
y = (e.pageY - Canvas.element.getBoundingClientRect().top) - (h / 2);
});
Canvas.bindEvent('click', function () {
createProjectile(50, (y + (h / 2)) - 10);
});
// ------------------------------------------------------------------------------------------------
// FUNCTIONS
// ------------------------------------------------------------------------------------------------
var createProjectile = function (x, y) {
projectiles.push({
x: x,
y: y
})
};
var update = function () {
for (var p = projectiles.length - 1; p >= 0; p--) {
projectiles[p].x += 10;
if (projectiles[p].x > Canvas.element.width)projectiles.splice(p, 1);
}
};
var render = function () {
Canvas.context.fillStyle = 'white';
Canvas.context.fillRect(x, y, w, h);
for (var p = 0; p < projectiles.length; p++) {
Canvas.context.fillStyle = 'red';
Canvas.context.fillRect(projectiles[p].x, projectiles[p].y, 5, 5);
}
};
// ------------------------------------------------------------------------------------------------
// Exposed Variables and Functions
// ------------------------------------------------------------------------------------------------
return {
update: update,
render: render
}
})();
Js Fiddle Demo HERE: https://jsfiddle.net/oqz204bj/
Based on @Pimskie's answer, It does indeed seem like an optical illusion - so my question now becomes, how could I reduce this effect? I plan on implementing a feature in the future that allows the player to switch weapons (where some of them would **actually* fire multiple projectiles) but I don't want this effect to remain for fear of confusion.
Upvotes: 0
Views: 218
Reputation: 463
yes it is an optical illusion. The reason it looks like there multiple squares when first fired is because your eyes are focused on the big static ship square. Once your eye starts to follow the movement path, then it looks more like a fluid square moving instead of a square being redrawn 60 or 30 times per second. hold a piece of paper or your hand up to your screen covering the left half of it. Focus on the piece of paper and fire a few shots. You'll notice that the shots seem to appear multiple, the same as when just fired. It's a matter of your mind seeing 3 different frames as the same one.
requestAnimationFrame depends on the frame rate of your browser and computer. In most cases that's 60fps. 60 to 70fps is the limit of most monitors, and so it doesn't make sense to try and go above that. HOWEVER you can create the illusion of a more fluid movement by having a trailing tracer effect on your projectiles. That would involve having 2 or 3 extra squares created behind each projectile that have less and less opacity.
Upvotes: 2
Reputation: 1871
My best guess it's an optical illusion indeed. Check this updated fiddle: https://jsfiddle.net/oqz204bj/1/
I removed one requestAnimationFrame
and replaced a other with a very slow setInterval
, just for demonstration. You can see only one bullet is created.
Upvotes: 2