Are you redrawing every time to the invisible canvas, or are you saving the data, and just pushing that to the screen? I'm not entirely sure if this is plausible for you situation, but take the event of a game like mario. The ground on the bottom can be drawn one time grabbing each tile from a tile sheet, and then you can save that bitmap data, so you cut out having to 'pick out' each tile, and just push that data to the screen. Any chance you have an example of what you're doing for your sprite\tile layer? I believe it can be a bit fast this way, but we may just not be on the same page.
I have 4096x4096 tiles 64x64 pixels each. I can't draw that to off screen canvas at once. I only draw tiles that are visible, and terain is mostly empty (some platform in the air), than I don't draw anything obviously.
My fastest code:
for (var y=y1; y>=y0; --y) {
var resultY = (0.5+
(level.topLeft.y - camera.position.y + camera.screen.height / 2 +
level.cellHeight + y * level.cellHeight-level.cellHeight)
)|0; // fast clip to int
for (var x=x1; x>=x0; --x) {
var tileImageNo = level.layers[z].cells.valueAt([x, y])-1;
if (tileImageNo==null || tileImageNo<=0) {
//nothing to do
} else {
ctxOnScreenCanvas.drawImage(
tiles[tileImageNo],
(0.5+
(level.topLeft.x - camera.position.x + camera.screen.width / 2 +
level.cellWidth + x * level.cellWidth- level.cellWidth)
)|0, // fast clip to int
resultY
);
}
}
}
I've also tried drawing to OffScreenCanvas in the loop, and then drawing that canvas to screen, but it was slower.
I could try drawing to off screen canvas only when player moves out off current off screen canvas, but that will trade small delay each turn into big delay every N turns, and that's even worse. But I'll try that.
Gotcha, my suggestion, might require too much change to be worthwhile, but won't hurt to say it. Here is the assumptions I am working off of:
- You have a background layer, lets just say it's a blue background
- A middle layer, lets say clouds that move as you move to the right
- And a tile layer, which draws the sprites, and the tiles of the maps
For the tile layer, we can break it down into two separate groups, animated sprites, and static sprites.
The static sprites, can be drawn to the offscreen canvas, and you get the imageData from that one time, and then push that data to the screen there after. Then the animated sprites will just be drawn to the on screen canvas every time. http://imgur.com/n6RFF The stuff that should be drawn to the offscreen canvas, then grab the image data has gray around it, and the animated sprites are in the green.
So for drawing the tiles of the map we only have to loop through the tile data, one time, and after that if the imgData remains valid (a separate flag) we can just push that imgData to the screen.
This would also allow drawing section of the screens on the offscreen canvas in chunks, and storing that draw to just be pushed to the screen at appropriate times.
I don't know if I explained it very well, I could probably through together a crappy little demo if you'd like.