7

Movement Constraints

Commodore 64 • Phase 1 • Tier 1

Add boundaries and constraints to create strategic movement limitations

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

Learning Objectives

  • Implement movement boundaries and walls
  • Create invisible collision barriers
  • Add level design constraints
  • Build strategic movement limitations
đź§ 

Key Concepts

Collision detection - boundary checking Level design constraints - walls and barriers Strategic gameplay - movement limitations Coordinate validation - safe movement

Movement Constraints

“Now my sprite respects boundaries and obstacles!”

Welcome to the world of strategic constraints! In this lesson, you’ll add boundaries, walls, and obstacles to your movement system. This is where your sprite learns to respect the game world’s rules and limitations.

The Magic You’ll Create

“Perfect! My sprite can’t move through walls!”

By the end of this lesson, your sprite will respect boundaries and obstacles. Try to move into a wall or forbidden area - your sprite will stay put, following the rules of your game world perfectly!

Screenshot of completed lesson

Why Movement Constraints Matter

“This is how games create challenges and strategy!”

Movement constraints are essential for:

  • Level design - Creating walls, mazes, and boundaries
  • Strategic gameplay - Forcing players to think about positioning
  • Puzzle mechanics - Making certain moves impossible
  • Game balance - Preventing players from going where they shouldn’t

Every game from Pac-Man to Sokoban uses movement constraints to create engaging challenges!

Understanding Constraint Systems

Before we build it, let’s understand how constraints work:

Types of Constraints

  1. Screen boundaries - Can’t move outside the game area
  2. Wall barriers - Solid obstacles that block movement
  3. Forbidden zones - Areas where sprites can’t enter
  4. Conditional barriers - Walls that appear/disappear based on game state

Constraint Checking Process

  1. Plan the move - Where does the sprite want to go?
  2. Check constraints - Is that position valid?
  3. Execute or block - Move if valid, stay if blocked

Building the Constraint System

Let’s add intelligent boundary checking to your movement!

Step 1: Basic Boundary Checking

“This is how we keep sprites in the game area!”

check_boundaries:
        ; Check if new position is within grid bounds
        lda new_grid_x
        cmp #8                 ; Maximum X is 7 (0-7)
        bcs invalid_move       ; If >= 8, invalid
        
        lda new_grid_y
        cmp #6                 ; Maximum Y is 5 (0-5)
        bcs invalid_move       ; If >= 6, invalid
        
        ; Position is valid
        clc                    ; Clear carry = valid
        rts
        
invalid_move:
        sec                    ; Set carry = invalid
        rts

Magic Moment: Your sprite can’t escape the game area!

Step 2: Wall Detection System

“This is how we create solid barriers!”

; Simple wall map - 1 = wall, 0 = empty
wall_map:
        !byte 1,1,1,1,1,1,1,1  ; Row 0: top wall
        !byte 1,0,0,0,0,0,0,1  ; Row 1: side walls
        !byte 1,0,1,1,1,1,0,1  ; Row 2: inner walls
        !byte 1,0,0,0,0,0,0,1  ; Row 3: side walls
        !byte 1,0,1,1,1,1,0,1  ; Row 4: inner walls
        !byte 1,1,1,1,1,1,1,1  ; Row 5: bottom wall

check_wall_collision:
        ; Calculate offset in wall map
        lda new_grid_y
        asl                    ; Multiply by 2
        asl                    ; Multiply by 4
        asl                    ; Multiply by 8 (8 columns per row)
        clc
        adc new_grid_x         ; Add column offset
        tax                    ; Use as index
        
        ; Check if position has a wall
        lda wall_map,x
        beq no_wall            ; 0 = no wall
        
        ; Wall detected
        sec                    ; Set carry = blocked
        rts
        
no_wall:
        clc                    ; Clear carry = valid
        rts

Magic Moment: Your sprite bounces off walls like in a real maze!

Step 3: Complete Constraint Checking

“This is how we validate every move!”

validate_movement:
        ; Store proposed new position
        lda grid_x
        sta old_grid_x
        lda grid_y
        sta old_grid_y
        
        ; Calculate new position based on input
        jsr calculate_new_position
        
        ; Check all constraints
        jsr check_boundaries
        bcs movement_blocked   ; Boundary violation
        
        jsr check_wall_collision
        bcs movement_blocked   ; Wall collision
        
        ; Movement is valid - update position
        lda new_grid_x
        sta grid_x
        lda new_grid_y
        sta grid_y
        clc                    ; Clear carry = success
        rts
        
movement_blocked:
        ; Movement blocked - restore old position
        lda old_grid_x
        sta grid_x
        lda old_grid_y
        sta grid_y
        sec                    ; Set carry = blocked
        rts

Magic Moment: Your sprite follows all the rules perfectly!

Step 4: Direction-Specific Constraint Checking

“This is how we handle each direction intelligently!”

calculate_new_position:
        ; Start with current position
        lda grid_x
        sta new_grid_x
        lda grid_y
        sta new_grid_y
        
        ; Check each direction
        lda joystick_state
        and #$01               ; Up
        bne check_down
        dec new_grid_y         ; Try moving up
        jmp position_calculated
        
check_down:
        lda joystick_state
        and #$02               ; Down
        bne check_left
        inc new_grid_y         ; Try moving down
        jmp position_calculated
        
