And a new boss. Quite similar to the first actually, but supposed to be a bit more aggressive.
This boss needed a bit of refactoring since a few code parts were reusable from the first boss. First up, the find one player to hunt:
;looks for player
;x = own object index
;returns player index in y
!zone FindPlayer
FindPlayer
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
ldy #2
rts
.FoundPlayer
rts
The homing boss movement is put in a sub routine:
BossFollowPlayer
inc SPRITE_ANIM_DELAY,x
lda SPRITE_ANIM_DELAY,x
cmp #10
beq .DoCheckMove
jmp .DoGhostMove
.DoCheckMove
lda #0
sta SPRITE_ANIM_DELAY,x
jsr FindPlayer
cmp #2
bne +
;no player to hunt
rts
+
;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 #BOSS_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
lda #SPRITE_BOSS_FOOT_R
sta SPRITE_POINTER_BASE,x
jmp .CheckYNow
.AlreadyLookingRight
lda SPRITE_MOVE_POS,x
cmp #BOSS_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 #BOSS_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 #BOSS_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 here's the actual boss behaviour. The boss homes in on the player and will directly attack if the player could be hit:
;------------------------------------------------------------
;boss
;------------------------------------------------------------
!zone BehaviourBoss4
BehaviourBoss4
BOSS_MOVE_SPEED = 1
lda SPRITE_HITBACK,x
beq .NoHitBack
dec SPRITE_HITBACK,x
ldy SPRITE_HITBACK,x
lda BOSS_FLASH_TABLE,y
sta VIC_SPRITE_COLOR,x
cpy #0bne .NoHitBack
;make vulnerable again
lda SPRITE_STATE,x
cmp #128bne .NoHitBack
lda #0
sta SPRITE_STATE,x
.NoHitBack
lda DELAYED_GENERIC_COUNTER
and #$03bne .NoAnimUpdate
.NoAnimUpdate
lda SPRITE_STATE,x
bne .NotFollowPlayer
;check if on same height as a player
lda SPRITE_ACTIVE
cmp #TYPE_PLAYER_DEANbne ++
lda SPRITE_CHAR_POS_Y
cmp SPRITE_CHAR_POS_Y,x
beq .StartAttackMode
++
lda SPRITE_ACTIVE + 1cmp #TYPE_PLAYER_SAMbne ++
lda SPRITE_CHAR_POS_Y + 1cmp SPRITE_CHAR_POS_Y,x
beq .StartAttackMode
++
;anim
lda SPRITE_DIRECTION,x
beq +
lda #SPRITE_BOSS_FOOT_L
jmp ++
+
lda #SPRITE_BOSS_FOOT_R
++
sta SPRITE_POINTER_BASE,x
jmp BossFollowPlayer
.StartAttackMode
lda #1
sta SPRITE_STATE,x
lda #0
sta SPRITE_MOVE_POS,x
sta SPRITE_MODE_POS,x
jmp .AttackMode
.NotFollowPlayercmp #1beq .AttackMode
rts
.AttackMode;Attack modes (more modes?)
inc SPRITE_MOVE_POS,x
lda SPRITE_MOVE_POS,x
cmp #4beq .NextAttackStep
rts
.NextAttackStep
lda SPRITE_CHAR_POS_X,x
sta PARAM4
lda SPRITE_CHAR_POS_Y,x
sta PARAM5
lda #0
sta SPRITE_MOVE_POS,x
inc SPRITE_MODE_POS,x
lda SPRITE_MODE_POS,x
cmp #11bcc .BeamNotDangerous
cmp #29bcs .BeamNotDangerous
;does player hit beam?
ldy #0
jsr CheckIsPlayerCollidingWithBeam
ldy #1
jsr CheckIsPlayerCollidingWithBeam
.BeamNotDangerous
lda SPRITE_MODE_POS,x
cmp #5beq .BeamStep1
cmp #6beq .BeamStep2
cmp #7beq .BeamStep3
cmp #8beq .BeamStep4
cmp #9beq .BeamStep3
cmp #10beq .BeamStep4
cmp #11beq .BeamStep3
cmp #12beq .BeamEnd
rts
.HandleBeam
lda BEAM_CHAR_H,y
sta PARAM1
lda BEAM_CHAR_V,y
sta PARAM2
lda BEAM_COLOR,y
sta PARAM3
jsr DrawBeamH
jsr DrawBeamV
rts
.BeamStep1;beam
ldy #BEAM_TYPE_DARK
jmp .HandleBeam
.BeamStep2;beam
ldy #BEAM_TYPE_MEDIUM
jmp .HandleBeam
.BeamStep3;beam
ldy #BEAM_TYPE_LIGHT
jmp .HandleBeam
.BeamStep4;beam
ldy #BEAM_TYPE_LIGHT2
jmp .HandleBeam
.BeamEnd
jsr RestoreBeamHV
lda #0
sta SPRITE_STATE,x
rts
Have fun!
step70.zip
Previous Step Next Step