A C64 Game - Step 34


And another refinement step:
Two new items are added, one for faster reload, another for temporary invincibility. Also, not every kill is getting you an item to collect.



The most interesting new part is the state of a sprite. For now only used for the player, but will be put to good use for enemies as well. The state of an object is used for different behaviour steps, but also to describe, if an object will react to collisions. If the highest bit is set (0x80), an object will not kill the player (or the player cannot be killed).

We'll start by defining the new constants for the items:

;item types
ITEM_FAST_RELOAD = 2
ITEM_INVINCIBLE = 3

;effect counters
PLAYER_FAST_RELOAD
!byte 0

PLAYER_INVINCIBLE
!byte 0

;item images
ITEM_CHAR_UL
!byte 4,8,16,20

ITEM_COLOR_UL
!byte 7,2,1,1

ITEM_CHAR_UR
!byte 5,9,17,21

ITEM_COLOR_UR
!byte 4,2,2,7

ITEM_CHAR_LL
!byte 6,10,18,22

ITEM_COLOR_LL
!byte 7,2,2,7

ITEM_CHAR_LR
!byte 7,11,19,23

ITEM_COLOR_LR
!byte 4,2,2,4



The actual collect item code is simple, we're just setting some new variables. Note the SPRITE_STATE, which is set to 0x80.

.EffectFastReload
lda #200
sta PLAYER_FAST_RELOAD
jmp .RemoveItem

.EffectInvincible
lda #200
sta PLAYER_INVINCIBLE
lda #128
sta SPRITE_STATE
jmp .RemoveItem



Thus the CheckCollision adds a check for the highest bit in SPRITE_STATE, to allow for player invincibility.

CheckCollisions
lda SPRITE_ACTIVE
bne .PlayerIsAlive
rts

.PlayerIsAlive
lda SPRITE_STATE
cmp #128
bmi .IsVulnerable
rts

.IsVulnerable
ldx #1

.CollisionLoop




To visualize the invincibility state we add this code at the start of PlayerControl. If PLAYER_INVINCIBLE is set, the players color is cycled.

          lda PLAYER_INVINCIBLE
beq .NotInvincible

;count down invincibility
inc VIC_SPRITE_COLOR
dec PLAYER_INVINCIBLE
bne .NotInvincible

lda #0
sta SPRITE_STATE
lda #10
sta VIC_SPRITE_COLOR

.NotInvincible
... previous code



In the players reload code we add the double speed reload check:

          ...
lda PLAYER_FAST_RELOAD
beq .NoFastReload

dec PLAYER_FAST_RELOAD

inc PLAYER_STAND_STILL_TIME

.NoFastReload
...



At the location, where we previously always spawned an item we add this:

          ;only spawn item randomly
lda GenerateRandomNumber
and #02
beq .CreateItem

jmp .ShotDone

...

.CreateItem
jsr SpawnItem
jmp .ShotDone



To get things running clean we change a few spots:

On restarting the temporary states need to be reset.

          lda #0
sta PLAYER_FAST_RELOAD
sta PLAYER_INVINCIBLE
sta SPRITE_STATE




step34.zip