More gameplay action, whee!
We add a new enemy, the beloved zombie. The zombie can appear from underground, walks about slowly, and if shot, dives in the ground again.
And while underground the zombie will move about. With the effect, that the zombie will probably appear some where else, not where the player is waiting with the shotgun.
Adding a new enemy is pretty easy now, a new entry in the behaviour table. There are a few more entries in other tables (start color, start sprite, etc.) which we don't go into detail now.
ENEMY_BEHAVIOUR_TABLE_LO
!byte <PlayerControl
!byte <BehaviourBatLR
!byte <BehaviourBatUD
!byte <BehaviourBat8
!byte <BehaviourMummy
!byte <BehaviourZombie
ENEMY_BEHAVIOUR_TABLE_HI
!byte >PlayerControl
!byte >BehaviourBatLR
!byte >BehaviourBatUD
!byte >BehaviourBat8
!byte >BehaviourMummy
!byte >BehaviourZombie
First off the generic counter is checked to slow the zombie movement. The most interesting part in this step is the added state for the enemies. The zombie makes good use of it, as it comes with several states:
-normal walk
-collapsing (2 part)
-reappearing (2 part)
-hidden (walk)
!zone BehaviourZombie
BehaviourZombie
lda DELAYED_GENERIC_COUNTER
and #$3
beq .MovementUpdate
rts
.MovementUpdate
lda SPRITE_STATE,x
bne .OtherStates
jmp .NormalWalk
.OtherStates;collapsing?cmp #128
beq .Collapsing1
cmp #129
beq .Collapsing2
cmp #131
beq .WakeUp1
cmp #132
beq .WakeUp2
cmp #130
bne .NotHidden
jmp .Hidden
.NotHidden
rts
.Collapsing1
lda #SPRITE_ZOMBIE_COLLAPSE_R_2
clcadc SPRITE_DIRECTION,x
sta SPRITE_POINTER_BASE,x
inc SPRITE_STATE,x
rts
.Collapsing2
lda #SPRITE_INVISIBLE
sta SPRITE_POINTER_BASE,x
inc SPRITE_STATE,x
;generate hidden time
jsr GenerateRandomNumber
clcadc #25
sta SPRITE_MOVE_POS,x
;normalise position on full char
ldy SPRITE_CHAR_POS_X_DELTA,x
sty PARAM5
.CheckXPos
beq .XPosClear
jsr ObjectMoveLeft
dec PARAM5
jmp .CheckXPos
.XPosClear
ldy SPRITE_CHAR_POS_Y_DELTA,x
sty PARAM5
.CheckYPos
beq .YPosClear
jsr ObjectMoveUp
dec PARAM5
jmp .CheckYPos
.YPosClear
rts
.WakeUp1
lda #SPRITE_ZOMBIE_COLLAPSE_R_1
clcadc SPRITE_DIRECTION,x
sta SPRITE_POINTER_BASE,x
inc SPRITE_STATE,x
rts
.WakeUp2
lda #SPRITE_ZOMBIE_WALK_R_1
clcadc SPRITE_DIRECTION,x
sta SPRITE_POINTER_BASE,x
lda #0
sta SPRITE_STATE,x
sta SPRITE_MOVE_POS,x
rts
.NormalWalkinc SPRITE_MOVE_POS,x
lda SPRITE_MOVE_POS,x
and #$7
sta SPRITE_MOVE_POS,x
cmp #4bpl .CanMove
rts
.CanMove
lda SPRITE_DIRECTION,x
beq .MoveRight
;move left
jsr ObjectWalkLeft
beq .ToggleDirection
rts
.MoveRight
jsr ObjectWalkRight
beq .ToggleDirection
rts
.ToggleDirection
lda SPRITE_DIRECTION,x
eor #1
sta SPRITE_DIRECTION,x
rts
.Hidden;are we apt to wake up?dec SPRITE_MOVE_POS,x
bne .RandomMove
;wake upinc SPRITE_STATE,x
lda #SPRITE_ZOMBIE_COLLAPSE_R_2
clcadc SPRITE_DIRECTION,x
sta SPRITE_POINTER_BASE,x
rts
.RandomMove;move randomly left/right
jsr GenerateRandomNumber
and #$1
beq .MoveLeft
;move right if possible
jsr CanWalkRight
beq .Blocked
inc SPRITE_CHAR_POS_X,x
ldy #8
sty PARAM5
.MoveSpriteRight
jsr MoveSpriteRight
dec PARAM5
bne .MoveSpriteRight
rts
.MoveLeft
jsr CanWalkLeft
beq .Blocked
dec SPRITE_CHAR_POS_X,x
ldy #8
sty PARAM5
.MoveSpriteLeft
jsr MoveSpriteLeft
dec PARAM5
bne .MoveSpriteLeft
rts
.Blocked
rts
Since shooting the zombie has a different effect than for any other enemy the hurt table acquires a new entry:
;behaviour for an enemy being hit
ENEMY_HIT_BEHAVIOUR_TABLE_LO
!byte <HitBehaviourHurt ;bat LR
!byte <HitBehaviourHurt ;bat UD
!byte <HitBehaviourHurt ;bat8
!byte <HitBehaviourHurt ;mummy
!byte <HitBehaviourCrumble ;zombie
ENEMY_HIT_BEHAVIOUR_TABLE_HI
!byte >HitBehaviourHurt ;bat LR
!byte >HitBehaviourHurt ;bat UD
!byte >HitBehaviourHurt ;bat8
!byte >HitBehaviourHurt ;mummy
!byte >HitBehaviourCrumble ;zombie
HitBehaviourCrumble is completely tailored to the zombie, it merely sets the collapse state. The collapsing itself is done in the behaviour code.
!zone HitBehaviourCrumble
HitBehaviourCrumble
lda SPRITE_STATE,x
bne .NoHit
lda #SPRITE_ZOMBIE_COLLAPSE_R_1
clcadc SPRITE_DIRECTION,x
sta SPRITE_POINTER_BASE,x
lda #128
sta SPRITE_STATE,x
.NoHit
rts