check_left:
        lda joystick_state
        and #$04               ; Left
        bne check_right
        dec new_grid_x         ; Try moving left
        jmp position_calculated
        
check_right:
        lda joystick_state
        and #$08               ; Right
        bne position_calculated
        inc new_grid_x         ; Try moving right
        
position_calculated:
        rts

Magic Moment: Each direction is checked independently and intelligently!

Step 5: The Constrained Movement Loop

“This is how we create rule-respecting gameplay!”

game_loop:
        jsr read_joystick          ; Get player input
        jsr validate_movement      ; Check if move is legal
        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 respects all game world rules!

Create Your Constrained Game World

Now it’s your turn to build a world with rules and boundaries!

Build Your Rule-Respecting Sprite

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

Expected Wonder

When you run this program, you’ll experience:

  • Boundary respect: Can’t move outside the game area
  • Wall collisions: Sprite stops at walls and barriers
  • Strategic positioning: Must plan moves around obstacles
  • Rule enforcement: Game world has consistent laws
  • The realization: “This feels like a real game world!”

Understanding Constraint Magic

The Power of Limitations

“Constraints create gameplay!”

Movement constraints create:

  • Challenge: Players must think strategically
  • Exploration: Finding paths through obstacles
  • Puzzle solving: Working around barriers
  • Spatial awareness: Understanding the game world

Constraint Checking Efficiency

Your constraint system is efficient:

  • Pre-validation: Check before moving, not after
  • Carry flag: Simple success/failure indication
  • Modular checking: Each constraint type is separate
  • Rollback capability: Can undo invalid moves

Level Design Possibilities

With your constraint system, you can create:

  • Mazes: Complex path-finding challenges
  • Rooms: Separate areas connected by doorways
  • Barriers: Strategic obstacles and choke points
  • Puzzles: Movement-based problem solving

Make It Even More Amazing

Ready to enhance your constraint system?

Challenge 1: Dynamic Walls

Wonder Goal: “Walls can appear and disappear!”

Add walls that change based on conditions:

; Wall appears when sprite is in certain position
; or after certain number of moves
check_dynamic_walls:
        ; Check game state conditions
        ; Modify wall_map based on conditions

Challenge 2: One-Way Barriers

Wonder Goal: “Some barriers only block certain directions!”

Create directional barriers:

; Allow movement in one direction but not the other
; Like one-way doors or force fields

Challenge 3: Visual Wall Indicators

Wonder Goal: “I can see the walls on screen!”

Draw walls using character graphics:

; Use character codes to draw wall tiles
; Show barriers visually on screen

Challenge 4: Conditional Passages

Wonder Goal: “Walls disappear when I have keys!”

Add key-based barriers:

; Track keys/conditions sprite has collected
; Allow movement through certain walls when conditions met

What You’ve Achieved

🎉 Congratulations! You’ve mastered movement constraints!

The Intelligence You Added

  • ✨ Boundary checking - Automatic area limitation
  • ✨ Wall collision detection - Solid barrier implementation
  • ✨ Movement validation - Pre-move legality checking
  • ✨ Strategic constraints - Rule-based gameplay
  • ✨ Level design foundation - Tools for creating game worlds

Your Programming Journey

You’ve just implemented the constraint system that makes games challenging and strategic! This is the foundation of level design, puzzle mechanics, and tactical gameplay.

Historical Achievement

You’ve just implemented the same constraint system used in:

  • Pac-Man - Maze walls and boundary checking
  • Sokoban - Box and wall collision detection
  • Rogue - Dungeon wall and door systems
  • Adventure games - Room boundaries and barriers

Modern Relevance

This constraint system concept powers:

  • Level editors - Collision layer design
  • Physics engines - Collision detection systems
  • Game engines - Tilemap collision systems
  • AI pathfinding - Obstacle avoidance algorithms

What’s Next?

“Ready to add statistics and game state tracking?”

In the final Foundation lesson, you’ll learn how to implement a complete game loop with statistics tracking. This will teach you how to count moves, track time, and display game information - the foundation of all game state management!

Coming Up

  • Implement move counting and statistics
  • Add time tracking and display
  • Create game state management
  • Build information display systems
  • Complete the Foundation phase with a full game loop

You’re about to learn how games track everything that happens and provide feedback to players!

Ready to complete the Foundation phase? Let’s add game statistics!


Technical Reference

Constraint Types

  • Boundary constraints: Grid limits (0-7, 0-5)
  • Wall constraints: Solid barriers in wall_map
  • Conditional constraints: State-based restrictions
  • Directional constraints: One-way barriers

Constraint Checking Process

  1. Calculate new position: Based on input direction
  2. Validate boundaries: Check grid limits
  3. Check wall collisions: Query wall_map
  4. Execute or block: Move if valid, stay if blocked

Wall Map Structure

  • 8Ă—6 grid: Matches sprite movement grid
  • 1 byte per cell: 1 = wall, 0 = empty
  • Linear storage: Row-major order
  • 48 bytes total: Complete level data

Validation Variables

  • new_grid_x/y: Proposed position
  • old_grid_x/y: Backup position
  • Carry flag: Success/failure indicator
  • wall_map: Level collision data

This constraint system foundation will serve you in every game that needs strategic boundaries and obstacles!