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