So after a break last week we carry on. There were even more enemy sprites created, so here we go. New are the floating ghost and the fly.
The floating ghost is homing in on the player, but currently blocked by platforms downwards. To amend this we add a new routine. It's a clone of ObjectMoveDownBlocking, the only difference is the call to IsCharBlocking.
;------------------------------------------------------------
;move object down if not blocked
;x = object index
;------------------------------------------------------------
!zone ObjectMoveDownBlockingNoPlatform
ObjectMoveDownBlockingNoPlatform
lda SPRITE_CHAR_POS_Y_DELTA,x
beq .CheckCanMoveDown
.CanMoveDown
inc SPRITE_CHAR_POS_Y_DELTA,x
lda SPRITE_CHAR_POS_Y_DELTA,x
cmp #8bne .NoCharStep
lda #0
sta SPRITE_CHAR_POS_Y_DELTA,x
inc SPRITE_CHAR_POS_Y,x
.NoCharStep
jsr MoveSpriteDown
lda #1
rts
.CheckCanMoveDown
lda SPRITE_CHAR_POS_X_DELTA,x
beq .NoSecondCharCheckNeeded
ldy SPRITE_CHAR_POS_Y,x
iny
lda SCREEN_LINE_OFFSET_TABLE_LO,y
sta ZEROPAGE_POINTER_1
lda SCREEN_BACK_LINE_OFFSET_TABLE_HI,y
sta ZEROPAGE_POINTER_1 + 1
ldy SPRITE_CHAR_POS_X,x
iny
lda (ZEROPAGE_POINTER_1),y
jsr IsCharBlocking
bne .BlockedDown
.NoSecondCharCheckNeeded
ldy SPRITE_CHAR_POS_Y,x
iny
lda SCREEN_LINE_OFFSET_TABLE_LO,y
sta ZEROPAGE_POINTER_1
lda SCREEN_BACK_LINE_OFFSET_TABLE_HI,y
sta ZEROPAGE_POINTER_1 + 1
ldy SPRITE_CHAR_POS_X,x
lda (ZEROPAGE_POINTER_1),y
jsr IsCharBlocking
bne .BlockedDown
jmp .CanMoveDown
.BlockedDown
lda #0
rts
We had code for the ghost skeleton last week, but it was only animating. Now here comes the homing in part. The most annoying part is actually to decide which player to follow. For now it settles on one of the two, that may be subject to change later.
;------------------------------------------------------------
;ghost skeleton
;------------------------------------------------------------
!zone BehaviourGhostSkeleton
BehaviourGhostSkeleton
GHOST_MOVE_SPEED = 1
lda DELAYED_GENERIC_COUNTER
and #$03
bne .NoAnimUpdate
inc SPRITE_ANIM_POS,x
lda SPRITE_ANIM_POS,x
and #$03
sta SPRITE_ANIM_POS,x
tay
lda GHOST_SKELETON_ANIMATION_TABLE,y
sta SPRITE_POINTER_BASE,x
.NoAnimUpdateinc SPRITE_ANIM_DELAY,x
lda SPRITE_ANIM_DELAY,x
cmp #10
beq .DoCheckMove
jmp .DoGhostMove
.DoCheckMove
lda #0
sta SPRITE_ANIM_DELAY,x
txa
and #$01
tay
lda SPRITE_ACTIVE,y
cmp #TYPE_PLAYER_DEAN
beq .FoundPlayer
cmp #TYPE_PLAYER_SAM
beq .FoundPlayer
;check other player
tya
eor #1
tay
lda SPRITE_ACTIVE,y
cmp #TYPE_PLAYER_DEAN
beq .FoundPlayer
cmp #TYPE_PLAYER_SAM
beq .FoundPlayer
;no player to hunt
rts
.FoundPlayer;player index in y
lda SPRITE_CHAR_POS_X,y
cmp SPRITE_CHAR_POS_X,x
bpl .MoveRight
;move left
lda SPRITE_DIRECTION,x
bne .AlreadyLookingLeft
lda SPRITE_MOVE_POS,x
beq .TurnLNow
dec SPRITE_MOVE_POS,x
bne .CheckYNow
.TurnLNow;turning now
lda #1
sta SPRITE_DIRECTION,x
jmp .CheckYNow
.AlreadyLookingLeft
lda SPRITE_MOVE_POS,x
cmp #GHOST_MOVE_SPEED
beq .CheckYNow
inc SPRITE_MOVE_POS,x
jmp .CheckYNow
.MoveRight
lda SPRITE_DIRECTION,x
beq .AlreadyLookingRight
lda SPRITE_MOVE_POS,x
beq .TurnRNow
dec SPRITE_MOVE_POS,x
bne .CheckYNow
;turning now
.TurnRNow
lda #0
sta SPRITE_DIRECTION,x
jmp .CheckYNow
.AlreadyLookingRight
lda SPRITE_MOVE_POS,x
cmp #GHOST_MOVE_SPEED
beq .CheckYNow
inc SPRITE_MOVE_POS,x
jmp .CheckYNow
.CheckYNow;player index in y
lda SPRITE_CHAR_POS_Y,y
cmp SPRITE_CHAR_POS_Y,x
bpl .MoveDown
;move left
lda SPRITE_DIRECTION_Y,x
bne .AlreadyLookingUp
lda SPRITE_MOVE_POS_Y,x
beq .TurnUNow
dec SPRITE_MOVE_POS_Y,x
bne .DoGhostMove
.TurnUNow;turning now
lda #1
sta SPRITE_DIRECTION_Y,x
jmp .DoGhostMove
.AlreadyLookingUp
lda SPRITE_MOVE_POS_Y,x
cmp #GHOST_MOVE_SPEED
beq .DoGhostMove
inc SPRITE_MOVE_POS_Y,x
jmp .DoGhostMove
.MoveDown
lda SPRITE_DIRECTION_Y,x
beq .AlreadyLookingDown
lda SPRITE_MOVE_POS_Y,x
beq .TurnDNow
dec SPRITE_MOVE_POS_Y,x
bne .DoGhostMove
;turning now
.TurnDNow
lda #0
sta SPRITE_DIRECTION_Y,x
jmp .DoGhostMove
.AlreadyLookingDown
lda SPRITE_MOVE_POS_Y,x
cmp #GHOST_MOVE_SPEED
beq .DoGhostMove
inc SPRITE_MOVE_POS_Y,x
jmp .DoGhostMove
.DoGhostMove;move X times
ldy SPRITE_MOVE_POS,x
sty PARAM4
beq .DoY
lda SPRITE_DIRECTION,x
beq .DoRight
.MoveLoopL
jsr ObjectMoveLeftBlocking
dec PARAM4
bne .MoveLoopL
jmp .DoY
.DoRight
.MoveLoopR
jsr ObjectMoveRightBlocking
dec PARAM4
bne .MoveLoopR
.DoY;move X times
ldy SPRITE_MOVE_POS_Y,x
sty PARAM4
beq .MoveDone
lda SPRITE_DIRECTION_Y,x
beq .DoDown
.MoveLoopU
jsr ObjectMoveUpBlocking
dec PARAM4
bne .MoveLoopU
jmp .MoveDone
.DoDown
.MoveLoopD
jsr ObjectMoveDownBlockingNoPlatform
dec PARAM4
bne .MoveLoopD
.MoveDone
rts
And last but not least, the annoying fly. Moving randomly about it surely annoys the heck out of you.
;------------------------------------------------------------
;move randomly diagonal
;------------------------------------------------------------
!zone BehaviourFly
BehaviourFly
lda DELAYED_GENERIC_COUNTER
and #$01bne .NoAnimUpdate
lda SPRITE_ANIM_POS,x
eor #1
sta SPRITE_ANIM_POS,x
clc
adc #SPRITE_FLY_1
sta SPRITE_POINTER_BASE,x
.NoAnimUpdate
lda SPRITE_STATE,x
beq .Move
dec SPRITE_MOVE_POS,x
bne .NoAction
;can move again
dec SPRITE_STATE,x
jsr GenerateRandomNumber
sta SPRITE_MOVE_POS,x
jsr GenerateRandomNumber
and #$03cmp #3bne .ValueOK
lda #2
.ValueOK
sta SPRITE_DIRECTION,x
jsr GenerateRandomNumber
and #$03cmp #3bne .ValueOK2
lda #2
.ValueOK2
sta SPRITE_DIRECTION_Y,x
.NoAction
rts
.Move
dec SPRITE_MOVE_POS,x
bne .CanMove
;wait
jsr GenerateRandomNumber
sta SPRITE_MOVE_POS,x
inc SPRITE_STATE,x
rts
.CanMove
lda SPRITE_DIRECTION,x
beq .MoveRight
cmp #2beq .MoveY
;move left
jsr ObjectMoveLeftBlocking
beq .ToggleDirection
jmp .MoveY
.MoveRight
jsr ObjectMoveRightBlocking
beq .ToggleDirection
jmp .MoveY
.ToggleDirection
lda SPRITE_DIRECTION,x
eor #1
sta SPRITE_DIRECTION,x
.MoveY
lda SPRITE_DIRECTION_Y,x
beq .MoveDown
cmp #2beq .NoYMovement
;move up
jsr ObjectMoveUpBlocking
beq .ToggleDirectionY
rts
.MoveDown
jsr ObjectMoveDownBlockingNoPlatform
beq .ToggleDirectionY
.NoYMovement
rts
.ToggleDirectionY
lda SPRITE_DIRECTION_Y,x
eor #1
sta SPRITE_DIRECTION_Y,x
rts