Another boss!
And one, that works differently than the others before him.
This boss is spawning bats that fly left/right and vanish once hitting the screen border.
Thus we remove the path-8-flying bat and replace it by a simple attacking bat:
!zone BehaviourBatAttacking
BehaviourBatAttacking
lda DELAYED_GENERIC_COUNTER
and #$03bne .NoAnimUpdate
inc SPRITE_ANIM_POS,x
lda SPRITE_ANIM_POS,x
and #$03
sta SPRITE_ANIM_POS,x
tay
lda BAT_ANIMATION,y
sta SPRITE_POINTER_BASE,x
.NoAnimUpdate
lda #3
sta PARAM1
lda SPRITE_DIRECTION,x
beq .MoveRight
.MoveLeft
jsr ObjectMoveLeft
dec PARAM1
bne .MoveLeft
jmp .XMoveDone
.MoveRight
jsr ObjectMoveRight
dec PARAM1
bne .MoveRight
.XMoveDone
lda SPRITE_CHAR_POS_X,x
cmp #255beq .RemoveMe
cmp #39beq .RemoveMe
rts
.RemoveMe
inc SPAWN_NO_ITEM
jsr KillEnemy
dec SPAWN_NO_ITEM
rts
The boss itself is not really clever. It calculates a random y position, moves there, spawns bats and starts all over again. Note that it is only vulnerable while spawning bats though
Remember, vulnerability is controlled by having the MSB set in SPRITE_STATE,x.
;------------------------------------------------------------
;boss #5
;state 0 = find target Y
;state 1 = move towards target Y
;state 2 = attack
;state 3 = cool off
;------------------------------------------------------------
!zone BehaviourBoss5
BehaviourBoss5
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
lda #1
sta VIC_SPRITE_COLOR,x
;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 +
jmp .FindTargetY
+
cmp #1beq .MoveTowardsTarget
cmp #2beq .Attack
cmp #3beq .CoolOff
lda #0
sta SPRITE_STATE,x
rts
.CoolOff
inc SPRITE_MODE_POS,x
lda SPRITE_MODE_POS,x
cmp #30bne +
lda #0
sta SPRITE_STATE,x
+
rts
.Attack
inc SPRITE_MOVE_POS,x
lda SPRITE_MOVE_POS,x
and #$1f
cmp #$1f
beq +
rts
+
;free bats
inc SPRITE_MODE_POS,x
lda SPRITE_MODE_POS,x
cmp #5bne +
inc SPRITE_STATE,x
lda #0
sta SPRITE_MODE_POS,x
rts
+
lda SPRITE_CHAR_POS_X,x
sta PARAM1
lda SPRITE_CHAR_POS_Y,x
sta PARAM2
inc PARAM2
stx PARAM10
jsr FindEmptySpriteSlot
beq ++
lda #TYPE_BAT_ATTACKING
sta PARAM3
jsr SpawnObject
lda #0
sta SPRITE_DIRECTION,x
jsr FindEmptySpriteSlot
beq ++
jsr SpawnObject
lda #1
sta SPRITE_DIRECTION,x
++
ldx PARAM10
rts
.MoveTowardsTarget;player index in y
lda SPRITE_VALUE,x
cmp SPRITE_CHAR_POS_Y,x
bne +
;arrived at target Y
inc SPRITE_STATE,x
lda #0
sta SPRITE_MODE_POS,x
rts
+
bpl .MoveDown
;move up?
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_SPEEDbeq .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_SPEEDbeq .DoGhostMove
inc SPRITE_MOVE_POS_Y,x
jmp .DoGhostMove
.DoGhostMove;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
.FindTargetY
lda #4
sta PARAM5
lda #18
sta PARAM6
jsr GenerateRangedRandom
sta SPRITE_VALUE,x
inc SPRITE_STATE,x
rts
For the boss routine we require a little utility function which returns a ranged random number. No division or module means manual work: create random number, subtract range until it's small enough, then add the lower range.
;lower end = PARAM5
;higher end = PARAM6
GenerateRangedRandom
lda PARAM6
sec
sbc PARAM5
clcadc #1
sta PARAM6
jsr GenerateRandomNumber
.CheckValuecmp PARAM6
bcc .ValueOk
;too high
sec
sbc PARAM6
jmp .CheckValue
.ValueOkclcadc PARAM5
rts
Have fun!
step74.zip
Previous Step Next Step