Details of Lander's object types and the object map
Most of the objects in Lander live on the ground - in fact, the only aspects of the game that happen above ground are the player's ship, the particles system and falling rocks. Everything else is either landscape, or on the landscape.
In this article we take a look at the way that Lander populates its landscape with 3D objects, using the object map and the different object types.
The object types
----------------
Before we can talk about the object map, we need to talk about object types. There are 12 main object types, numbered from 0 to 11, though type 0 is never used. Adding 12 to an object type gets us the type for that object when it is destroyed, so type 5 is a gazebo, for example, and type 17 is the object type for a destroyed gazebo. Destroyed objects are drawn with clouds of smoke particles rising up from the detritus.
The different object types are defined in the objectTypes table, which maps object types to object blueprints. Each object type has an associated object blueprint, though different types can share the same blueprint.
The available object types are as follows:
Type | State | Object blueprint | Object |
---|---|---|---|
0 | Intact | objectPyramid | Pyramid (unused) |
1 | Intact | objectSmallLeafyTree | Small leafy tree |
2 | Intact | objectTallLeafyTree | Tall leafy tree |
3 | Intact | objectSmallLeafyTree | Small leafy tree |
4 | Intact | objectSmallLeafyTree | Small leafy tree |
5 | Intact | objectGazebo | Gazebo |
6 | Intact | objectTallLeafyTree | Tall leafy tree |
7 | Intact | objectFirTree | Fir tree |
8 | Intact | objectBuilding | Building |
9 | Intact | objectRocket | Rocket |
10 | Intact | objectRocket | Rocket |
11 | Intact | objectRocket | Rocket |
12 | Destroyed | objectRocket | Smoking but intact rocket (unused) |
13 | Destroyed | objectSmokingRemainsRight | Smoking remains (bends to the right) |
14 | Destroyed | objectSmokingRemainsLeft | Smoking remains (bends to the left) |
15 | Destroyed | objectSmokingRemainsLeft | Smoking remains (bends to the left) |
16 | Destroyed | objectSmokingRemainsLeft | Smoking remains (bends to the left) |
17 | Destroyed | objectSmokingGazebo | Smoking remains of a gazebo |
18 | Destroyed | objectSmokingRemainsRight | Smoking remains (bends to the right) |
19 | Destroyed | objectSmokingRemainsRight | Smoking remains (bends to the right) |
20 | Destroyed | objectSmokingBuilding | Smoking remains of a building |
21 | Destroyed | objectSmokingRemainsRight | Smoking remains (bends to the right) |
22 | Destroyed | objectSmokingRemainsLeft | Smoking remains (bends to the left) |
23 | Destroyed | objectSmokingRemainsLeft | Smoking remains (bends to the left) |
Objects 0 and 12 (the pyramid) are not used anywhere, and the objectTypes table contains an extra entry for object type 24 that is also never used. On top of this, there are two additional 3D objects in the game - the player's ship and the rock - whose blueprints are defined in the objectPlayer and objectRock tables, but these do not have assigned object types, as they can't be placed on the object map. Instead, they are always spawned above ground level.
As noted, the objectTypes table links to the blueprints for each object. Some types share the same blueprints, so object types 1, 3 and 4 are all identical small leafy trees, for example. However, when destroyed, the smoking remains of type 1 bend to the right (as object type 13 uses the right-leaning blueprint), while the smoking remains of types 3 and 4 bend to the left (as types 15 and 16 use the left-leaning blueprint).
The object map
--------------
The shape of the landscape in Lander is the same from game to game, as it is generated using the same procedural approach for every game, but with the exception of the three rockets along the right edge of the launchpad, the game's objects are different every time. This random approach is courtesy of the PlaceObjectsOnMap routine, which is called at the start of each new game to populate the landscape with up to 2048 objects (though in practice there are far fewer than this).
In order to store the details of which objects live where on the landscape, the game contains an object map that maps landscape coordinates to the objects that live there. The object map (stored at objectMap) contains one byte for each tile on the landscape. This byte determines the type of object (if any) that appears on that tile, where objects are trees, buildings, rockets and so on.
A byte of &FF in the object map indicates that there is no object on that tile, while a value of 0 to 23 indicates that the tile contains an object of that type (though as noted above, values of 0 and 12 are not used).
There can be only one object on each tile, and the object is placed at the tile corner. If you look at the screenshot again, you can see that all ground-based objects are drawn on tile corners:
The object map covers an area of 256 x 256 tiles, and each object is placed on the front-left corner of the corresponding tile. If we fly beyond the edge of the object map in-game, the object map repeats in all directions, even though the landscape shape doesn't repeat. So if we fly directly into the screen, then every now and then we'll come across three rockets all in a row, and we know that we've just wrapped around to the start of the object map once again.
Incidentally, the DrawObjects routine contains a check to ensure that objects don't suddenly appear in the sea in these repeated instances of the map. Because the landscape in Lander is infinite but the object map is finite and gets repeated every 256 tiles in each direction, objects that appear on land in one instance of the object may well appear in the sea in another instance, so this check prevents that from happening.
The object map shares the same coordinate system as the rest of the game, so it uses a right-hand coordinate system, with the x-axis going from left to right, the y-axis going down the screen, and the z-axis going into the screen.
Because the purpose of the object map is to record object positions on the map, it does not include altitude data, so the y-axis is ignored (as the altitude of an object on the landscape is determined by the landscape altitude at that point). You can think of the object map as a paper map that is draped over the landscape, and whose longitude and latitude values map to the x-axis and z-axis respectively.
The origin of the object map is at the front-left corner of the launchpad, and we can talk about coordinates on the map in terms of tiles as (x, z) coordinates. So a map coordinate of (7, 1) is 7 tiles to the right and 1 tile into the screen, starting from the front-left corner of the launchpad; in this example, that's the coordinate of the front rocket of the three alongside the launchpad when we start the game.
The object at coordinate (x, z) is stored at byte offset &zzxx within objectMap, so the rocket at (7, 1) is at objectMap + &0107.
As the object map stores object locations in terms of tile numbers, we can think of the coordinates in the object map as &xx000000 and &zz000000 (as coordinates for the game world are 32-bit), and that's why we only need to store &xx and &zz.
So to convert from 3D game coordinates to object map coordinates, we can simply zero the bottom three bytes of the 3D x-coordinate and z-coordinate to snap the coordinates to the relevant tile corner, or if we only need to extract the object map data, we can simply use the top two bytes in the form &zzxx.
In terms of populating the object map, the PlaceObjectsOnMap routine simply runs a loop for 2048 iterations, and in each iteration it generates a random tile coordinate and a random object type. If the coordinate is in the sea, we move on to the next iteration, as there are no objects in the sea in Lander. Similarly, if the coordinate is on the launchpad, then we move on to the next iteration, so the launchpad is kept clear.
The routine chooses randomly from object types 1 to 8, as follows:
- Small leafy tree
- Tall leafy tree
- Small leafy tree
- Small leafy tree
- Gazebo
- Tall leafy tree
- Fir tree
- Building
This means the chances of an object being a small leafy tree are 3 in 8, while the tall leafy tree is 1 in 4, and the gazebo, fir tree and building are 1 in 8. This is why the landscape in Lander is so lush; trees, on average, account for 75% of ground objects.
The routine finishes off by placing three rockets along the right edge of the launchpad, ready for the new game.