6

Sprite Grid Movement

Commodore 64 • Phase 1 • Tier 1

Convert grid positions back to pixel positions for snap-to-grid movement

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

Learning Objectives

  • Convert grid positions to pixel positions
  • Create snap-to-grid movement
  • Build discrete grid-based controls
  • Experience precision grid movement
đź§ 

Key Concepts

Grid-to-pixel conversion - reverse mathematics Discrete movement - snap-to-grid controls Multiplication by shifting - fast grid math Grid-based game mechanics foundation

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!

Screenshot of completed lesson

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

  1. Create the program: All code is in pixel-patrol-06.asm
  2. Build it: Run make clean && make all
  3. 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!