Jump to content

  • Log In with Google      Sign In   
  • Create Account





A C64 Game - Step 74

Posted by Endurion, in C64 26 October 2012 · 780 views

Another boss!

And one, that works differently than the others before him.

Attached Image

This boss is spawning bats that fly left/right and vanish once hitting the screen border.
Thus we remove the path-8-flying bat and replace it by a simple attacking bat:

!zone BehaviourBatAttacking
BehaviourBatAttacking
		  lda DELAYED_GENERIC_COUNTER
		  and #$03
		  bne .NoAnimUpdate
		
		  inc SPRITE_ANIM_POS,x
		  lda SPRITE_ANIM_POS,x
		  and #$03
		  sta SPRITE_ANIM_POS,x
		
		  tay
		  lda BAT_ANIMATION,y
		  sta SPRITE_POINTER_BASE,x
		
.NoAnimUpdate		
		  lda #3
		  sta PARAM1
		  lda SPRITE_DIRECTION,x
		  beq .MoveRight
.MoveLeft
		  jsr ObjectMoveLeft
		  dec PARAM1
		  bne .MoveLeft
		  jmp .XMoveDone
		
.MoveRight
		  jsr ObjectMoveRight
		  dec PARAM1
		  bne .MoveRight
		
.XMoveDone
		  lda SPRITE_CHAR_POS_X,x
		  cmp #255
		  beq .RemoveMe
		  cmp #39
		  beq .RemoveMe
		  rts
		
.RemoveMe
		  inc SPAWN_NO_ITEM
		  jsr KillEnemy
		  dec SPAWN_NO_ITEM
		  rts


The boss itself is not really clever. It calculates a random y position, moves there, spawns bats and starts all over again. Note that it is only vulnerable while spawning bats though Posted Image
Remember, vulnerability is controlled by having the MSB set in SPRITE_STATE,x.

;------------------------------------------------------------
;boss #5
;state 0 = find target Y
;state 1 = move towards target Y
;state 2 = attack
;state 3 = cool off
;------------------------------------------------------------
!zone BehaviourBoss5
BehaviourBoss5
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
		  lda #1
		  sta VIC_SPRITE_COLOR,x
		  ;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
		
.NoAnimUpdate  
		  lda SPRITE_STATE,x
		  bne +
		  jmp .FindTargetY
+		
		  cmp #1
		  beq .MoveTowardsTarget
		  cmp #2
		  beq .Attack
		  cmp #3
		  beq .CoolOff
		
		  lda #0
		  sta SPRITE_STATE,x
		  rts
		
.CoolOff
		  inc SPRITE_MODE_POS,x
		  lda SPRITE_MODE_POS,x
		  cmp #30
		  bne +
		
		  lda #0
		  sta SPRITE_STATE,x
		
+		
		  rts
		
.Attack
		  inc SPRITE_MOVE_POS,x
		  lda SPRITE_MOVE_POS,x
		  and #$1f
		  cmp #$1f
		  beq +
		  rts
		
+		
		  ;free bats
		  inc SPRITE_MODE_POS,x
		  lda SPRITE_MODE_POS,x
		  cmp #5
		  bne +
		
		  inc SPRITE_STATE,x
		  lda #0
		  sta SPRITE_MODE_POS,x
		  rts
		
+		
		  lda SPRITE_CHAR_POS_X,x
		  sta PARAM1
		  lda SPRITE_CHAR_POS_Y,x
		  sta PARAM2
		  inc PARAM2
		  stx PARAM10
		  jsr FindEmptySpriteSlot
		  beq ++
		
		  lda #TYPE_BAT_ATTACKING
		  sta PARAM3
		  jsr SpawnObject
		  lda #0
		  sta SPRITE_DIRECTION,x
		  jsr FindEmptySpriteSlot
		  beq ++
		  jsr SpawnObject
		  lda #1
		  sta SPRITE_DIRECTION,x
		
++		
		  ldx PARAM10
		  rts
		
		
.MoveTowardsTarget
		  ;player index in y
		  lda SPRITE_VALUE,x
		  cmp SPRITE_CHAR_POS_Y,x
		  bne +

		  ;arrived at target Y
		  inc SPRITE_STATE,x
		  lda #0
		  sta SPRITE_MODE_POS,x
		  rts
		
+		
		  bpl .MoveDown
		
		  ;move up?
		  lda SPRITE_DIRECTION_Y,x
		  bne .AlreadyLookingUp
		  lda SPRITE_MOVE_POS_Y,x
		  beq .TurnUNow
		  dec SPRITE_MOVE_POS_Y,x
		  bne .DoGhostMove
		
.TurnUNow		
		  ;turning now
		  lda #1
		  sta SPRITE_DIRECTION_Y,x
		  jmp .DoGhostMove
		
.AlreadyLookingUp
		  lda SPRITE_MOVE_POS_Y,x
		  cmp #BOSS_MOVE_SPEED
		  beq .DoGhostMove
		  inc SPRITE_MOVE_POS_Y,x
		  jmp .DoGhostMove
		
.MoveDown
		  lda SPRITE_DIRECTION_Y,x
		  beq .AlreadyLookingDown
		
		  lda SPRITE_MOVE_POS_Y,x
		  beq .TurnDNow
		  dec SPRITE_MOVE_POS_Y,x
		  bne .DoGhostMove
		
		  ;turning now
.TurnDNow		
		  lda #0
		  sta SPRITE_DIRECTION_Y,x
		  jmp .DoGhostMove
		
.AlreadyLookingDown
		  lda SPRITE_MOVE_POS_Y,x
		  cmp #BOSS_MOVE_SPEED
		  beq .DoGhostMove
		  inc SPRITE_MOVE_POS_Y,x
		  jmp .DoGhostMove
.DoGhostMove
		  ;move X times
		  ldy SPRITE_MOVE_POS_Y,x
		  sty PARAM4
		  beq .MoveDone
		
		  lda SPRITE_DIRECTION_Y,x
		  beq .DoDown
.MoveLoopU
		  jsr ObjectMoveUpBlocking
		  dec PARAM4
		  bne .MoveLoopU
		  jmp .MoveDone
		
.DoDown
.MoveLoopD
		  jsr ObjectMoveDownBlockingNoPlatform
		  dec PARAM4
		  bne .MoveLoopD
		
.MoveDone	  
		  rts
		
.FindTargetY
		  lda #4
		  sta PARAM5
		  lda #18
		  sta PARAM6
		  jsr GenerateRangedRandom
		  sta SPRITE_VALUE,x
		  inc SPRITE_STATE,x
		  rts

For the boss routine we require a little utility function which returns a ranged random number. No division or module means manual work: create random number, subtract range until it's small enough, then add the lower range.


;lower end = PARAM5		
;higher end = PARAM6
GenerateRangedRandom
		  lda PARAM6
		  sec
		  sbc PARAM5
		  clc
		  adc #1
		  sta PARAM6
		  jsr GenerateRandomNumber
.CheckValue		
		  cmp PARAM6
		  bcc .ValueOk
		
		  ;too high
		  sec
		  sbc PARAM6
		  jmp .CheckValue
.ValueOk
		  clc
		  adc PARAM5
		  rts


Have fun!



Previous Step Next Step

Attached Files






December 2014 »

S M T W T F S
 123456
78910111213
14151617181920
212223242526 27
28293031   
PARTNERS