A C64 Game - Step 88

posted in New Old Things
Published February 24, 2013
Advertisement

And finally, here's the big boss. Expect him to put up quite a fight once he is completed. Note that currently you cannot kill the last part.



First of all, the boss is not just simply there, it is entering with a few flashes. We reuse Dean's shot flash code for this. To mark the final boss entry we use a new bit in the level config byte:

;final boss intro 
          lda LEVEL_CONFIG 
          and #$08 
          beq ++ 
          
          jsr HandleFinalBossIntro 
          jmp .NotDoneYet
          
++


The boss is compiled of several sprites which we create once the flashes are done. Also, the boss bit is removed to avoid restarting the boss intro.

!zone HandleFinalBossIntro
HandleFinalBossIntro 
          inc FINAL_INTRO_TIMER_DELAY 
          lda FINAL_INTRO_TIMER_DELAY 
          and #$03 
          beq ++ 
          rts
          
++ 
          inc FINAL_INTRO_TIMER 
          lda FINAL_INTRO_TIMER 
          cmp #5 
          beq .Flash 
          cmp #8 
          beq .Flash 
          cmp #10 
          beq .Flash 
          cmp #11 
          beq .SpawnBoss 
          rts 
          
.Flash 
          ;use dean's shot flash 
          lda #5 
          sta PLAYER_RELOAD_FLASH_POS 
          lda #1 
          sta VIC_BACKGROUND_COLOR 
          rts 
          
.SpawnBoss 
          ;disable intro flag 
          lda LEVEL_CONFIG 
          and #$f7 
          sta LEVEL_CONFIG 
          
          ;spawn boss 
          lda #0 
          sta BOSS_PARTS_KILLED 
          lda #19 
          sta PARAM1 
          lda #6 
          sta PARAM2 
          lda #TYPE_BOSS7 
          sta PARAM3 
          jsr FindEmptySpriteSlot 
          jsr SpawnObject 
          
          stx PARAM10 
          
          ;torso 
          lda #19 
          sta PARAM1 
          lda #10 
          sta PARAM2 
          lda #TYPE_BOSS5 
          sta PARAM3 
          jsr FindEmptySpriteSlot 
          jsr SpawnObject 
          
          lda #TYPE_BOSS_PART 
          sta SPRITE_ACTIVE,x 
          lda #128 
          sta SPRITE_STATE,x 
          jsr MoveSpriteUp 
          jsr MoveSpriteUp 
          lda PARAM10 
          sta SPRITE_VALUE,x 
          lda #2 
          sta VIC_SPRITE_COLOR,x 
          
          ;left arm 
          lda #17 
          sta PARAM1 
          lda #9 
          sta PARAM2 
          lda #TYPE_BOSS3 
          sta PARAM3 
          jsr FindEmptySpriteSlot 
          jsr SpawnObject 
          lda #TYPE_BOSS_PART 
          sta SPRITE_ACTIVE,x 
          lda #0 
          sta SPRITE_STATE,x 
          lda PARAM10 
          sta SPRITE_VALUE,x 
          lda #2 
          sta VIC_SPRITE_COLOR,x 
          
          ;right arm 
          lda #21 
          sta PARAM1 
          lda #9 
          sta PARAM2 
          lda #TYPE_BOSS4 
          sta PARAM3 
          jsr FindEmptySpriteSlot 
          jsr SpawnObject 
          lda #TYPE_BOSS_PART 
          sta SPRITE_ACTIVE,x 
          lda #0 
          sta SPRITE_STATE,x 
          lda PARAM10 
          sta SPRITE_VALUE,x 
          lda #2 
          sta VIC_SPRITE_COLOR,x 
          
          ;left foot 
          lda #18 
          sta PARAM1 
          lda #13 
          sta PARAM2 
          lda #TYPE_BOSS2 
          sta PARAM3 
          jsr FindEmptySpriteSlot 
          jsr SpawnObject 
          lda #TYPE_BOSS_PART 
          sta SPRITE_ACTIVE,x 
          lda #0 
          sta SPRITE_STATE,x 
          lda PARAM10 
          sta SPRITE_VALUE,x 
          lda #2 
          sta VIC_SPRITE_COLOR,x 
          
          ;right foot 
          lda #20 
          sta PARAM1 
          lda #13 
          sta PARAM2 
          lda #TYPE_BOSS 
          sta PARAM3 
          jsr FindEmptySpriteSlot 
          jsr SpawnObject 
          lda #TYPE_BOSS_PART 
          sta SPRITE_ACTIVE,x 
          lda #0 
          sta SPRITE_STATE,x 
          lda PARAM10 
          sta SPRITE_VALUE,x 
          lda #2 
          sta VIC_SPRITE_COLOR,x 
          jmp .Flash
          

