Jump to content

  • Log In with Google      Sign In   
  • Create Account

New Old Things



A C64 Game - Step 74

Posted by , in C64 26 October 2012 - - - - - - · 1,058 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




A C64 Game - Step 73

Posted by , in C64 19 October 2012 - - - - - - · 1,091 views

Nothing new code wise this time, but something necessary: Packing.

The normal file now hits the 40Kb mark, and it's slowly getting too big to simply load. Remember the memory layout?
There is free memory from 2048 to 49151. Above that address the Basic and Kernal are overlayed over RAM. And both are active by default when loading.

Here comes Exomizer to the rescue. It's a cross plattform packer tool targetting old computers with little memory. It compiles code parts, unpacks them to specific memory locations and even takes care of the ROM/RAM settings. Terrific!

In the .zip file there's the executable and a changed .c64 project file. In C64 Studio you'll now find a new build config "Default Crunched". This builds the file as normal and as a post build step calls Exomizer:
$(BuildTargetPath)/exomizer sfx 2064 $(BuildTargetFilename) -t64 -n -o $(BuildTargetPath)/gamecrunched.bin
..and copies over to the original output file name:
copy $(BuildTargetPath)\gamecrunched.bin $(BuildTargetPath)\jmain.prg /Y

The latter step allows us to still debug through the code as usual, since C64 Studio starts the file with the name given in the !to directive.

Attached File  step73.zip (181.65KB)
downloads: 114

Previous Step Next Step


A C64 Game - Step 72

Posted by , in C64 12 October 2012 - - - - - - · 1,108 views

A rather simple step, remember the story page? Now the next chapter text has been put in place, as well as a cool off text after beating the first boss.

Attached Image Attached Image


Analog to the ShowChapter routine we add a ShowChapterEnd routine.

!zone ShowChapterEnd
ShowChapterEnd
		  ;clear screen
		  lda #32
		  ldy #1
		  jsr ClearScreen
		  jsr ResetObjects
		
		  ldy CHAPTER
		  lda CHAPTER_END_PAGES_LO,y
		  sta ZEROPAGE_POINTER_1
		  lda CHAPTER_END_PAGES_HI,y
		  sta ZEROPAGE_POINTER_1 + 1
		
		  lda #0
		  sta VIC_SPRITE_ENABLE
		  sta VIC_SPRITE_X_EXTEND
		  sta SPRITE_POS_X_EXTEND
		
		  lda #1
		  sta PARAM1
		  lda #1
		  sta PARAM2
		  jsr DisplayText
		  jmp StoryLoop


The StoryLoop routine is a part of the original ShowChapter routine doing the car movement and wait for button part. We simply reuse the code.


At the .GotoNextLevel label we add this to actually call the new code.

lda LEVEL_NR
		  cmp #10
		  beq .ShowStory
		  cmp #21
		  beq .ShowStory
		  jmp .NoStory
	  
.ShowStory	  
		  jsr ShowChapterEnd
		  inc CHAPTER
		  jsr ShowChapter
		  pla
		  pla
		
		  lda #$0b
		  sta VIC_CONTROL_MODE
		  jsr StartLevel
		
		  inc LEVEL_NR
		  jsr BuildScreen
		
		  jsr CopyLevelToBackBuffer
		  jsr DisplayGetReady
		
		  lda #$1b
		  sta VIC_CONTROL_MODE		
		  jmp DisplayScoreDisplay		
		
.NoStory


Have fun!



Previous Step Next Step

Attached Files




A C64 Game - Step 71

Posted by , in C64 06 October 2012 - - - - - - · 1,226 views

Now a little polish for Sams dark powers, they were a tad too dark to see ;)

Attached Image

Realistic colors are one thing, but if it hampers the gameplay they have to go. So dark powers are now white.
And animated.


Core routine is this, it redraws every char of the beam with one of four random characters:

;redraw force beam (randomly)
!zone RedrawForceBeam		
RedrawForceBeam		
		  ldy SAM_FORCE_START_Y
		
		  lda SCREEN_LINE_OFFSET_TABLE_LO,y
		  sta ZEROPAGE_POINTER_1
		  lda SCREEN_LINE_OFFSET_TABLE_HI,y
		  sta ZEROPAGE_POINTER_1 + 1
		
		  lda SAM_FORCE_LENGTH
		  sta PARAM1
		
		  ldy SAM_FORCE_START_X
		
-		
		  jsr GenerateRandomNumber
		  and #$03
		  clc
		  adc #252
		  sta (ZEROPAGE_POINTER_1),y
		
		  iny
		  dec PARAM1
		  bne -
		  rts


Most of the other changes include a call to the routine above, some are fixes for crashes that were introduces.

For one, when removing the beam item images could be clipped, a simple call to

jsr RedrawItems

fixes that.


And a little change to gameplay, if Sam moves (falls/jumps) while holding an enemy and moves too far, he loses grip on the enemy.
This is done via a little comparison between the beam start Y pos and the players pos. Too far, and the enemy is released.

;release beam when moving
		  lda SAM_FORCE_START_Y
		  clc
		  adc #1
		  cmp SPRITE_CHAR_POS_Y,x
		  bne .SamNotFirePushed
		
		  ;Sam needs to keep pressed
		  jsr RedrawForceBeam


Have fun!



Previous Step Next Step

Attached Files







October 2012 »

S M T W T F S
 123456
78910111213
14151617181920
21222324252627
28293031   


PARTNERS