2
\$\begingroup\$

I've made a 2D tile-based game with DOM/Javascript. For each level, the map data is loaded and parsed, then lots of tiles ( elements) are drawn onto a larger "map" element. The map is inside of a container that hides overflow, so I can move the map element around by positioning it absolutely. Works a treat on desktop browsers, and my iPad 2.

My problem is that performance is really bad on iPad 1. The performance hit is directly related to all the tile elements in my map, because when I remove or reduce the number of tiles drawn, performance improves. Optimizing my collision detection loop has no effect.

My first thought was to batch groups of tiles into containers, then hide/show them based on proximity to the player, however this still causes a huge hiccup when the player moves and a new group of tiles is displayed (offscreen). Actually removing the out-of-sight elements from the DOM, then re-adding them as necessary is no faster.

Anyone know of any tips that might speed up DOM performance here? My map is 1920 x 1920 pixels, so as far as I know should be within the WebKit texture limit on iOS 5/iPad. The map is being moved with CSS3 transforms, and I've picked all the other obvious low-hanging fruit.

\$\endgroup\$
1
  • \$\begingroup\$ This is maybe not what you want but have you considered using canvas to draw your tiles instead of DOM elements? Depending how you wrote your game it could be quite easy to switch from one rendering method to another, and then make some tests. The problem with DOM elements/CSS is that there is a lot of things happening "under the hood" when manipulating them. That could explain the poor performance you described. Also: if you implement rendering using canvas, for extra performance be sure to draw only differences between frames and not the whole new state (technique know as "redraw regions"). \$\endgroup\$
    – tigrou
    Commented Nov 21, 2012 at 0:14

2 Answers 2

3
\$\begingroup\$

The trick is to only use enough tiles to fill your viewport - that's also how classic consoles (like the NES) simulated huge/wide backgrounds and maps. This is also the reason why these consoles (especially the NES) had sometimes colors overlapping from one side of the screen to the other (as it's essentially continuous memory being wrapped).

For example, if your viewport is 320 pixels wide and one tile has a width of 32 pixels, then you use 11 columns to render the Background/tiles (10 tiles just for the width and another column to fill the gap on the left or right).

How so? Easy: No matter how you move the tiles, there'll always be a maximum of 11 tiles be visible next to each other. If your viewport is exactly at the borders of tiles, you see ten tiles. Move them a bit to the left or right and an eleventh tile appears on the other side.

So rather than creating, deleting and/or moving tiles around, just move them to have proper tile borders and update their content accordingly. This way 32px wide tiles will move by a Maximum of 32 pixels in one direction.

This sounds a bit complicated, but it's actually rather easy.

I've had to look around a bit to find some sources without having to draw something myself (rather late already).

Look for the section Tiled Backgrounds and Levels, which will show you an image of a tiled background. They use a different width, so they always show 12 or 13 tiles horizontally. Just consider how the grid would move. Once a full row of tiles disappears on either side, all tiles are moved back by one row and their images are updated accordingly.

Also just to mention it: I'm not sure about the iPad's capabilities, but shouldn't you be able to use the canvas element? I'm sure it would be more performant.

\$\endgroup\$
0
0
\$\begingroup\$

I suggest you use canvas, and then prerender the tile map. This is a process of rendering large chunks of your tile map to off-screen images, which are then blitted to the screen. This can dramatically redice the number of image draws, which should increase performance. We've managed to get some pretty good performance from iPad 1's using this technique.

BTW: the playcraft engine will do this for you automatically (plug). It's in open beta and is free. http://playcraftlabs.com

\$\endgroup\$
1
  • \$\begingroup\$ Thanks for the suggestion, but a different implementation is not very relevant. \$\endgroup\$
    – endemic
    Commented Nov 27, 2012 at 20:42

You must log in to answer this question.

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