Also, the boss is required to be killed in several steps. First the limbs, followed by torso and finally the head. This is done by setting states accordingly (remember, states >= 128 mark invincibility) increasing the killed body part count and making other parts vulnerable:


          cpy #TYPE_BOSS_PART 
          bne ++ 
          
          inc BOSS_PARTS_KILLED 
          lda BOSS_PARTS_KILLED cmp #5 
          beq .MakeBossHeadVulnerable 
          cmp #4 
          bne ++ 
          
          ;make boss torso vulnerable 
          ldy #1 
          
- 
          lda SPRITE_ACTIVE,y 
          cmp #TYPE_BOSS_PART 
          beq + 
          
          iny 
          bne - 
          
+ 
          lda #0 
          sta SPRITE_STATE,y 
          jmp ++ 
          
.MakeBossHeadVulnerable 
          ldy #1 
          
- 
          lda SPRITE_ACTIVE,y 
          cmp #TYPE_BOSS7 
          beq + 
          
          iny 
          bne - 
          
+ 
          lda #0 
          sta SPRITE_STATE,y
          
++

Since the boss object is controlled by the head but bigger with all parts attached the possible movement area needs to be limited (the boss body should not move outside the screen). Therefore a little check is added to all movement routines:


          lda SPRITE_CHAR_POS_X,x 
          cmp MOVE_BORDER_LEFT 
          beq .BlockedLeft


..and similar to the other three directions.

The bosses limbs are shooting beams horizontally and diagonally. These require a few changes to the existing collision check routines to allow for partial beams:

;------------------------------------------------------------
;check player vs. beam H
; YPos in PARAM3
; player index in y
;------------------------------------------------------------
!zone CheckIsPlayerCollidingWithYPosH
CheckIsPlayerCollidingWithYPosH 
          lda SPRITE_ACTIVE,y 
          bne .PlayerIsActive
          
.PlayerNotActive 
          rts 
          
.PlayerIsActive 
          cmp #TYPE_PLAYER_DEAN 
          beq + 
          cmp #TYPE_PLAYER_SAM 
          beq + 
          rts 
          
+ 
          lda SPRITE_STATE,y 
          cmp #128 
          bcs .PlayerNotActive 
          
          lda SPRITE_CHAR_POS_X,y 
          cmp PARAM1 
          bcc .PlayerNotActive 
          cmp PARAM2 
          bcs .PlayerNotActive 
          
          ;compare char positions in y 
          lda PARAM3 
          cmp SPRITE_CHAR_POS_Y,y 
          beq .PlayerHit 
          
          clc 
          adc #1 
          cmp SPRITE_CHAR_POS_Y,y 
          beq .PlayerHit 
          
          sec 
          sbc #2 
          cmp SPRITE_CHAR_POS_Y,y 
          beq .PlayerHit 
          
          ;not hit 
          rts 
          
.PlayerHit 
          ;player killed 
          jmp KillPlayer
          
;------------------------------------------------------------
;check player vs. diagonal beam
; X start in PARAM1
; Y start in PARAM2
; player index in y
;------------------------------------------------------------
!zone CheckIsPlayerCollidingWithDiagonalLLUR
CheckIsPlayerCollidingWithDiagonalLLUR 
          lda SPRITE_ACTIVE,y 
          bne .PlayerIsActive
          
.PlayerNotActive 
          rts 
          
.PlayerIsActive 
          lda SPRITE_STATE,y 
          cmp #128 
          bcs .PlayerNotActive 
          
          ;compare char positions in x 
          lda PARAM1 
          sec 
          sbc SPRITE_CHAR_POS_X,y 
          bpl .PositiveX 
          
          ;player is to the right 
          rts
          
