🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

A C64 Game - Step 56

posted in New Old Things
Published June 16, 2012
Advertisement

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 #0bne .NoHitBack

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

          lda #0
          sta SPRITE_STATE,x

.NoHitBack
          lda DELAYED_GENERIC_COUNTER
          and #$03bne .NoAnimUpdate

          ;lda SPRITE_POINTER_BASE,x;eor #$01;sta SPRITE_POINTER_BASE,x

.NoAnimUpdate
          lda SPRITE_STATE,x
          and #$7f
          bne .NotFollowPlayer
          jmp BossFollowPlayer

.NotFollowPlayercmp #1beq .AttackMode
          rts

.AttackMode;Attack modes (more modes?)
          inc SPRITE_MOVE_POS,x
          lda SPRITE_MOVE_POS,x
          cmp #4beq .NextAttackStep
          rts

.NextAttackStep
          lda #0
          sta SPRITE_MOVE_POS,x
          inc SPRITE_MODE_POS,x

          lda SPRITE_MODE_POS,x
          cmp #11bcc .BeamNotDangerous
          cmp #29bcs .BeamNotDangerous
;does player hit beam?
          ldy #0
          jsr CheckIsPlayerCollidingWithDiagonalBeam
          ldy #1
          jsr CheckIsPlayerCollidingWithDiagonalBeam

.BeamNotDangerous
          lda SPRITE_MODE_POS,x
          cmp #11beq .BeamStep1
          cmp #12beq .BeamStep2
          cmp #13beq .BeamStep3
          cmp #16beq .BeamStep4
          cmp #17beq .BeamStep3
          cmp #18beq .BeamStep4
          cmp #19beq .BeamStep3
          cmp #20beq .BeamStep4
          cmp #21beq .BeamStep3
          cmp #22beq .BeamStep4
          cmp #23beq .BeamStep3
          cmp #24beq .BeamStep4
          cmp #25beq .BeamStep3
          cmp #26beq .BeamStep4
          cmp #27beq .BeamStep3
          cmp #28beq .BeamStep4
          cmp #29beq .BeamStep3
          cmp #30beq .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 #38beq .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 #22beq .LowerPartDone

          ;left border reached?
          lda PARAM7
          beq .LeftDoneBottom
          dec PARAM7
.LeftDoneBottom
          lda PARAM8
          beq .RightEndReachedBottom
          cmp #38beq .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 + 1clcadc #( ( 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

.NoRightPartdec 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 + 1clcadc #( ( 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

.NoRightPartBottominc 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 #128bcs .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 #1beq .PlayerHit


          ;not hit
          rts

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

          lda #SPRITE_PLAYER_DEAD
          sta SPRITE_POINTER_BASE,y

          lda #0
          sta SPRITE_MOVE_POS,y

          lda SPRITE_ACTIVE,y
          cmp #TYPE_PLAYER_SAMbne .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!

step56.zip

Previous Step Next Step

Previous Entry A C64 Game - Step 55
0 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