(back to project page)

Stellar 7 Objects

The code has two distinct but intertwined sections: the graphics engine, and the game code. Both have slots for 24 objects. Slot 0 is reserved for the player, slots 1 and 2 for the player's cannon projectiles, and slot 3 for the Warplink. If all slots are full enemies will be unable to fire their weapons, but in practice the game doesn't fill the slots to that degree.

The graphics engine data starts at $6600. It includes for each object:

Most of these are set by the OBJ# file and then overwritten during object initialization. The X/Y/Z position and facing values are kept for the initial set of objects.

The game object data starts at $8400. It includes for each object:

In addition, it has parameters for things like how many enemies must be killed before the Warplink appears. The data is set by the DYN# file, with most of the fields being cleared during object initialization. The object type here is used to initialize the type in the graphics engine for the initial objects.

Some fields are used for the player, like the shot status, while others like armor remaining are tracked elsewhere.

The mission briefing code sits on top of the game object data and code. It uses the graphics engine to display the shapes.

Objects

Index Img Name Move Class
0 ($00) u00 (player)0
1 ($01) u01 Sandsled1
2 ($02) u02 Laser Tank1
3 ($03) u03 Hovercraft1
4 ($04) u04 Prowler1
5 ($05) u05 Heavy Tank1
6 ($06) u06 Stalker1
7 ($07) u07 Gir Draxon1
8 ($08) u08 Laser Battery2
9 ($09) u09 Gun Battery2
10 ($0a) u10 Pulsar2
11 ($0b) u11 Skimmer3
12 ($0c) u12 Stinger3
13 ($0d) u13 Guiser4
14 ($0e) u14 Seeker4
15 ($0f) u15 Projectile - Low Laser5
16 ($10) u16 Projectile - Medium Laser5
17 ($11) u17 Projectile - High Laser5
18 ($12) u18 Projectile - Light Cannon6
19 ($13) u19 Projectile - Medium Cannon6
20 ($14) u20 Projectile - Heavy Cannon6
21 ($15) u21 Projectile - Thunder Cannon7
22 ($16) u22 Obstacle8
23 ($17) u23 Fuelbay8
24 ($18) u24 Warplink8
31 ($1f) u31 Explosion 09
32 ($20) u32 Explosion 19
33 ($21) u33 Explosion 29
34 ($22) u34 Explosion 39
35 ($23) u35 Explosion 49
36 ($24) u36 Explosion 59
37 ($25) u37 Explosion 69
38 ($26) u38 Explosion 79
41 ($29) u41 Impact 09
42 ($2a) u42 Impact 19
43 ($2b) u43 Impact 29
44 ($2c) u44 Impact 39
45 ($2d) u45 Impact 49
46 ($2e) u46 Impact 59
47 ($2f) u47 Impact 69
48 ($30) u48 Impact 79

There are three "meta types", $19, $1a, and $1b. When a unit or projectile is destroyed, it's replaced with one of the meta-types. The meta value is combined with a counter to set the unit type to one of the explosion or impact frames.

Movement Class

Movement classes determine how objects behave and under what circumstances they appear on radar. Some things always appear, some never appear, and some only appear in "full" mode.

Class Description Radar?
0PlayerAlways
1Ground vehicleAlways
2TurretAlways
3FlierAlways
4BombAlways
5Laser projectileFull mode
6Cannon projectileFull mode
7Player projectileFull mode
8Immobile objectAlways
9Explosion animationNever

Movement class ranges are used in a number of places. For example, classes 1 through 3 can fire weapons. When two objects collide, their movement classes determine the result (e.g. did a tank drive into an obstacle or a projectile)?

Mesh Data Format

The LEV# files and (for the mission briefing) BRIEF.ST hold the mesh data. Each file starts with a table of 16-bit offsets to 64 shapes. The offset will be >= $8000 if the entry is unused. The 0th entry in the table, which would correspond to the player's tank, instead holds the address of the first byte past the end of the table.

The mesh data has two tables, vertices and edges, terminated by stop symbols ($80). Vertex data is three bytes, but is not Cartesian X/Y/Z coordinates. Instead, the first two bytes define X/Z with polar coordinates (distance then angle), while the third byte holds the Y coordinate. This arrangement makes computation of rotation about the Y axis simpler. The edge data table is just pairs of vertex indices.

As an example, consider the Obstacle:

shp_obstacle .bulk   $6a,$20,$5a
             .bulk   $6a,$20,$c4
             .bulk   $6a,$60,$5a
             .bulk   $6a,$60,$c4
             .bulk   $6a,$e0,$5a
             .bulk   $6a,$e0,$c4
             .bulk   $6a,$a0,$5a
             .bulk   $6a,$a0,$c4
             .dd1    $80
             .bulk   $00,$01
             .bulk   $02,$03
             .bulk   $04,$05
             .bulk   $06,$07
             .bulk   $00,$02
             .bulk   $04,$06
             .bulk   $01,$03
             .bulk   $05,$07
             .bulk   $00,$04
             .bulk   $02,$06
             .bulk   $01,$05
             .bulk   $03,$07
             .dd1    $80

The first 8 lines are the vertices. They all have the same distance ($6a), which makes sense for a cube. The cube edges are axis-aligned, so the vertex angles are at 45 degrees. With 256 angles making a circle, the compass points are 0/64/128/192 ($00/$40/$80/$c0), so the vertices are at angles 32/96/160/224 ($20/$60/$a0/$e0).

The Y coordinates are signed, and defined so they don't need to be translated for the viewer (at Y=0). The Obstacle uses $5a/$c4, which are +90/-60. This gives the impression that the player's eye level is 60 units above ground level. You can see Y=-60 ($c4) used elsewhere, e.g. for the skids on the Sandsled. (The tallest shape in the game is the Warplink, which extends from -100 to +120.)

The vertex transformation code has an optimization that allows it to save some time if a vertex has the same distance and angle as the previous vertex (i.e. if they're on the same vertical line). The Obstacle definition takes advantage of this.

The end of the vertex list is marked with $80.

The next section defines the 12 edges. Each pair of bytes holds the indices of the start and end vertices of an edge. Lines are generally drawn with inclusive coordinates, so it doesn't matter in what order the edges or vertices appear.

As with vertices, the end of the edge list is marked with $80.


Copyright 2020 by Andy McFadden