A C64 game - Step 9

posted in New Old Things
Published June 11, 2011
Advertisement

What are enemies if they just sit put and don't move at all? Therefore we now add the sub routine ObjectControl. ObjectControl loops through all objects (even the player) and jumps to the behaviour function depending on the object type. This incurs that the behaviour is tied to the object type. We provide a table with function pointers to every object's behaviour code (including the player).

step9.png.8bc47ec3c4cfa658e0fc790cd5c56b20.png



ObjectControl takes the object type as index into the table and jumps to the target address. For now we have two enemy types, dumb moving up/down or left/right. For moving we reuse the previously created functions we already use for the player, namely ObjectMoveLeft/ObjectMoveRight etc.

Loop over all active objects and jump at their behaviour code. Note that we apply a nasty trick. Since jsr doesn't allow for indirect jumps we manually push the return address on the stack and then call indirect jmp. This allows for the behaviour code to return with rts.
 


;------------------------------------------------------------
;Enemy Behaviour
;------------------------------------------------------------
!zone ObjectControl
ObjectControl
          ldx #0
.ObjectLoop
          ldy SPRITE_ACTIVE,x
          beq .NextObject
          
          ;enemy is active
          dey
          lda ENEMY_BEHAVIOUR_TABLE_LO,y
          sta ZEROPAGE_POINTER_2
          lda ENEMY_BEHAVIOUR_TABLE_HI,y
          sta ZEROPAGE_POINTER_2 + 1
          
          ;set up return address for rts
          lda #>( .NextObject - 1 )
          pha
          lda #<( .NextObject - 1 )
          pha
          jmp (ZEROPAGE_POINTER_2)
          
.NextObject
          inx
          cpx #8
          bne .ObjectLoop
          rts

 

The main game loop is now changed; removed the call of PlayerControl and added the call to ObjectControl:


;------------------------------------------------------------
;the main game loop
;------------------------------------------------------------
GameLoop
          jsr WaitFrame
          jsr ObjectControl
          jmp GameLoop

 

The behaviour table is built from the behaviour code addresses. Actually we use two tables for high and low byte, this way we don't have to mess with the index. The < and > operators return the low and high byte of a 16 bit value.
 


ENEMY_BEHAVIOUR_TABLE_LO
          !byte <PlayerControl
          !byte <BehaviourDumbEnemyLR
          !byte <BehaviourDumbEnemyUD          
          
ENEMY_BEHAVIOUR_TABLE_HI
          !byte >PlayerControl
          !byte >BehaviourDumbEnemyLR
          !byte >BehaviourDumbEnemyUD


step9.zip



Previous Step 8 Next Step 10

Previous Entry A C64 game - Step 8
0 likes 2 comments

Comments

krasiplasuminu
The way these indirect jumps have always been done, is by simply modifying an existing JSR instruction:


[code]

lda TABLE_LO, y
sta .JumpPoint+1
lda TABLE_HI, y
sta .JumpPoint+2

.JumpPoint jsr $1234
[/code]
June 11, 2011 02:03 PM
Endurion
Ah, neat! I never did assembly on the C64 back then, just started out 2007.

Always good to learn something new ;)
June 12, 2011 07:20 AM
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Profile
Author
Advertisement
Advertisement