• entries
    104
  • comments
    101
  • views
    256235

A C64 Game - Step 60

Sign in to follow this  

1679 views

And here's boss #3. Good luck!

step60.png

A note to the latter code additions: If you wonder about the +(+) and -(-) labels, they are relative labels. They basically work like this: If a jmp or other reference is encountered, the compiler looks forward (+) or backward(-) for the first matching location. The +/- labels can be reused.
This avoids all annoying loop23, otherloop14b, etc. labels.

This boss has a vertical beam again, but this time only downwards. So here's a specialised check routine:

;------------------------------------------------------------
;check player vs. beam
; beam boss index in x
; player index in y
; PARAM5 = beam start Y
;------------------------------------------------------------
!zone CheckIsPlayerCollidingWithBeamV
CheckIsPlayerCollidingWithBeamV
          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

          ;compare char positions in x
          lda SPRITE_CHAR_POS_X,x
          cmp SPRITE_CHAR_POS_X,y
          beq .XMatch

          clc
          adc #1
          cmp SPRITE_CHAR_POS_X,y
          beq .XMatch

          sec
          sbc #2
          cmp SPRITE_CHAR_POS_X,y
          beq .XMatch

          ;not hit
          rts

.XMatch
          ;compare char positions in y
          lda SPRITE_CHAR_POS_Y,x
          cmp SPRITE_CHAR_POS_Y,y
          bmi .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_SAM
          bne .PlayerWasDean

          ;reset Sam specific variables
          lda #0
          sta SPRITE_HELD

.PlayerWasDean
          rts


Code reuse and refactoring from the first boss gives us a routine to draw a vertical beam:

!zone DrawBeamV
DrawBeamV
          ldy PARAM4
          ldx PARAM5

.NextLine
          lda SCREEN_LINE_OFFSET_TABLE_LO,x
          sta ZEROPAGE_POINTER_1
          sta ZEROPAGE_POINTER_2
          lda SCREEN_LINE_OFFSET_TABLE_HI,x
          sta ZEROPAGE_POINTER_1 + 1
          clc
          adc #( ( SCREEN_COLOR - SCREEN_CHAR ) >> 8 )
          sta ZEROPAGE_POINTER_2 + 1

          lda PARAM2
          sta (ZEROPAGE_POINTER_1),y
          lda PARAM3
          sta (ZEROPAGE_POINTER_2),y

          inx
          cpx #22
          bne .NextLine
          
          ldx PARAM6
          rts


And the rather complicated behaviour. The boss has two major states. One, where it flies horizontally and tries to home in on a player, and second, once a player has been seen, shoot downwards.

;------------------------------------------------------------
;boss 3
;state 1 = shoot
;state 128 = follow player
;state 129 = shoot, hitback active
;------------------------------------------------------------
!zone BehaviourBoss3
BehaviourBoss3
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 #129
          bne .NoHitBack

          lda #1
          sta SPRITE_STATE,x

.NoHitBack
          lda SPRITE_STATE,x
          and #$7f
          beq .FollowPlayer
          ;shoot state
          jmp .ShootDown

.FollowPlayer
          ;above player?
          txa
          and #$01
          tay
          lda SPRITE_ACTIVE,y
          cmp #TYPE_PLAYER_DEAN
          beq .FoundPlayer
          cmp #TYPE_PLAYER_SAM
          beq .FoundPlayer

          ;check other player
          tya
          eor #1
          tay
          lda SPRITE_ACTIVE,y
          cmp #TYPE_PLAYER_DEAN
          beq .FoundPlayer
          cmp #TYPE_PLAYER_SAM
          beq .FoundPlayer

          ;no player to hunt
          rts

.FoundPlayer
          ;player index in y
          lda SPRITE_CHAR_POS_X,y
          cmp SPRITE_CHAR_POS_X,x
          bne +
          ;enter attack mode
          lda #1
          sta SPRITE_STATE,x
          lda #0
          sta SPRITE_MODE_POS,x
          rts
          
+
          lda DELAYED_GENERIC_COUNTER
          and #$01
          beq +

          rts

+
          ;y swing
          inc SPRITE_MOVE_POS_Y,x
          lda SPRITE_MOVE_POS_Y,x
          and #15
          sta SPRITE_MOVE_POS_Y,x

          ldy SPRITE_MOVE_POS_Y,x
          lda PATH_DY,y
          beq .NoYMoveNeeded
          sta PARAM1
          and #$80
          beq .MoveDown

          ;move up
          lda PARAM1
          and #$7f
          sta PARAM1
.MoveUp
          jsr ObjectMoveUp
          dec PARAM1
          bne .MoveUp

          jmp BossFollowPlayerX

.MoveDown
          jsr ObjectMoveDown
          dec PARAM1
          bne .MoveDown
.NoYMoveNeeded
          jmp BossFollowPlayerX

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

.NextAttackStep
          lda #0
          sta SPRITE_ANNOYED,x
          lda SPRITE_CHAR_POS_X,x
          sta PARAM4
          lda SPRITE_CHAR_POS_Y,x
          sta PARAM5
          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 CheckIsPlayerCollidingWithBeamV
          ldy #1
          jsr CheckIsPlayerCollidingWithBeamV

.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

.HandleBeam
          lda BEAM_CHAR_H,y
          sta PARAM1
          lda BEAM_CHAR_V,y
          sta PARAM2
          lda BEAM_COLOR,y
          sta PARAM3

          txa
          pha
          jsr DrawBeamV
          pla
          tax
          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

.BeamEnd
          jsr RestoreBeamHV

          lda #128
          sta SPRITE_STATE,x
          rts


Plus the usual table additions which I don't list here.

Have fun!

step60.zip

Previous Step Next Step

Sign in to follow this  


1 Comment


Recommended Comments

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

Sign in

Already have an account? Sign in here.

Sign In Now