The GameObject System

The heart of this Genesis game / engine is the GameObject system. And it doesn't really get much simpler than this. (These aren't Unity GameObjects!)

I have a single list of GOs - each being an area of memory - effectively in a list. They are (sort of) structures. (there are not really any structs or classes in assembler)

These contain the basics which every kind of GO needs. Data like position, velocity, animation frame, flags, etc.

Alongside that they have some space which can contain different data for different types of GOs.

There is no concept of a class hierarchy, each GO is the same from the code's point of view. Having a fixed size structure is an enormous advantage. It keeps things simple, and removes the need to have different sorts of lists for different objects.

For speed when adding / deleting objects I keep lists of pointers. One for GameObjects which are in use, and one for those which are inactive, so this operation always takes a fixed amount of time.

The main loop calls the GameObject Update function, which cycles through the active list, running a piece of code for each object. Similarly, when a new object is made active, it has a few important variables reset, and calls a function to initialize the object.

Here's the code for about the simplest object I can find:

InitSpikes:
    SETSPR SPRITE_spikes_2_2
    SET_DEATHCOLLISION COLLIDER_spikes_2_2
    rts

UpdateSpikes:
    GLOBAL_ANIMFRAME 3,1
    rts

GameObjects are identified by type, which is simply an index. In this case:

    GOTYPE_SPIKES so.b 1

And there's also a table which contains the data to initialize a GameObject:

    dc.w GOTYPE_SPIKES ,0

    dc.l UpdateSpikes,InitSpikes


So, the functions are looked up in the table, using the GOTYPE, and InitSpikes is called. InitSpikes uses a couple of macros to set what sprite and collider that GO is using, while UpdateSpikes (which is called every frame) performs a simple animation loop.

All very simple, but the real beauty is that the code and tables are generated from within the Unity editor when the game is exported. The Init Function will be exported as is shown here, as the collision and sprite are set up with editor tools. The Update function will be empty, so all I need to do there is go in and add whatever code is required. 

Here's another slightly more complex example. A proximity mine which explodes when near the player, and generates 6 pieces of shrapnel:

;------------------------------------------------------------------------------------------------
InitProximityMine:
    SETSPR SPRITE_proximity_mine            ; set the sprite address 
    SET_TRIGGER TRIGGER_proximity_mine      ; set the trigger data address and flags
    rts

UpdateProximityMine:
    jsr GOTOOLS_IsPlayerInTriggerZone       ;using trigger zones, determine if player is close.
    beq .return                             ; if not, return

; player is near this object, so spawn some shrapnel, and destroy this object
    lea .angles,a3                          ; the table of data for each piece of shrapnel
    move (a3)+,d6                           ; get the amount of pieces to spawn (-1)
.lp:
    SPAWN_GO GOTYPE_PROXIMITY_MINE_SHRAPNEL     ; spawn a new GameObject, this returns the GO addr in a1 (THIS GO is always in a0)
    move.w (a3)+,go_rot(a1)                 ; take the next entry from the table, and set the shrapnel's angle of travel
    dbra d6,.lp                             ; loop for each one in the table

    jsr GOTOOLS_DeleteObject                ; finally destroy this object
.return:
    rts
.angles:
    dc.w 6-1                                ;amount of pieces to spawn -1
    dc.w 0,42*1,42*2,42*3,42*4,42*5         ; the angles of each piece

Here you can see the Proximity Mine's definition in the Unity Editor. The blue box is the size of the object's collision area (this can be any number of rectangles and / or circles).


And here you can see Proximity mines placed in a level in the editor. Their trigger zone is shown to more easily plan gameplay segments.


To sum up, this is how pretty much everything works in the game. GameObjects which have some definition and functionality. This is the same for the player, bosses, 3d objects on the title screen, and even invisible controller objects.



Comments

Popular posts from this blog

Converting Gunslugs to Megadrive / Genesis

Mega Palettes