1
\$\begingroup\$

I've been messing around with HTML5 for quite some time now but this is something that I guess I haven't figured out how to handle well yet. I'm sure there's an extremely easy solution and I just haven't opened my eyes to it but anyway.

The problem is thus: I have an HTML5 canvas on which I've loaded image tiles using a function (called once on page load) which sets up an image object called imageObj, and on imageObj.onload, it draws the image that I want it to draw at the specific coordinates.

Now, I generally always run my main canvas game code in a setTimeout that runs at 30 frames per second. I have a separate function which checks what keys have been pressed and stores them in an array (to account for multiple key presses), and if arrow keys are pressed, then global variables that store the player's x and y position are incremented/decremented accordingly.

Now, in the setTimeout loop, here is where i draw a small rectangle with the x and y coordinates as that of the player x-and-y variables. However here is where I have the problem.

I do not refresh my canvas in the sense, I do not clear the screen or put a new black background covering the screen at the beginning of each frame, because then I would have to reload the tilemap and that's incredibly slow on my localhost, and would be even more so online. Furthermore, since I do not clear the screen, the rectangle of the player is leaving a trail of rectangles behind it (i.e, all previous instances of its position have a rectangle in its place)

How do I handle this? How do I manage dynamic objects over the tile map and refreshing the canvas without having to constantly reload the tile map? (or reloading the tile map in some smart way. I believe there are certain methods such as drawing the next frame beforehand or as such; I'm not too sure)

Edit: I'd rather not use any third party apis or libraries or game engines, bit of a purist that way. Also, just occurred to me, what if I had 2 canvases back to back? One with the tile map and the other containing the objects?

\$\endgroup\$

2 Answers 2

4
\$\begingroup\$

You can solve this problem by layering multiple <canvas> elements over each other. When you erase on one canvas, the canvas below will not be affected and be visible through the pixel you erased and thus are now transparent.

But... why do you have to reaload your tile image from the hard drive to draw a new screen? Why can't you keep the image in memory? That seems like a design flaw to me.

\$\endgroup\$
4
  • \$\begingroup\$ Thank you for your quick response! I've only recently started to work with images in HTML5, so I am not aware of how to keep the image stored in memory. Do elaborate on this! \$\endgroup\$
    – user26073
    Feb 8, 2013 at 9:53
  • \$\begingroup\$ @user26073 Don't re-create an image on each frame, just reuse the ones you've loaded on init. \$\endgroup\$ Feb 8, 2013 at 10:11
  • \$\begingroup\$ @user26073 You usually load an external asset as an Image object which you store in a variable. When you want to draw the image, you check if it is already loaded, and when it has, you call context.drawImage with this image. When you need more details I would recommend you to open a new question with your current image loading and drawing code. \$\endgroup\$
    – Philipp
    Feb 8, 2013 at 10:50
  • \$\begingroup\$ Oh, yep. It's what I've been doing, just not the right way. Thank you for your help! \$\endgroup\$
    – user26073
    Feb 8, 2013 at 11:05
0
\$\begingroup\$

What you should do is not to refresh the whole canvas and all tiles, because as you reported, it will be slow, but only redraw tiles behind player (which normally is a small area unless player is half screen size).

Every time a actor (eg: player, enemy) is moved on the tilemap, call a function that will invalidate region where the actor was. That region will be repainted later by main drawing function (by calling the tile drawing function for specific tiles). note : if tilemap drawing function is really slow (even for a few tiles) you can also store a copy of full, original tiles rendering in another canvas. to redraw tiles to a specific region on main canvas, use that hidden, duplicate canvas.

For more info about this technique search canvas dirty rectangle on google for some code and tutorials.

Note : this technique is not new and have been used by lots of 2D games (eg: DOS) when drawing is slow (eg : no hardware acceleration). it is also how macromedia flash works.

\$\endgroup\$
1
  • \$\begingroup\$ This is a rather interesting/unconventional method (atleast in my opinion) to go about this. Worth great experimentation. Thanks a lot for sharing this! \$\endgroup\$
    – user26073
    Feb 8, 2013 at 14:30

You must log in to answer this question.

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