.PositiveX 
          sta PARAM3 
          lda PARAM2 
          sec 
          sbc SPRITE_CHAR_POS_Y,y 
          bpl .PositiveY 
          
          lda SPRITE_CHAR_POS_Y,y 
          sec 
          sbc PARAM2
          
.PositiveY 
          sta PARAM4 
          lda PARAM3 
          cmp PARAM4 
          beq .PlayerHit 
          
          lda PARAM3 
          sec 
          sbc PARAM4 
          bpl .PositiveDelta 
          
          lda PARAM4 
          sec 
          sbc PARAM3
          
.PositiveDelta 
          cmp #1 
          beq .PlayerHit 
          
          ;not hit 
          rts 
          
.PlayerHit 
          ;player killed 
          jmp KillPlayer
          
;------------------------------------------------------------
;check player vs. diagonal beam
; X start in PARAM1
; Y start in PARAM2
; player index in y
;------------------------------------------------------------
!zone CheckIsPlayerCollidingWithDiagonalULLR
CheckIsPlayerCollidingWithDiagonalULLR 
          lda SPRITE_ACTIVE,y 
          bne .PlayerIsActive
          
.PlayerNotActive 
          rts 
          
.PlayerIsActive 
          lda SPRITE_STATE,y 
          cmp #128 
          bcs .PlayerNotActive 
          
          ;compare char positions in x 
          lda PARAM1 
          sec 
          sbc SPRITE_CHAR_POS_X,y 
          bpl .PlayerNotActive 
          
          ;player is to the right 
          lda SPRITE_CHAR_POS_X,y 
          sec 
          sbc PARAM1 
          sta PARAM3 
          lda PARAM2 
          sec 
          sbc SPRITE_CHAR_POS_Y,y 
          bpl .PositiveY 
          
          lda SPRITE_CHAR_POS_Y,y 
          sec 
          sbc PARAM2
          
.PositiveY 
          sta PARAM4 
          lda PARAM3 
          cmp PARAM4 
          beq .PlayerHit 
          
          lda PARAM3 
          sec 
          sbc PARAM4 
          bpl .PositiveDelta 
          
          lda PARAM4 
          sec 
          sbc PARAM3
          
.PositiveDelta 
          cmp #1 
          beq .PlayerHit 
          
          ;not hit 
          rts 
          
.PlayerHit 
          ;player killed 
          jmp KillPlayer


All the beams are controlled by the boss head. Attack states, firing and collision checks:

;------------------------------------------------------------
;boss #7
;state = 128 -> random movements
;state = 129 -> attack with beams
;------------------------------------------------------------
!zone BehaviourBoss7
BehaviourBoss7
BOSS_MOVE_SPEED = 1 
          lda SPRITE_STATE,x 
          beq .RandomMovements 
          cmp #129 
          bne + 
          
          jmp .AttackWithBeams
          
+
.RandomMovements 
          inc SPRITE_MODE_POS,x 
          bne + 
          
          ;attack mode 
          lda #129 
          sta SPRITE_STATE,x 
          rts
          
+ 
          lda SPRITE_MOVE_POS,x 
          bne .DoMove 
          
          ;find new random dir 
          lda #25 
          sta SPRITE_MOVE_POS,x 
          jsr GenerateRandomNumber 
          and #$01 
          sta SPRITE_DIRECTION,x 
          jsr GenerateRandomNumber 
          and #$01 
          sta SPRITE_DIRECTION_Y,x
          
.DoMove 
          dec SPRITE_MOVE_POS,x 
          lda #12 
          sta MOVE_BORDER_LEFT 
          lda #39 - 12 
          sta MOVE_BORDER_RIGHT 
          lda #4 
          sta MOVE_BORDER_TOP 
          lda #12 
          sta MOVE_BORDER_BOTTOM 
          lda SPRITE_DIRECTION,x 
          beq ++ 
          
          jsr ObjectMoveLeftBlocking 
          beq .DoMoveY 
          
          ;move other parts 
          lda #5 
          sta PARAM10
