4

Basic Sprite Movement

Commodore 64 • Phase 1 • Tier 1

Make your sprite respond to joystick input and move around the screen

⚪ easy
⏱️ 30-45 minutes
đź’» Code Examples
🛠️ Exercise
🎯

Learning Objectives

  • Read joystick input from hardware
  • Move sprites in response to player input
  • Create smooth, responsive movement
  • Experience the joy of interactive control
đź§ 

Key Concepts

CIA chip joystick reading - hardware input Pixel-based movement - smooth positioning Game control loops - responsive interaction Input-to-movement mapping - player control

Basic Sprite Movement

“I can control it! My sprite moves exactly where I want!”

Welcome to the moment when your C64 creation becomes truly interactive! In this lesson, you’ll experience the pure joy of controlling your sprite with the joystick. This is where programming becomes a game!

The Magic You’ll Create

“Incredible! It responds to my every move!”

By the end of this lesson, you’ll have a sprite that moves smoothly around the screen in response to your joystick input. Watch as your yellow sprite glides through the blue background, following your commands perfectly!

Screenshot of completed lesson

Why This Feels So Good

“This is the moment when code becomes alive!”

There’s something magical about the first time you control a sprite with a joystick. It’s the moment when:

  • Your code responds to your actions in real-time
  • The sprite becomes your character on screen
  • Programming transforms from abstract to interactive
  • You feel the power of real-time control

This is the same feeling that millions of C64 users experienced when they first played games like Impossible Mission, Jumpman, or Paradroid!

Understanding Interactive Control

Before we dive into the code, let’s understand what makes this so special:

The Input-Response Loop

Your Input → Hardware → Your Code → Sprite Movement → Screen Update
    ↓            ↓           ↓              ↓              ↓
 Joystick    CIA Chip   Movement      VIC-II Sprite    Visual
  Press      Reading    Calculation    Registers      Feedback

The C64’s Interactive Magic

The C64 was designed for responsive interaction:

  • CIA chip reads joystick input instantly
  • VIC-II chip updates sprite position in real-time
  • 6502 processor handles the logic between them
  • Perfect timing creates smooth, responsive movement

Building Interactive Movement

Let’s build your interactive sprite step by step!

Step 1: The Joystick Reading Magic

“This is how we capture your intentions!”

read_joystick:
        ; Read joystick port 2 (CIA1 Port A)
        lda $dc00              ; Read CIA1 Port A
        sta joystick_state     ; Store current state
        
        ; The bits are "active low" - 0 means pressed
        ; Bit pattern: xxxFRLDU (Fire, Right, Left, Down, Up)
        
        rts

Magic Moment: The CIA chip at $DC00 instantly tells you which direction the joystick is pointing!

Step 2: Converting Input to Movement

“This is where intention becomes action!”

move_sprite:
        ; Check Up (bit 0 clear means pressed)
        lda joystick_state
        and #$01               ; Isolate bit 0
        bne check_down         ; If not 0, button not pressed
        
        ; Move up
        lda sprite_y
        sec                    ; Set carry for subtraction
        sbc #2                 ; Move 2 pixels up
        sta sprite_y
        
check_down:
        ; Check Down (bit 1 clear means pressed)
        lda joystick_state
        and #$02               ; Isolate bit 1
        bne check_left         ; If not 0, button not pressed
        
        ; Move down
        lda sprite_y
        clc                    ; Clear carry for addition
        adc #2                 ; Move 2 pixels down
        sta sprite_y

Magic Moment: Your sprite position variables change based on your joystick input!

Step 3: Four-Way Movement

“This is how we achieve complete control!”

check_left:
        ; Check Left (bit 2 clear means pressed)
        lda joystick_state
        and #$04
        bne check_right
        
        ; Move left
        lda sprite_x
        sec
        sbc #2                 ; Move 2 pixels left
        sta sprite_x
        
check_right:
        ; Check Right (bit 3 clear means pressed)
        lda joystick_state
        and #$08
        bne move_done
        
        ; Move right
        lda sprite_x
        clc
        adc #2                 ; Move 2 pixels right
        sta sprite_x
        
move_done:
        rts

Magic Moment: Your sprite can now move in all four directions!

Step 4: Updating the Hardware

“This is where your calculations become visible!”

update_sprite_position:
        ; Set sprite X position
        lda sprite_x
        sta $d000              ; Sprite 0 X position
        
        ; Set sprite Y position
        lda sprite_y
        sta $d001              ; Sprite 0 Y position
        
        ; Handle X MSB if needed (for X > 255)
        lda sprite_x
        cmp #255
        bcc no_msb
        
        ; Set X MSB
        lda $d010
        ora #$01
        sta $d010
        jmp msb_done
        
no_msb:
        ; Clear X MSB
        lda $d010
        and #$fe
        sta $d010
        
msb_done:
        rts

