Sprite Grid Movement
Commodore 64 • Phase 1 • Tier 1
Convert grid positions back to pixel positions for snap-to-grid movement
Learning Objectives
- Convert grid positions to pixel positions
- Create snap-to-grid movement
- Build discrete grid-based controls
- Experience precision grid movement
Key Concepts
Sprite Grid Movement
“My sprite snaps perfectly from cell to cell!”
Welcome to the world of precise, grid-based movement! In this lesson, you’ll reverse the process from lesson 5, converting grid positions back to pixel positions to create that satisfying snap-to-grid movement found in classic puzzle games and RPGs.
The Magic You’ll Create
“Perfect! Every move is exactly one grid cell!”
By the end of this lesson, your sprite will move in discrete grid steps - no more continuous pixel movement. Press a direction and your sprite will snap cleanly from one grid cell to the next, just like Pac-Man or Sokoban!
Why Grid Movement Matters
“This is the foundation of strategic gameplay!”
Grid-based movement is essential for:
- Puzzle games - Sokoban, Tetris, sliding block puzzles
- RPGs - Turn-based movement and positioning
- Strategy games - Unit positioning and tactical gameplay
- Board games - Chess, checkers, and board game adaptations
Grid movement creates precision, strategy, and predictability - the opposite of free-form pixel movement!
Understanding Grid-to-Pixel Conversion
Before we build it, let’s understand the mathematical magic:
The Reverse Process
In lesson 5: Pixel Position → Grid Position (division by 32) In lesson 6: Grid Position → Pixel Position (multiplication by 32)
The Multiplication Trick
Just like we used bit shifting for division, we can use it for multiplication:
- Pixel X = Grid X Ă— 32
- Pixel Y = (Grid Y Ă— 32) + 50
But we’ll use left shifts (ASL) instead of multiplication!
Building Grid-Based Movement
Let’s create that satisfying snap-to-grid movement!
Step 1: Grid-to-Pixel Conversion
“This is how we reverse the coordinate transformation!”
convert_grid_to_pixels:
; Convert grid X to pixel X
; pixel_x = grid_x * 32
lda grid_x
asl ; Multiply by 2
asl ; Multiply by 4
asl ; Multiply by 8
asl ; Multiply by 16
asl ; Multiply by 32
sta sprite_x
; Convert grid Y to pixel Y
; pixel_y = (grid_y * 32) + 50
lda grid_y
asl ; Multiply by 2
asl ; Multiply by 4
asl ; Multiply by 8
asl ; Multiply by 16
asl ; Multiply by 32
clc
adc #50 ; Add screen offset
sta sprite_y
rts
Magic Moment: Five ASL instructions = multiply by 32! The reverse of our division trick!
Step 2: Grid-Based Input Processing
“This is how we make discrete movement decisions!”
process_grid_movement:
; Read joystick input
jsr read_joystick
; Only process if we have input
lda joystick_state
cmp #$ff ; All bits set = no input
beq no_movement
; Check each direction for grid movement
jsr check_grid_up
jsr check_grid_down
jsr check_grid_left
jsr check_grid_right
no_movement:
rts
Magic Moment: We only move when there’s input, and we move exactly one grid cell!
Step 3: Discrete Direction Checking
“This is how we create precise, one-cell movements!”
check_grid_up:
; Check Up (bit 0 clear means pressed)
lda joystick_state
and #$01
bne not_up
; Move up one grid cell
lda grid_y
beq not_up ; Can't move up from row 0
dec grid_y ; Move up one grid cell
not_up:
rts
check_grid_down:
; Check Down (bit 1 clear means pressed)
lda joystick_state
and #$02
bne not_down
; Move down one grid cell
lda grid_y
cmp #5 ; Maximum row (0-5)
beq not_down ; Can't move down from row 5
inc grid_y ; Move down one grid cell
not_down:
rts
Magic Moment: Your sprite moves exactly one grid cell per input, with boundary checking!
Step 4: Complete Grid Movement
“This is how we handle all four directions with precision!”
check_grid_left:
; Check Left (bit 2 clear means pressed)
lda joystick_state
and #$04
bne not_left
; Move left one grid cell
lda grid_x
beq not_left ; Can't move left from column 0
dec grid_x ; Move left one grid cell
not_left:
rts
check_grid_right:
; Check Right (bit 3 clear means pressed)
lda joystick_state
and #$08
bne not_right
; Move right one grid cell
lda grid_x
cmp #7 ; Maximum column (0-7)
beq not_right ; Can't move right from column 7
inc grid_x ; Move right one grid cell
not_right:
rts
Magic Moment: Perfect grid movement with automatic boundary checking!
Step 5: The Grid Movement Loop
“This is how we create responsive grid-based gameplay!”
game_loop:
jsr process_grid_movement ; Handle grid-based input
jsr convert_grid_to_pixels ; Convert to pixel coordinates
jsr update_sprite_position ; Update hardware
jsr display_current_position ; Show grid position
jsr wait_frame
jmp game_loop
Magic Moment: Your sprite now moves in perfect grid steps!
Create Your Grid-Based Game
Now it’s your turn to experience the precision of grid movement!
Build Your Grid-Perfect Sprite
- Create the program: All code is in
pixel-patrol-06.asm
- Build it: Run
make clean && make all
- Experience the precision: Execute
make run
Expected Wonder
When you run this program, you’ll experience:
- Discrete movement: Each joystick press moves exactly one grid cell
- Perfect alignment: Your sprite always sits perfectly in grid cells
- Strategic positioning: You can plan moves precisely
- Boundary respect: Can’t move outside the 8×6 grid
- The satisfaction: “Every move is exactly where I expect!”
Understanding Grid Movement Magic
The Power of Discrete Movement
“This is strategic gameplay at its finest!”
Grid movement creates:
- Predictability: Every move is exactly one cell
- Strategy: You can plan sequences of moves
- Precision: No “almost there” positions
- Clarity: Your position is always unambiguous
The Mathematical Beauty
Your position conversion works perfectly:
- Grid (3,2) → Pixel (96,114): 3×32=96, 2×32+50=114
- Grid (7,5) → Pixel (224,210): 7×32=224, 5×32+50=210
- Always centered: Sprite sits in the middle of each cell
Bit Shifting for Multiplication
Why ASL works for multiplication:
Original: 00000011 (3)
ASL #1: 00000110 (6) Ă— 2
ASL #2: 00001100 (12) Ă— 4
ASL #3: 00011000 (24) Ă— 8
ASL #4: 00110000 (48) Ă— 16
ASL #5: 01100000 (96) Ă— 32 = Grid 3 becomes pixel 96!
Make It Even More Amazing
Ready to enhance your grid-based gameplay?
Challenge 1: Movement Animation
Wonder Goal: “My sprite animates between grid cells!”
Add smooth movement between grid positions:
; Instead of instant teleportation,
; animate sprite from old position to new position
; over several frames
Challenge 2: Grid Overlay
Wonder Goal: “I can see the grid on screen!”
Draw grid lines:
; Use character graphics to draw grid lines
; every 32 pixels horizontally and vertically
Challenge 3: Turn-Based Movement
Wonder Goal: “I can only move on my turn!”
Add turn-based mechanics:
; Only accept input on specific frames
; Create turn-based gameplay rhythm
Challenge 4: Multiple Sprites
Wonder Goal: “Multiple sprites move on the grid!”
Add a second sprite:
; Create player_grid_x/y and enemy_grid_x/y
; Both sprites use the same grid system
What You’ve Achieved
🎉 Congratulations! You’ve mastered grid-based movement!
The Precision You Created
- ✨ Discrete movement - Perfect one-cell-per-move precision
- ✨ Grid-to-pixel conversion - Reverse coordinate transformation
- ✨ Boundary checking - Automatic grid limit enforcement
- ✨ Strategic positioning - Foundation for tactical gameplay
- ✨ Bit shifting multiplication - Fast mathematical operations
Your Programming Journey
You’ve just implemented the movement system that powers countless classic games! This discrete, grid-based movement is the foundation of strategic gameplay, puzzle mechanics, and tactical positioning.
Historical Achievement
You’ve just implemented the same movement system used in:
- Pac-Man - Precise maze navigation
- Sokoban - Strategic box-pushing puzzles
- Rogue - Dungeon exploration RPGs
- Chess programs - Precise piece positioning
Modern Relevance
This grid movement concept powers:
- Puzzle games - Modern match-3 and sliding puzzles
- Strategy games - Turn-based tactical games
- Board game adaptations - Digital board games
- Level editors - Precise object placement tools
What’s Next?
“Ready to add boundaries and constraints to your movement?”
In the next lesson, you’ll learn how to implement movement constraints - invisible walls, boundaries, and collision detection. This will teach you how to create levels with walls, obstacles, and strategic constraints!
Coming Up
- Implement boundary checking and walls
- Create invisible collision barriers
- Add level design constraints
- Build the foundation for maze-like gameplay
- Experience the precision of constrained movement
You’re about to learn how games create walls, mazes, and strategic obstacles that make gameplay challenging and interesting!
Ready to master movement constraints? Let’s build some walls!
Technical Reference
Grid-to-Pixel Conversion
- Pixel X: grid_x Ă— 32 (multiply by 32)
- Pixel Y: (grid_y Ă— 32) + 50 (multiply by 32, add offset)
- Bit shifting: 5 ASL instructions = multiply by 32
Grid Movement Characteristics
- Movement unit: Exactly one grid cell
- Input response: One move per input press
- Boundary checking: Automatic grid limit enforcement
- Precision: Always perfectly aligned
Grid Boundaries
- X range: 0-7 (8 columns)
- Y range: 0-5 (6 rows)
- Pixel coverage: 256Ă—192 pixels
- Cell size: 32Ă—32 pixels each
Movement Variables
- grid_x/y: Logical position (0-7, 0-5)
- sprite_x/y: Pixel position (calculated)
- Direction checking: One move per input
This grid movement foundation will serve you in every game that needs strategic, precise positioning!