A C64 Game - Step 77
And another boss. This one is different, as it spawns bats to the left and right. And is only vulnerable during that part ;)

The boss routine is a bit bigger this time. The attacking bat code is already there, so nothing to add on that part.
As behaviours got increasingly complex I started to write the state values on top of the routines. Remember, any states with MSB set (>=128) mark the object as invincible.
;------------------------------------------------------------
;boss #5
;state 128 = find target Y
;state 129 = move towards target Y
;state 0 = attack
;state 130 = cool off
;------------------------------------------------------------
!zone BehaviourBoss6
BehaviourBoss6
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 #0
bne .NoHitBack
lda #1
sta VIC_SPRITE_COLOR,x
;keep invulnerable
.NoHitBack
lda DELAYED_GENERIC_COUNTER
and #$03
bne .NoAnimUpdate
.NoAnimUpdate
lda SPRITE_STATE,x
beq .Attack
cmp #128
bne +
jmp .FindTargetY
+
cmp #129
beq .MoveTowardsTarget
cmp #130
beq .CoolOff
lda #0
sta SPRITE_STATE,x
rts
.CoolOff
inc SPRITE_MODE_POS,x
lda SPRITE_MODE_POS,x
cmp #30
bne +
lda #128
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 #5
bne +
lda #130
sta 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
lda #0
sta SPRITE_MODE_POS,x
sta SPRITE_STATE,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_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_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
Have fun!
step77.zip