A C64 Game - Step 6


And onwards we go: Obviously we don't want the player to move through walls. In this step we check the chars in the players way to see if they are blocking.



To make this easier we store the character pos and the character delta pos (0 to 7) for x and y for every sprite (SPRITE_CHAR_POS_X, SPRITE_CHAR_POS_X_DELTA). If the sprite is not at a character brink the move is allowed, if it hits the brink, check the characters at the target.

For this step any character equal or above index 128 is considered blocking, any below is free to move.

The collision code assumes that the collision box of a sprite is one char wide and two chars high.

This step shows:
-calculating character positions while moving about
-checking the position for blocking chars
-calculating the required sprite position from character pos (for starting a sprite at a specific place)

Since the code is basically the same for all four directions I'll only go into details on one of them:

;------------------------------------------------------------
;PlayerMoveLeft
;------------------------------------------------------------
!zone PlayerMoveLeft
PlayerMoveLeft
ldx #0

;check if we are on the brink of a character
lda SPRITE_CHAR_POS_X_DELTA
beq .CheckCanMoveLeft

;no, we are not

.CanMoveLeft
dec SPRITE_CHAR_POS_X_DELTA
jsr MoveSpriteLeft
rts

.CheckCanMoveLeft
lda SPRITE_CHAR_POS_Y_DELTA
beq .NoThirdCharCheckNeeded

;find the character in the screen buffer
ldy SPRITE_CHAR_POS_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 SPRITE_CHAR_POS_X
clc
adc #39 ;39 equals one line down (40 chars) and one to the left (-1)
tay
lda (ZEROPAGE_POINTER_1),y
jsr IsCharBlocking
bne .BlockedLeft

.NoThirdCharCheckNeeded
ldy SPRITE_CHAR_POS_Y
dey
lda SCREEN_LINE_OFFSET_TABLE_LO,y
sta ZEROPAGE_POINTER_1
lda SCREEN_LINE_OFFSET_TABLE_HI,y
sta ZEROPAGE_POINTER_1 + 1
ldy SPRITE_CHAR_POS_X
dey
lda (ZEROPAGE_POINTER_1),y
jsr IsCharBlocking
bne .BlockedLeft

tya
clc
adc #40
tay
lda (ZEROPAGE_POINTER_1),y
jsr IsCharBlocking
bne .BlockedLeft

lda #8
sta SPRITE_CHAR_POS_X_DELTA
dec SPRITE_CHAR_POS_X
jmp .CanMoveLeft

.BlockedLeft
rts



The subroutine IsCharBlocking is rather primitive, as described it only checks if the character is smaller than 128:

;------------------------------------------------------------
;IsCharBlocking
;checks if a char is blocking
;A contains the character
;returns 1 for blocking, 0 for not blocking
;------------------------------------------------------------
!zone IsCharBlocking
IsCharBlocking
cmp #128
bpl .Blocking

lda #0
rts

.Blocking
lda #1
rts




step6.zip