Skip to content

Sprite Movement with Bounds

Move sprites with joystick input and play area boundary clamping. Foundation for player control.

Taught in Game 1, Unit 2 spritesmovementboundsjoystick

Overview

Amiga sprites move by updating their control words each frame. Read the joystick, apply movement with boundary checks, then recalculate the sprite’s position registers. The 68000’s signed comparisons make bounds checking straightforward.

Code

; =============================================================================
; SPRITE MOVEMENT WITH BOUNDS - AMIGA
; Move sprite with joystick and boundary clamping
; Taught: Game 1 (Signal), Unit 2
; CPU: ~60 cycles | Memory: ~50 bytes
; =============================================================================

MOVE_SPEED      equ 2           ; Pixels per frame

; Play area boundaries
MIN_X           equ 48          ; Left edge
MAX_X           equ 280         ; Right edge
MIN_Y           equ 44          ; Top edge
MAX_Y           equ 196         ; Bottom edge

; Move sprite based on decoded joystick input
; Input: D0 = decoded joystick (from read_joystick)
;        Bit 8 = up, Bit 0 = down
;        Bit 9 = left, Bit 1 = right
move_frog:
            ; === Check Up ===
            btst    #8,d0
            beq.s   .no_up
            move.w  frog_y,d1
            sub.w   #MOVE_SPEED,d1
            cmp.w   #MIN_Y,d1
            blt.s   .no_up          ; Past top boundary
            move.w  d1,frog_y
.no_up:
            ; === Check Down ===
            btst    #0,d0
            beq.s   .no_down
            move.w  frog_y,d1
            add.w   #MOVE_SPEED,d1
            cmp.w   #MAX_Y,d1
            bgt.s   .no_down        ; Past bottom boundary
            move.w  d1,frog_y
.no_down:
            ; === Check Left ===
            btst    #9,d0
            beq.s   .no_left
            move.w  frog_x,d1
            sub.w   #MOVE_SPEED,d1
            cmp.w   #MIN_X,d1
            blt.s   .no_left        ; Past left boundary
            move.w  d1,frog_x
.no_left:
            ; === Check Right ===
            btst    #1,d0
            beq.s   .no_right
            move.w  frog_x,d1
            add.w   #MOVE_SPEED,d1
            cmp.w   #MAX_X,d1
            bgt.s   .no_right       ; Past right boundary
            move.w  d1,frog_x
.no_right:
            rts

frog_x:     dc.w    160             ; Current X position
frog_y:     dc.w    180             ; Current Y position

Trade-offs

AspectCost
CPU~60 cycles
Memory~50 bytes
LimitationMust call update_sprite after to see changes

When to use: Any game with joystick-controlled sprites.

When to avoid: Mouse-controlled games - read mouse deltas instead.

How Signed Comparisons Work

The 68000’s CMP and Bcc instructions handle signed values naturally:

ConditionBranchUse Case
BLTLess than (signed)Check against minimum
BGTGreater than (signed)Check against maximum
BLELess or equalInclusive minimum
BGEGreater or equalInclusive maximum

This is simpler than 6502 where you must track carry/overflow manually.

Complete Movement Loop

mainloop:
            bsr     wait_vblank
            bsr     read_joystick   ; D0 = joystick state
            bsr     move_frog       ; Update position
            bsr     update_sprite   ; Recalculate control words
            bra     mainloop

Adjusting Boundaries

For different play areas or sprite sizes:

SPRITE_WIDTH    equ 16
SPRITE_HEIGHT   equ 16

; Account for sprite size in boundaries
MAX_X           equ 320-SPRITE_WIDTH
MAX_Y           equ 256-SPRITE_HEIGHT

Patterns: Joystick Reading, Sprite Control Words

Vault: Commodore Amiga