- 
          inx 
          jsr ObjectMoveLeft 
          dec PARAM10 
          bne - 
          jmp .DoMoveY
          
++ 
          jsr ObjectMoveRightBlocking 
          beq .DoMoveY 
          
          ;move other parts 
          lda #5 
          sta PARAM10
- 
          inx 
          jsr ObjectMoveRight 
          dec PARAM10 
          bne - 
          
.DoMoveY 
          ldx CURRENT_INDEX 
          lda SPRITE_DIRECTION_Y,x 
          beq ++ 
          
          jsr ObjectMoveUpBlocking 
          beq .DoMoveDone 
          
          ;move other parts 
          lda #5 
          sta PARAM10
- 
          inx 
          jsr ObjectMoveUp 
          dec PARAM10 
          bne - 
          
          jmp .DoMoveDone
          
++ 
          jsr ObjectMoveDownBlocking 
          beq .DoMoveDone 
          
          ;move other parts 
          lda #5 
          sta PARAM10
- 
          inx 
          jsr ObjectMoveDown 
          dec PARAM10 
          bne -
          
.DoMoveDone 
          lda #0 
          sta MOVE_BORDER_LEFT 
          sta MOVE_BORDER_TOP 
          lda #39 
          sta MOVE_BORDER_RIGHT 
          lda #23 
          sta MOVE_BORDER_BOTTOM 
          rts
          
.AttackWithBeams 
          inc SPRITE_MOVE_POS,x 
          lda SPRITE_MOVE_POS,x 
          and #$03 
          beq + 
          
          rts
          
+ 
          inc SPRITE_MODE_POS,x 
          lda SPRITE_MODE_POS,x 
          cmp #5 
          bcs + 
          jmp .BeamNotDangerous
          
+ 
          cmp #12 
          bcc + 
          jmp .BeamNotDangerous
          
+ 
          ;does player hit beam? ;modify x to point to arm object ;TODO - only check left/right segment! 
          lda SPRITE_ACTIVE + 2,x 
          beq ++ 
          
          ;left arm 
          lda SPRITE_CHAR_POS_Y,x 
          clc 
          adc #3 
          sta PARAM3 
          lda #0 
          sta PARAM1 
          lda SPRITE_CHAR_POS_X,x 
          sec 
          sbc #2 
          sta PARAM2 
          
          ldy #0 
          jsr CheckIsPlayerCollidingWithYPosH 
          ldy #1 
          jsr CheckIsPlayerCollidingWithYPosH
          
++ 
          lda SPRITE_ACTIVE + 3,x 
          beq ++ 
          
          ;right arm 
          lda SPRITE_CHAR_POS_Y,x 
          clc 
          adc #3 
          sta PARAM3 
          lda SPRITE_CHAR_POS_X,x 
          clc 
          adc #2 
          sta PARAM1 
          lda #39 
          sta PARAM2 
          
          ldy #0 
          jsr CheckIsPlayerCollidingWithYPosH 
          ldy #1 
          jsr CheckIsPlayerCollidingWithYPosH
          
++ 
          lda SPRITE_ACTIVE + 4,x 
          beq ++ 
          lda SPRITE_CHAR_POS_Y,x 
          clc 
          adc #8 
          sta PARAM2 
          lda SPRITE_CHAR_POS_X,x 
          sec 
          sbc #1 
          sta PARAM1 
          
          ldy #0 
          jsr CheckIsPlayerCollidingWithDiagonalLLUR 
          ldy #1 
          jsr CheckIsPlayerCollidingWithDiagonalLLUR
          
++ 
          lda SPRITE_ACTIVE + 5,x 
          beq ++ 
          
          lda SPRITE_CHAR_POS_X,x 
          clc 
          adc #2 
          sta PARAM1 
          lda SPRITE_CHAR_POS_Y,x 
          clc 
          adc #8 
          sta PARAM2 
          
          ldy #0 
          jsr CheckIsPlayerCollidingWithDiagonalULLR 
          ldy #1 
          jsr CheckIsPlayerCollidingWithDiagonalULLR
          
