I wrote a Sim City clone in JavaScript

Tags:

This is why I haven’t been updating lately: I have been working on a Sim City clone, written purely in HTML, CSS and JavaScript!

The game is called WidgetCity, and I’m participating with it in the Betavine Widget Competition 2009.

The game was designed to run in Opera Widgets mode, but it also works in Firefox – only downside is that you can’t save your city. Get the widget here, or if you don’t have Opera, you can play the game here. There is also a help file.

Continue reading to find out more details about the game’s inner workings and such!

The basic stuff

The game is quite similar to the original Sim City – it actually uses some graphics from it, thanks to the fact that the original Sim City source code has been released under GPL, which was a good thing because I’m not the world’s greatest graphics artist!

As per the requirements of the Betavine competition, the game had to run in a mobile phone. This is why the game is so small: It had the screen size limitations of a Nokia N95, which is something like 260×240 pixels.

The game was originally supposed to be based on the canvas tag, which I’ve used on my past widget projects like TankWar Online. However, this turned out to be a bit of a problem on the phone, and only one of the problems caused by the phone.

The N95 is actually a quite good device: It has the hardware to run games with 3D graphics, etc. etc., but it’s completely unable to run JavaScript code at a reasonable pace. Using canvas, the game ran absurdly slow!

In the end, I had to resort to using old-school DHTML style trickery: The game area is simply a table, with some CSS classes applied to each of the cells in JavaScript.

Under the surface

Under the relatively simple looking graphics of the game ticks a quite serious simulation engine.

The game engine simulates a lot of things, and it had quite serious performance implications which required a lot of JavaScript optimization. You can read more about the problems and optimizations encountered in development in Optimizing JavaScript for extreme performance and low memory consumption.

The sim engine calculates at least the following:

It keeps a track of what’s built in each tile in the game. This data is then used to calculate things like how much residential/commercial/industrial demand there is.

For some specific tile types like residential zones, the game calculates desirability and traffic: Is this area of the map “good enough” to build a large apartment block, and can the people living here drive to some destination?

The desirability calculations are based on a bunch of other large calculations: Pollution, crime rate, land value, population density. Each of these has to be calculated again and again during the progress of the game to keep the city developing.

Traffic itself uses a quite “dumb” algorithm: It just attempts to drive in a random direction along the roads until it reaches a destionation, which works okay for the simple calculations involved.

The large calculations like pollution and land value calculations require going over all the tiles in the map to determine what’s built where, and then based on those some values are calculated.

You can probably see why the performance wasn’t so great, as there is a lot of stuff going on in the background!

Issues during development

Most of the problems during the game’s development were caused by the really poor JavaScript performance on the target device.

For example, the original map size in the game was 300×300 tiles. This would cause the phone to immediately run out of memory when attempting to play, so I had to reduce the size to 128×128, which still quite good is nowhere near as large as the original.

Note that the original 300×300 map did run perfectly fine on my desktop and on my HTC Touch Diamond. It would probably have had major performance implications in the future, though…

Additionally, I originally planned to use canvas. However, I had to scrap that and use a table as the speed of canvas was just way too poor. You may be interested in reading how the WidgetCity map is rendered using a table and some CSS.

The JS performance in general seemed quite awful: Just looping over the 128×128 map was slow. If you did nothing else than just iterate over each of the 16 384 tiles, it would already have a small impact, which you wouldn’t have with most other languages, or even with a bit newer JavaScript engines.

Another memory related problem surfaced closer to finishing the development: The N95 would run out of memory when saving the game.

Saving and loading are a quite vital feature of the game, so this was a critical issue. However, Remco Lanting came up with a nice idea to possibly fix it: Save the map in smaller parts. The idea worked flawlessly. Remco also helped with testing the game and with some ideas, so a big thanks to him.

What’s missing?

While the game is quite ready and playable now, there are various things that I would’ve liked to add to it, but due to lack of time I couldn’t.

These include being able to lay rail, being able to get nice maps that display things like crime rate in different parts of the map, some user interface improvements, and of course disasters like nuclear plant meltdowns!

One particularily cool thing I would have liked to have was the ability to overlay data like crime rates on top of the city. I wrote a post earlier on how you can get Photoshop layer style stuff in JavaScript, which could have been a nice way to do this.

I don’t know if I will be adding all those, as I have various other things to do now that the game is released, like actually writing blogposts again. :)

However, if you’d like, you are free to modify the game. I’ve decided to release it under GPL, similar to the graphics from the Micropolis project used in it. If you would like to play with the source code, just download the widget, rename the file to .zip and unzip it like normal.