0
\$\begingroup\$

I have multiple canvases placed on top of each other for different layers (background, game objects, foreground). I was expecting this to allow me to have the background and foreground update at a lower frame rate, because they use either simple animations or static images. But currently, I can't really do that, because all layers still adjust to the player camera (the game camera centers to the movable player). In other words, I still have to redraw the foreground and background in 60fps to smoothly adjust to the camera movement, which seems excessive, since nothing on the canvas is changing that fast.

Is there a less expensive way to move a whole canvas (or everything on the canvas) compared to constantly redrawing the whole context with new offsets? This is for situations where everything on the canvas stays the same. And in case there's no better alternative, is using putImageData() for the whole canvas and moving it going to be more efficient than redrawing each image with new offsets?

\$\endgroup\$

1 Answer 1

0
\$\begingroup\$

You could make semitransparent canvases larger than the page viewport size, draw the entire canvas area, then move the canvases for camera/parallax using CSS transforms.

You would still have to redraw a canvas whenever the real visible area reaches the edge of the larger already-drawn area, if your world is not finite (and even if it is, drawing the entire area might be too expensive or take too much memory to store all the pixels).


Note: That recommendation is based on your canvas being a 2D canvas, (which I assume since you mentioned using putImageData()). If instead you were using a WebGL canvas, then the best option would be to just redraw every frame, possibly putting predrawn layers into WebGL textures. In that case, you're having the GPU do all the work, which is the same work that CSS transforms and multiple canvases would tell the browser's compositor to tell the GPU to do.

\$\endgroup\$
2
  • \$\begingroup\$ Thanks for the suggestion, that makes sense. I was hoping there's a good solution within the canvas context (to avoid dealing with DOM stuff), but I'll try to implement that and see if it causes any other issues. But yeah, it will probably greatly reduce processing, especially when it comes to something like hundreds of raindrops. \$\endgroup\$
    – Batash
    Commented Feb 1, 2022 at 19:43
  • \$\begingroup\$ @Batash If you were using WebGL in your canvas, then it would make sense to do the drawing every frame (possibly as individual objects or possibly as a texture) instead of using multiple canvases, and that would open up a lot of possibilities for both efficient and fancy drawing. However, if you're not already using WebGL I wouldn't recommend adding that learning experience while you've already got a game in project — there's a lot of details to learn there. (I added a note to my answer about this, since someone else looking reading might be in a different situation.) \$\endgroup\$
    – Kevin Reid
    Commented Feb 1, 2022 at 20:42

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .