A C64 Game - Step 4


Now we take a bigger step: Moving the sprite with the joystick. Since we want to make a real game we also allow to move the sprite over to the right side (in other words we'll take care of the extended x bit).

For clarification: The C64 has 8 hardware sprites. That's 8 objects of the size 24 x 21 pixels. They can be placed anywhere. The coordinates are stored in memory addresses. However since the X resolution is higher than 256 all the sprites 9th bit is stored in another memory location (which makes it highly annoying to work with).
Sprite coordinates are set in X, Y pairs via the memory locations 53248 (=X sprite 0), 53249 (=Y sprite 0), 53250 (=X sprite 1), etc. The extended sprite bits are stored in 53248 + 16.

Since I don't plan to allow sprites to go off screen in the game later there is no defined behaviour if you move the sprite off screen too far. It'll simply bounce back in once the coordinate wraps around.

The joystick ports can be checked via the memory locations 56320 (Port 2) or 56321 (Port 1). The lower 5 bits are cleared(!) if either up, down, left, right for fire is pressed.


This step shows:
-Joystick control
-Sprite extended x bit



Inside the GameLoop we add a call to the players control function:

          jsr PlayerControl



PlayerControl itself checks the joystick port (II) and calls the proper direction move routines. Note that the move routines themselves simply set the object index to 0 (for the player) and call a generic sprite move routine.


          ;------------------------------------------------------------
;check joystick (player control)
;------------------------------------------------------------
!zone PlayerControl
PlayerControl
lda #$2
bit $dc00
bne .NotDownPressed
jsr PlayerMoveDown

.NotDownPressed
lda #$1
bit $dc00
bne .NotUpPressed
jsr PlayerMoveUp

.NotUpPressed
lda #$4
bit $dc00
bne .NotLeftPressed
jsr PlayerMoveLeft

.NotLeftPressed
lda #$8
bit $dc00
bne .NotRightPressed
jsr PlayerMoveRight

.NotRightPressed
rts

PlayerMoveLeft
ldx #0
jsr MoveSpriteLeft
rts

PlayerMoveRight
ldx #0
jsr MoveSpriteRight
rts

PlayerMoveUp
ldx #0
jsr MoveSpriteUp
rts

PlayerMoveDown
ldx #0
jsr MoveSpriteDown
rts



The sprite move routines are rather simple, update the position counter variables and set the actual sprite registers. A bit more complicated are the X move functions. If X reaches the wraparound, the extended x bit (the 9th bit) is looked up in a table and then added/removed.


          ;------------------------------------------------------------
;Move Sprite Left
;expect x as sprite index (0 to 7)
;------------------------------------------------------------
!zone MoveSpriteLeft
MoveSpriteLeft
dec SPRITE_POS_X,x
bpl .NoChangeInExtendedFlag
lda BIT_TABLE,x
eor #$ff
and SPRITE_POS_X_EXTEND
sta SPRITE_POS_X_EXTEND
sta VIC_SPRITE_X_EXTEND
.NoChangeInExtendedFlag
txa
asl
tay
lda SPRITE_POS_X,x
sta VIC_SPRITE_X_POS,y
rts

;------------------------------------------------------------
;Move Sprite Right
;expect x as sprite index (0 to 7)
;------------------------------------------------------------
!zone MoveSpriteRight
MoveSpriteRight
inc SPRITE_POS_X,x
lda SPRITE_POS_X,x
bne .NoChangeInExtendedFlag
lda BIT_TABLE,x
ora SPRITE_POS_X_EXTEND
sta SPRITE_POS_X_EXTEND
sta VIC_SPRITE_X_EXTEND
.NoChangeInExtendedFlag
txa
asl
tay
lda SPRITE_POS_X,x
sta VIC_SPRITE_X_POS,y
rts

;------------------------------------------------------------
;Move Sprite Up
;expect x as sprite index (0 to 7)
;------------------------------------------------------------
!zone MoveSpriteUp
MoveSpriteUp
dec SPRITE_POS_Y,x
txa
asl
tay
lda SPRITE_POS_Y,x
sta 53249,y
rts

;------------------------------------------------------------
;Move Sprite Down
;expect x as sprite index (0 to 7)
;------------------------------------------------------------
!zone MoveSpriteDown
MoveSpriteDown
inc SPRITE_POS_Y,x
txa
asl
tay
lda SPRITE_POS_Y,x
sta 53249,y
rts




step4.zip