Jump to content

  • Log In with Google      Sign In   
  • Create Account





A C64 Game - Step 88

Posted by Endurion, in C64 23 February 2013 · 661 views

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.

Attached Image

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!

Previous Step Next Step

Attached Files






December 2014 »

S M T W T F S
 123456
78910111213
14151617181920
21 22 2324252627
28293031   
PARTNERS