Skip to main content
GameDev.net gamedev.net

PRO Tired of ads? Read GameDev.net ad-free and help keep the community independent with GameDev Pro — $3/month.

A C64 Game - Step 6

A C64 Game - Step 6

Endurion
Endurion
New Old Things · · 2 min read
9,098 0

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

Previous Step 5 Next Step 7

Discussion

Loading comments...