++ 
.BeamNotDangerous 
          lda SPRITE_MODE_POS,x 
          cmp #5 
          beq .BeamStep1 cmp #6 
          beq .BeamStep2 cmp #7 
          beq .BeamStep3 cmp #8 
          beq .BeamStep4 cmp #9 
          beq .BeamStep3 cmp #10 
          beq .BeamStep4 cmp #11 
          beq .BeamStep3 cmp #12 
          bne + 
          
          lda #128 
          sta SPRITE_STATE,x 
          lda #0 
          sta SPRITE_MODE_POS,x 
          
          ;remove beam 
          lda #0 
          sta PARAM3 
          lda SPRITE_CHAR_POS_Y,x 
          clc 
          adc #3 
          sta PARAM4 
          lda #39 
          sta PARAM5 
          jsr RestoreBeamHSegment 
          
          lda SPRITE_CHAR_POS_X,x 
          sec 
          sbc #1 
          sta PARAM3 
          lda SPRITE_CHAR_POS_Y,x 
          clc 
          adc #8 
          sta PARAM4 
          jsr RestoreBeamDiagonalLLUR 
          
          lda SPRITE_CHAR_POS_X,x 
          clc 
          adc #2 
          sta PARAM3 
          lda SPRITE_CHAR_POS_Y,x 
          clc 
          adc #8 
          sta PARAM4 
          jsr RestoreBeamDiagonalULLR 
          
+ 
          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 
          
.HandleBeam 
          ;PARAM1 = beam h char ;PARAM2 = beam color ;PARAM3 = x char pos ;PARAM4 = y char pos ;PARAM5 = x end pos 
          tya 
          pha 
          lda BEAM_CHAR_H,y 
          sta PARAM1 
          lda BEAM_COLOR,y 
          sta PARAM2 
          
          ;left arm 
          lda SPRITE_ACTIVE + 2,x 
          beq ++ 
          lda #0 
          sta PARAM3 
          lda SPRITE_CHAR_POS_Y,x 
          clc 
          adc #3 
          sta PARAM4 
          lda SPRITE_CHAR_POS_X,x 
          sec 
          sbc #2 
          sta PARAM5 
          jsr DrawBeamHSegment
          
++ 
          lda SPRITE_ACTIVE + 3,x 
          beq ++ 
          lda SPRITE_CHAR_POS_X,x 
          clc 
          adc #3 
          sta PARAM3 
          lda SPRITE_CHAR_POS_Y,x 
          clc 
          adc #3 
          sta PARAM4 
          lda #39 
          sta PARAM5 
          jsr DrawBeamHSegment 
          
++ 
          ;diagonal left 
          pla 
          pha 
          tay 
          lda SPRITE_ACTIVE + 4,x 
          beq ++ 
          
          lda BEAM_CHAR_NESW,y 
          sta PARAM1 
          lda SPRITE_CHAR_POS_X,x 
          sec 
          sbc #1 
          sta PARAM3 
          lda SPRITE_CHAR_POS_Y,x 
          clc 
          adc #8 
          sta PARAM4 
          jsr DrawBeamDiagonalLLUR 
          
++ 
          pla 
          tay 
          lda SPRITE_ACTIVE + 5,x 
          beq ++ 
          
          lda BEAM_CHAR_NWSE,y 
          sta PARAM1 
          lda SPRITE_CHAR_POS_X,x 
          clc 
          adc #2 
          sta PARAM3 
          lda SPRITE_CHAR_POS_Y,x 
          clc 
          adc #8 
          sta PARAM4 
          jsr DrawBeamDiagonalULLR 
          
++ 
          rts

Firing the beams (and restoring background) is handled by new sub routines:


;PARAM1 = beam h char
;PARAM2 = beam color
;PARAM3 = x char pos
;PARAM4 = y char pos
!zone DrawBeamDiagonalLLUR
DrawBeamDiagonalLLUR
.NextLine 
          ldy PARAM4 
          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 
          
          ;left 
          ldy PARAM3 
          lda PARAM1 
          sta (ZEROPAGE_POINTER_1),y 
          lda PARAM2 
          sta (ZEROPAGE_POINTER_2),y 
          inc PARAM4 
          lda PARAM4 
          cmp #22 
          beq .LowerPartDone 
          
          ;left border reached? 
          lda PARAM3 
          beq .LowerPartDone 
          
          dec PARAM3 
          jmp .NextLine
          
