• entries
104
102
• views
259749

# A C64 Game - Step 56

1875 views

And here's the next boss. A striking similarity to the first boss, and yet a little bit different.

The main behaviour of this boss is the same as the previous, only the beam is diagonal this time.

Making a diagonal beam is somewhat more difficult, as you need to check for both playfield borders. The beams are started from the boss position and then all 4 directions are tackled after each other.

;------------------------------------------------------------
;boss
;------------------------------------------------------------
!zone BehaviourBoss2
BehaviourBoss2

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

;make vulnerable again
lda SPRITE_STATE,x
cmp #128
bne .NoHitBack

lda #0
sta SPRITE_STATE,x

.NoHitBack
lda DELAYED_GENERIC_COUNTER
and #$03 bne .NoAnimUpdate ;lda SPRITE_POINTER_BASE,x ;eor #$01
;sta SPRITE_POINTER_BASE,x

.NoAnimUpdate
lda SPRITE_STATE,x
and #$7f bne .NotFollowPlayer jmp BossFollowPlayer .NotFollowPlayer cmp #1 beq .AttackMode rts .AttackMode ;Attack modes (more modes?) inc SPRITE_MOVE_POS,x lda SPRITE_MOVE_POS,x cmp #4 beq .NextAttackStep rts .NextAttackStep lda #0 sta SPRITE_MOVE_POS,x inc SPRITE_MODE_POS,x lda SPRITE_MODE_POS,x cmp #11 bcc .BeamNotDangerous cmp #29 bcs .BeamNotDangerous ;does player hit beam? ldy #0 jsr CheckIsPlayerCollidingWithDiagonalBeam ldy #1 jsr CheckIsPlayerCollidingWithDiagonalBeam .BeamNotDangerous lda SPRITE_MODE_POS,x cmp #11 beq .BeamStep1 cmp #12 beq .BeamStep2 cmp #13 beq .BeamStep3 cmp #16 beq .BeamStep4 cmp #17 beq .BeamStep3 cmp #18 beq .BeamStep4 cmp #19 beq .BeamStep3 cmp #20 beq .BeamStep4 cmp #21 beq .BeamStep3 cmp #22 beq .BeamStep4 cmp #23 beq .BeamStep3 cmp #24 beq .BeamStep4 cmp #25 beq .BeamStep3 cmp #26 beq .BeamStep4 cmp #27 beq .BeamStep3 cmp #28 beq .BeamStep4 cmp #29 beq .BeamStep3 cmp #30 beq .BeamEnd rts .BeamStep1 ;beam lda #BEAM_TYPE_DARK jsr .DrawBeamDiagonal rts .BeamStep2 ;beam lda #BEAM_TYPE_MEDIUM jsr .DrawBeamDiagonal rts .BeamStep3 ;beam lda #BEAM_TYPE_LIGHT jsr .DrawBeamDiagonal rts .BeamStep4 ;beam lda #BEAM_TYPE_LIGHT2 jsr .DrawBeamDiagonal rts .BeamEnd jsr RestoreBeamDiagonal lda #0 sta SPRITE_STATE,x rts .DrawBeamDiagonal tay lda BEAM_CHAR_NWSE,y sta PARAM1 lda BEAM_CHAR_NESW,y sta PARAM2 lda BEAM_COLOR,y sta PARAM3 ldy SPRITE_CHAR_POS_Y,x sty PARAM9 stx PARAM6 lda SPRITE_CHAR_POS_X,x sta PARAM7 sta PARAM8 .NextUpperLine ldy PARAM9 lda SCREEN_LINE_OFFSET_TABLE_LO,y sta ZEROPAGE_POINTER_1 sta ZEROPAGE_POINTER_2 lda SCREEN_LINE_OFFSET_TABLE_HI,y sta ZEROPAGE_POINTER_1 + 1 clc adc #( ( SCREEN_COLOR - SCREEN_CHAR ) >> 8 ) sta ZEROPAGE_POINTER_2 + 1 ;upper part ;left ldy PARAM7 beq .NoLeftPart lda PARAM1 sta (ZEROPAGE_POINTER_1),y lda PARAM3 sta (ZEROPAGE_POINTER_2),y .NoLeftPart ;right ldy PARAM8 beq .NoRightPart lda PARAM2 sta (ZEROPAGE_POINTER_1),y lda PARAM3 sta (ZEROPAGE_POINTER_2),y .NoRightPart dec PARAM9 beq .UpperPartDone ;left border reached? lda PARAM7 beq .LeftDone dec PARAM7 .LeftDone lda PARAM8 beq .RightEndReached cmp #38 beq .RightEndReached inc PARAM8 jmp .NextUpperLine .RightEndReached lda #0 sta PARAM8 jmp .NextUpperLine .UpperPartDone ;lower part ldy SPRITE_CHAR_POS_Y,x sty PARAM9 stx PARAM6 lda SPRITE_CHAR_POS_X,x sta PARAM7 sta PARAM8 .NextUpperLineBottom ldy PARAM9 lda SCREEN_LINE_OFFSET_TABLE_LO,y sta ZEROPAGE_POINTER_1 sta ZEROPAGE_POINTER_2 lda SCREEN_LINE_OFFSET_TABLE_HI,y sta ZEROPAGE_POINTER_1 + 1 clc adc #( ( SCREEN_COLOR - SCREEN_CHAR ) >> 8 ) sta ZEROPAGE_POINTER_2 + 1 ;upper part ;left ldy PARAM7 beq .NoLeftPartBottom lda PARAM2 sta (ZEROPAGE_POINTER_1),y lda PARAM3 sta (ZEROPAGE_POINTER_2),y .NoLeftPartBottom ;right ldy PARAM8 beq .NoRightPartBottom lda PARAM1 sta (ZEROPAGE_POINTER_1),y lda PARAM3 sta (ZEROPAGE_POINTER_2),y .NoRightPartBottom inc PARAM9 lda PARAM9 cmp #22 beq .LowerPartDone ;left border reached? lda PARAM7 beq .LeftDoneBottom dec PARAM7 .LeftDoneBottom lda PARAM8 beq .RightEndReachedBottom cmp #38 beq .RightEndReachedBottom inc PARAM8 jmp .NextUpperLineBottom .RightEndReachedBottom lda #0 sta PARAM8 jmp .NextUpperLineBottom .LowerPartDone ldx PARAM6 rts Obviously all the same is repeated for the removal of the beam. !zone RestoreBeamDiagonal RestoreBeamDiagonal ldy SPRITE_CHAR_POS_Y,x stx PARAM6 ldy SPRITE_CHAR_POS_Y,x sty PARAM9 stx PARAM6 lda SPRITE_CHAR_POS_X,x sta PARAM7 sta PARAM8 .NextUpperLine ldy PARAM9 lda SCREEN_LINE_OFFSET_TABLE_LO,y sta ZEROPAGE_POINTER_1 sta ZEROPAGE_POINTER_2 sta ZEROPAGE_POINTER_3 sta ZEROPAGE_POINTER_4 lda SCREEN_LINE_OFFSET_TABLE_HI,y sta ZEROPAGE_POINTER_1 + 1 sec sbc #( ( SCREEN_CHAR - SCREEN_BACK_CHAR ) >> 8 ) sta ZEROPAGE_POINTER_2 + 1 clc adc #( ( SCREEN_COLOR - SCREEN_BACK_CHAR ) >> 8 ) sta ZEROPAGE_POINTER_3 + 1 sec sbc #( ( SCREEN_COLOR - SCREEN_BACK_COLOR ) >> 8 ) sta ZEROPAGE_POINTER_4 + 1 ;upper part ;left ldy PARAM7 beq .NoLeftPart lda (ZEROPAGE_POINTER_2),y sta (ZEROPAGE_POINTER_1),y lda (ZEROPAGE_POINTER_4),y sta (ZEROPAGE_POINTER_3),y .NoLeftPart ;right ldy PARAM8 beq .NoRightPart lda (ZEROPAGE_POINTER_2),y sta (ZEROPAGE_POINTER_1),y lda (ZEROPAGE_POINTER_4),y sta (ZEROPAGE_POINTER_3),y .NoRightPart dec PARAM9 beq .UpperPartDone ;left border reached? lda PARAM7 beq .LeftDone dec PARAM7 .LeftDone lda PARAM8 beq .RightEndReached cmp #38 beq .RightEndReached inc PARAM8 jmp .NextUpperLine .RightEndReached lda #0 sta PARAM8 jmp .NextUpperLine .UpperPartDone ;lower part ldy SPRITE_CHAR_POS_Y,x sty PARAM9 stx PARAM6 lda SPRITE_CHAR_POS_X,x sta PARAM7 sta PARAM8 .NextUpperLineBottom ldy PARAM9 lda SCREEN_LINE_OFFSET_TABLE_LO,y sta ZEROPAGE_POINTER_1 sta ZEROPAGE_POINTER_2 sta ZEROPAGE_POINTER_3 sta ZEROPAGE_POINTER_4 lda SCREEN_LINE_OFFSET_TABLE_HI,y sta ZEROPAGE_POINTER_1 + 1 sec sbc #( ( SCREEN_CHAR - SCREEN_BACK_CHAR ) >> 8 ) sta ZEROPAGE_POINTER_2 + 1 clc adc #( ( SCREEN_COLOR - SCREEN_BACK_CHAR ) >> 8 ) sta ZEROPAGE_POINTER_3 + 1 sec sbc #( ( SCREEN_COLOR - SCREEN_BACK_COLOR ) >> 8 ) sta ZEROPAGE_POINTER_4 + 1 ;upper part ;left ldy PARAM7 beq .NoLeftPartBottom lda (ZEROPAGE_POINTER_2),y sta (ZEROPAGE_POINTER_1),y lda (ZEROPAGE_POINTER_4),y sta (ZEROPAGE_POINTER_3),y .NoLeftPartBottom ;right ldy PARAM8 beq .NoRightPartBottom lda (ZEROPAGE_POINTER_2),y sta (ZEROPAGE_POINTER_1),y lda (ZEROPAGE_POINTER_4),y sta (ZEROPAGE_POINTER_3),y .NoRightPartBottom inc PARAM9 lda PARAM9 cmp #22 beq .LowerPartDone ;left border reached? lda PARAM7 beq .LeftDoneBottom dec PARAM7 .LeftDoneBottom lda PARAM8 beq .RightEndReachedBottom cmp #38 beq .RightEndReachedBottom inc PARAM8 jmp .NextUpperLineBottom .RightEndReachedBottom lda #0 sta PARAM8 jmp .NextUpperLineBottom .LowerPartDone ldx PARAM6 rts Checking if the player is hit by the beam as a bit different as well. The previous boss beam was checked simply by comparing X and Y pos. Now we take the distances between X and Y pos and compare them. They must be either equal or only differ by one to count as colliding. ;------------------------------------------------------------ ;check player vs. diagonal beam ; beam boss index in x ; player index in y ;------------------------------------------------------------ !zone CheckIsPlayerCollidingWithDiagonalBeam CheckIsPlayerCollidingWithDiagonalBeam lda SPRITE_ACTIVE,y bne .PlayerIsActive .PlayerNotActive rts .PlayerIsActive lda SPRITE_STATE,y cmp #128 bcs .PlayerNotActive ;compare char positions in x lda SPRITE_CHAR_POS_X,x sec sbc SPRITE_CHAR_POS_X,y bpl .PositiveX lda SPRITE_CHAR_POS_X,y sec sbc SPRITE_CHAR_POS_X,x .PositiveX sta PARAM1 lda SPRITE_CHAR_POS_Y,x sec sbc SPRITE_CHAR_POS_Y,y bpl .PositiveY lda SPRITE_CHAR_POS_Y,y sec sbc SPRITE_CHAR_POS_Y,x .PositiveY sta PARAM2 lda PARAM1 cmp PARAM2 beq .PlayerHit lda PARAM1 sec sbc PARAM2 and #$7f
cmp #1
beq .PlayerHit

;not hit
rts

.PlayerHit
;player killed
lda #129
sta SPRITE_STATE,y

sta SPRITE_POINTER_BASE,y

lda #0
sta SPRITE_MOVE_POS,y

lda SPRITE_ACTIVE,y
cmp #TYPE_PLAYER_SAM
bne .PlayerWasDean

;reset Sam specific variables
lda #0
sta SPRITE_HELD

.PlayerWasDean
rts


Play the first boss, then stumble upon this one. It's not really difficult as well, but annoying to get the habit of moving out of the way for the first boss out of your mind

Have fun!

There are no comments to display.

## Create an account or sign in to comment

You need to be a member in order to leave a comment

## Create an account

Sign up for a new account in our community. It's easy!

Register a new account