Magic Moment: The VIC-II chip instantly moves your sprite to the new position!

Step 5: The Interactive Loop

“This is how we create continuous responsiveness!”

game_loop:
        jsr read_joystick          ; Capture your input
        jsr move_sprite            ; Calculate movement
        jsr update_sprite_position ; Make it visible
        jsr wait_frame             ; Perfect timing
        jmp game_loop              ; Continue forever

Magic Moment: Your sprite now responds to your every move in real-time!

Create Your Interactive Experience

Now it’s your turn to feel the magic of interactive control!

Build Your Responsive Sprite

  1. Create the program: All code is in pixel-patrol-04.asm
  2. Build it: Run make clean && make all
  3. Experience the magic: Execute make run

Expected Wonder

When you run this program, prepare to experience:

  • Instant response: Your sprite moves the moment you touch the joystick
  • Smooth movement: 2 pixels per frame creates perfect fluidity
  • Total control: Move in any direction, stop instantly
  • Pure joy: The incredible feeling of “I’m controlling this!”

The Magic Behind the Movement

Why This Feels So Responsive

“This is real-time programming at its finest!”

Your movement system is:

  • Immediate: No delay between input and response
  • Smooth: Consistent 2-pixel movement per frame
  • Precise: Direct pixel-level positioning
  • Continuous: Moves while you hold the joystick
  • Intuitive: Natural directional mapping

The Technical Beauty

What you’ve created is a real-time system:

  • 50 times per second: Your loop runs at 50Hz (PAL)
  • Zero lag: Hardware-level input reading
  • Perfect timing: Synchronized with the display
  • Responsive control: The hallmark of great games

Make It Even More Amazing

Ready to enhance your interactive experience?

Challenge 1: Speed Control

Wonder Goal: “I can make it faster or slower!”

Change the movement speed:

sbc #1                 ; Slower (1 pixel per frame)
sbc #3                 ; Faster (3 pixels per frame)

Challenge 2: Diagonal Movement

Wonder Goal: “I can move diagonally!”

Your sprite already supports diagonal movement! Try holding Up+Right or Down+Left simultaneously.

Challenge 3: Visual Feedback

Wonder Goal: “I can see when I’m moving!”

Add border color changes:

; In move_sprite, add:
lda #$02               ; Red border when moving
sta $d020

What You’ve Achieved

🎉 Congratulations! You’ve mastered interactive sprite control!

The Magic You Conquered

  • ✨ Real-time input - You read hardware directly
  • ✨ Responsive movement - Your sprite obeys instantly
  • ✨ Smooth animation - Perfect pixel-level control
  • ✨ Interactive programming - Code that responds to you
  • ✨ Game control foundations - The basis of all interactive games

Your Programming Journey

You’ve just crossed a major milestone! You’ve created a real-time interactive system - the foundation of every video game ever made. This is the moment when programming becomes truly exciting!

Historical Achievement

You’ve just implemented the same control system used in countless classic C64 games:

  • Jumpman - Platform game character control
  • Impossible Mission - Smooth character movement
  • Paradroid - Robot control and movement
  • Summer Games - Athletic character control

Modern Relevance

The concepts you learned today power:

  • Game engines - Unity, Unreal Engine input systems
  • VR/AR applications - Motion tracking and response
  • Interactive interfaces - Touch and gesture control
  • Real-time systems - Any system that responds to user input

What’s Next?

“Ready to organize your movement into a logical grid?”

In the next lesson, you’ll discover how to add a grid position system to your sprite movement. This will let you track both the smooth pixel position AND the logical grid position - the foundation for game mechanics like collision detection and level design!

Coming Up

  • Create an 8Ă—6 grid overlay system
  • Track both pixel and grid positions simultaneously
  • Calculate grid position from pixel position
  • Display your current grid coordinates
  • Set up the foundation for grid-based game logic

You’re about to learn how professional games organize movement into logical, game-friendly coordinates!

Ready to add intelligence to your movement? Let’s create a grid system!


Technical Reference

CIA Joystick Reading

  • $DC00: CIA1 Port A (joystick port 2)
  • Active low: 0 = pressed, 1 = not pressed
  • Bit mapping: xxxFRLDU (Fire, Right, Left, Down, Up)

Movement Characteristics

  • Speed: 2 pixels per frame
  • Directions: 4-way movement (8-way with diagonals)
  • Response: Immediate (no acceleration)
  • Timing: 50Hz update rate (PAL)

Sprite Position Registers

  • $D000: Sprite 0 X position (low byte)
  • $D001: Sprite 0 Y position
  • $D010: Sprite X MSB register (for X > 255)

Movement Variables

  • sprite_x: Current X position (0-255+)
  • sprite_y: Current Y position (0-255)
  • joystick_state: Current input state

This interactive foundation will serve you throughout your entire C64 programming journey!