.LowerPartDone 
          rts 
          
          ;PARAM3 = x char pos;PARAM4 = y char pos
!zone RestoreBeamDiagonalLLUR
RestoreBeamDiagonalLLUR
.NextLine 
          ldy PARAM4 
          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 
          clc 
          adc #( ( SCREEN_COLOR - SCREEN_CHAR ) >> 8 ) 
          sta ZEROPAGE_POINTER_2 + 1 
          sec 
          sbc #( ( SCREEN_COLOR - SCREEN_BACK_CHAR ) >> 8 ) 
          sta ZEROPAGE_POINTER_3 + 1 
          sec 
          sbc #( ( SCREEN_BACK_CHAR - SCREEN_BACK_COLOR ) >> 8 ) 
          sta ZEROPAGE_POINTER_4 + 1 
          
          ;left 
          ldy PARAM3 
          lda (ZEROPAGE_POINTER_3),y 
          sta (ZEROPAGE_POINTER_1),y 
          lda (ZEROPAGE_POINTER_4),y 
          sta (ZEROPAGE_POINTER_2),y 
          inc PARAM4 
          lda PARAM4 
          cmp #22 
          beq .LowerPartDone 
          
          ;left border reached? 
          lda PARAM3 
          beq .LowerPartDone 
          
          dec PARAM3 
          jmp .NextLine
          
.LowerPartDone 
          rts
          
          ;PARAM1 = beam h char;PARAM2 = beam color;PARAM3 = x char pos;PARAM4 = y char pos
!zone DrawBeamDiagonalULLR
DrawBeamDiagonalULLR
.NextLine 
          ldy PARAM4 
          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 
          ldy PARAM3 
          lda PARAM1 
          sta (ZEROPAGE_POINTER_1),y 
          lda PARAM2 
          sta (ZEROPAGE_POINTER_2),y 
          inc PARAM4 
          lda PARAM4 
          cmp #22 
          beq .LowerPartDone 
          
          ;left border reached? 
          lda PARAM3 
          cmp #39 
          beq .LowerPartDone 
          
          inc PARAM3 
          jmp .NextLine
          
.LowerPartDone 
          rts 
          
          ;PARAM3 = x char pos;PARAM4 = y char pos
!zone RestoreBeamDiagonalULLR
RestoreBeamDiagonalULLR
.NextLine 
          ldy PARAM4 
          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 
          clc 
          adc #( ( SCREEN_COLOR - SCREEN_CHAR ) >> 8 ) 
          sta ZEROPAGE_POINTER_2 + 1 
          sec 
          sbc #( ( SCREEN_COLOR - SCREEN_BACK_CHAR ) >> 8 ) 
          sta ZEROPAGE_POINTER_3 + 1 
          sec 
          sbc #( ( SCREEN_BACK_CHAR - SCREEN_BACK_COLOR ) >> 8 ) 
          sta ZEROPAGE_POINTER_4 + 1 
          
          ldy PARAM3 
          lda (ZEROPAGE_POINTER_3),y 
          sta (ZEROPAGE_POINTER_1),y 
          lda (ZEROPAGE_POINTER_4),y 
          sta (ZEROPAGE_POINTER_2),y 
          inc PARAM4 
          lda PARAM4 
          cmp #22 
          beq .LowerPartDone 
          
          ;left border reached? 
          lda PARAM3 
          cmp #39 
          beq .LowerPartDone 
          
          inc PARAM3 
          jmp .NextLine
          
.LowerPartDone 
          rts


The behaviour of the boss parts is surprisingly simple, just react on being hit:

;------------------------------------------------------------
;boss helper
;------------------------------------------------------------
!zone BehaviourBossHelper
BehaviourBossHelper 
          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 #0 
          sta SPRITE_STATE,x 
          lda #2 
          sta VIC_SPRITE_COLOR,x 
          
.NoHitBack 
          rts


Have fun!

step88.zip

Previous Step Next Step

Previous Entry A C64 Game - Step 87
1 likes 0 comments

Comments

Nobody has left a comment. You can be the first!
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Profile
Author
Advertisement
Advertisement