While in my experience such projects are rarely ever considered finished, I would like to at least get the following done:
- Be able to create a randomly generated city within a set of parameters.
- To draw the city from an isometric perspective, at several levels of zoom.
- Be able to create all textures and detail for the buildings and landscape procedurally, that is no external resources (images/sounds etc.) will be imported to the program.
- Finally, to provide a automatic camera panning routine, and possible add a basic amount of animation (long term).
Procedural generation of cities is not a particularly new idea. Models with deep complexities can already can be found [PDF], supporting very organic road structures, population densities etc. Very little of that detail transfers particularly well to the pixel art world, for example curves/circles are notoriously difficult to draw realistically by hand, let alone by computer. For that reason, in this project I will be sticking to a very simple grid pattern, one that is not wholly unrealistic: many US cities today have a grid-like structure, particularly in the city centres.
Grid layouts are also much friendlier to program. The code will essentially store the city in a two dimensional array of grid squares, typical of many of the early simulation games (many of which are a big influence on the project). This lends itself well to an Object Orientated approach, such as that below.
This way, the data describing the cities composition is completely separate from the rendering process, allowing multiple levels of zooming (and possibly rotation?).
While drawing the basic shapes for the city shouldn't be too challenging, adding detail and textures will be a challenge. Some textures only need to be generated once then used repeatedly, such as road and grass tiles; building textures will vary greatly and will some can be reused, they will generally depend on factors such as height, type of building, and other factors. Also early experiments with Java's TexturePaint object suggest that it will not be flexible enough for the job, meaning a custom isometric texture renderer may have to be implemented.
The basic idea behind using an isometric view is to give the appearance of a 3D image on a 2D plane (i.e. the screen). The definition is basically that the each axis of projection follows the same scale, i.e. there is no perspective, meaning that the angle between all axes is the same (120°).
However, if we actually apply these angles to pixel art, it is more problematic. We have tan(30) ≈ 0.577, which means for every two pixels in the x-direction, we must move 1.155 in the y-direction! These clearly must be integer values if we are dealing with pixels on a screen, so we change the angle slightly so that we get a 1:2 ratio.
While we could in theory draw in a true isometric projection, it would require anti-aliasing to avoid looking horrible, and part of the whole pixel art philosophy is the idea of clean and crisp outlines; it is a style of digital art devoid of the smoothed, Photoshop processed feel that is more common today.
Of course other types of line can be used in isometric pixel art (to great effect), but it is generally advisable to stick to integer ratios for their gradients. A good example of this may be found in Rhys Davis' authoritative "The Complete Guide to Isometric Pixel Art", he describes a family of lines that work particularly well (see right).
This historic moment marks the start of Pixeville, my latest programming project. Inspired by Shamus Young's Pixel City, I have decided to try and create a procedurally generated city in an isometric pixel art style.
Having grown up loving classic isometric games such as Rollercoaster Tycoon and Transport Tycoon (see below, now available from the open source project OpenTTD), it seems the perfect challenge. The aims of the project are to have a arbitrarily large city generated at random, along with random textures and detail, and possibly eventually basic animation. As with all such projects, it will probably get turned into a screensaver eventually, but that is a long way off.
I'm writing the app in Java for the time being (as that's what I know best) but I am considering a C++ port eventually for the screensaver etc. You can keep track of developments on my Google Code project page.