I am working on a simple JavaScript based game using the canvas tag. As part of the game, I have several large sprite sheets (for example, 2816x768 and 4096x4864), each of which contains related animations for the character on the screen. When the game begins, the game simply has a game of idle animation. When the user presses the spacebar, I start playing another animation from a completely different page with the caption.
Here is the code that draws sprites:
Sprite.prototype.drawFrame = function(x, y) { ctx.drawImage(this.image, x*this.width, y*this.height, this.width, this.height, this.position[0], this.position[1], this.width, this.height); };
And here is the code that loads the images:
Stage.prototype.loadImage = function(src) { var image = new Image(); this.incAssets(); var stage = this; image.onload = function() { stage.decAssets(); } image.src = src; return image; }
The problem is that there is a delay of 1.5 seconds when the user presses the spacebar and when the frame from the new sprite sheet is really drawn. This is one time and does not affect the smoothness of the next animation. I already have sprite sheets preloaded with new Image and the game will not even start until all the relevant image.onload events have been fired, so I know that the browser does not wait for them to load. I went through JavaScript using the debugger in Chrome 17.0, and narrowed the delay for calling drawImage in context. The hardest part is that this delay is missing in Firefox 10.0.2, so this is a Chrome issue. It really breaks the game.
What am I doing wrong here? Is there a way to reduce this delay in Chrome?
Change I tried to draw the whole next frame as soon as it loaded, as suggested by Peter Wishart, but this had minimal effect. I also tried changing loadImage as follows:
Stage.prototype.loadImage = function(src) { var image = new Image(); this.incAssets(); var stage = this; image.onload = function() { ctx.drawImage(image, 0, 0); stage.decAssets(); } image.src = src; return image; };
This also showed no effect.
In fact, I found a solution, but it is terribly inefficient. It occurred to me that Chrome might try to do smart things with image memory after decoding it. If the image remains unused for a long time, and again this is just an assumption, Chrome will delete the decoded data from the memory and return it if necessary again. Typically, the decoding process takes an inconspicuous amount of time, but the large images that I use cause a very sharp drop in performance. Using this, I changed the drawing cycle to:
function draw() { var currentTime = new Date().getTime(); var deltaTime = currentTime - lastTime; lastTime = currentTime; var dt = deltaTime / 1000.0;
This solution really works, but, as I said, it seems like a terrible waste. I need to draw the entire frame of the next set of animations, just to save the decoded data in Chrome.
Are there any less wasteful and less hacker alternatives to this strategy?