My city building game, WidgetCity, displays the city as a table, each cell of a table representing one tile.
The tile map is done purely using just CSS, and CSS classes. The map is also scrollable.
How is this all done?
As always, there is more than one approach to doing this type of a tile map.
The most obvious approach is to chop down each graphic in the game to one tile sized small images. Then, each of the small images is applied using a background image to each of the tiles. For example, an industrial zone is 3×3 tiles, so this would need 9 small images which each get applied to specific tiles to build the whole industrial zone.
This small image approach can be done in two ways: Using a CSS style to put the image as the background, or by inserting an img tag into the cell and changing its src.
There’s a lot of different graphics for just a single type of zone: Indstrial zones for example have different graphics for different land valued zones and different populations on the zone. The above approach would work, but it would require a lot of work to chop each big graphic into small ones and also each image would have to follow a specific naming scheme so it could be applied correctly.
Another approach is similar to what is used in CSS sprites: Each larger graphic is contained in a single file, and the image is then mapped into the small cells using CSS’ background-position.
The chosen approach
The game defines a set of CSS naming rules which are used in the stylesheets, so the code in the game can easily apply styles without having to use special cases all over the place. Each cell’s className attribute consists of several classes:
- An “offset class”, which is used to place the big image into the small cell: for example, “o31x1” is the bottom right corner of a 3×3 tile – o for offset, 3 for 3×3, 1×1 for the X and Y offset from the center of the tile. The game knows which position of the tile it’s laying out, so it simply adds the respective offset class into the cell’s className.
- The main “graphic class”, such as “indbuilding” for an industrial building.
- A “land value/population class”. This is used to choose which graphic of the building to actually display, such as a small rowhouse, or a big skyscraper. These look like v0p1, where v0 means land value 0 and p1 means population 1
There are also some other special classes:
- nopower class is applied to zone center cells if the zone doesn’t have power. This shows the little no power indicator
- For roads and powerlines, there are classes called up, right, down and left, which are applied in following cases: if you have a road, and there’s a section of road above it, the class “up” is given to the bottom road cell, and the class “down” is given to the upper. If there’s also a road to the left of the upper cell, it gets “left”. In the stylesheet, there are combinations of these four classes, which apply the correct road and powerline graphics to the cells.
The scripting side of things
The classes are also applied only when something changes – the game keeps track of what classes are in the cells, as re-applying the class incurs a performance penalty.
What about canvas?
Lastly, some words on an alternative to using a table: the HTML5 canvas element.
While it may seem “wrong” to use table to do something like this, I think it’s in certain ways better than canvas. Firstly, you get better performance, and second, you need less code.
The benefits of using canvas would be that you could provide smooth scrolling. With a table it would be very tricky if not completely unfeasible. Canvas would also allow zooming or other effects.