A C64 Game - Step 10


So you found out the enemies couldn't hurt you? Well, we're working towards that goal in this step. We add collision checks. Since I'm not completely sure about later changes we are NOT relying on the VICs collision checks but roll our own. Remember the object size contraints from step #6? We apply those to the object collision checks as well.

We add a new subroutine CheckCollisions which in turn uses IsEnemyCollidingWithPlayer. We do not check for collisions between enemies. The check is not completely exact (behaves more like 9 pixel * 16 pixel), but that's good enough. To test the function a collision is signalled by setting the border color to white.



The routine CheckCollisions is simply added to the main game loop:

GameLoop
jsr WaitFrame
jsr ObjectControl
jsr CheckCollisions
jmp GameLoop



The function CheckCollision just loops through the active object list and calls IsEnemyCollidingWithPlayer for every active entry:

;------------------------------------------------------------
;check object collisions (enemy vs. player etc.)
;x
;------------------------------------------------------------
CheckCollisions
ldx #1
.CollisionLoop
lda SPRITE_ACTIVE,x
bne .CheckObject

.NextObject
inx
cpx #8
bne .CollisionLoop

lda #0
sta VIC_BORDER_COLOR
rts

.CheckObject
stx PARAM2
jsr IsEnemyCollidingWithPlayer
bne .PlayerCollidedWithEnemy

ldx PARAM2
jmp .NextObject

.PlayerCollidedWithEnemy
lda #1
sta VIC_BORDER_COLOR
;ldx #0
;jsr RemoveObject
rts



IsEnemyCollidingWithPlayer employs a few tricks to ease the calculation.
First we do the Y coordinate check to weed out. For the X coordinate: Since the actual X position is 9 bits we half the value (half the X coordinate and add 128 if the extended X bit is set). Now the comparation is easy.
The routine then returns 1 if a collision occurs and 0 if not.

;------------------------------------------------------------
;check object collision with player (object 0)
;x = enemy index
;return a = 1 when colliding, a = 0 when not
;------------------------------------------------------------
!zone IsEnemyCollidingWithPlayer

.CalculateSimpleXPos
;Returns a with simple x pos (x halved + 128 if > 256)
;modifies y
lda BIT_TABLE,x
and SPRITE_POS_X_EXTEND
beq .NoXBit

lda SPRITE_POS_X,x
lsr
clc
adc #128
rts

.NoXBit
lda SPRITE_POS_X,x
lsr
rts

IsEnemyCollidingWithPlayer
;modifies X
;check y pos
lda SPRITE_POS_Y,x
sec
sbc #( OBJECT_HEIGHT )

;offset to bottom
cmp SPRITE_POS_Y
bcs .NotTouching
clc
adc #( OBJECT_HEIGHT + OBJECT_HEIGHT - 1 )
cmp SPRITE_POS_Y
bcc .NotTouching

;X = Index in enemy-table
jsr .CalculateSimpleXPos
sta PARAM1

ldx #0
jsr .CalculateSimpleXPos
sec
sbc #4

;position X-Anfang Player - 12 Pixel
cmp PARAM1
bcs .NotTouching
adc #8
cmp PARAM1
bcc .NotTouching

lda #1
rts

.NotTouching
lda #0
rts




step10.zip