Skip to content

Value demonstration #177

Description

@bcorfman

ArcadeActions Value Demonstration Plan

Core Philosophy

Every example must answer: "Why is this simpler/better with ArcadeActions than vanilla Arcade?"

Focus on demonstrating clear code savings, architectural improvements, and patterns that leverage Actions' declarative, condition-based approach.

Priority 1: State Machine Design Patterns (HIGH VALUE)

1.1 Conceptual Guide: State Machines + Actions

Target: Intermediate to Advanced

Format: Documentation + Small Examples

Location: docs/state_machine_patterns.md

Content:

  1. Why State Machines? - Problems with complex nested ifs and state flags

  2. State Machine Basics - python-statemachine overview

  3. Pattern Library:

    • Player state patterns (idle/walk/jump/attack)
    • Enemy AI patterns (patrol/chase/attack/flee)
    • Boss phase patterns (intro/phase1/phase2/vulnerable/death)
    • Power-up patterns (inactive/active/expiring)
  4. Integration Patterns:

    • When to use state.on_enter vs action callbacks
    • Guard conditions vs action conditions
    • State-driven animation with CycleTexturesUntil
    • Centralized physics forces in state machine
  5. Common Mistakes:

    • Mixing state flags with state machine
    • Over-complex state machines
    • Wrong level of granularity
  6. Code Snippets: Each pattern as 30-50 line example

1.2 Refactoring Case Study (if time permits)

Target: Advanced

Format: Before/After Example

Location: examples/refactoring_case_study/

Show: Converting a 200-line imperative enemy AI to state machine + Actions

  • before.py - Nested if/state flags version
  • after.py - State machine + Actions version
  • comparison.md - Line count, complexity analysis

Priority 2: Pathfinding Library Integration

2.1 Library Evaluation and Integration

Target: Intermediate to Advanced

Format: Example + Documentation

Tasks:
Create example: examples/pathfinding_chase.py

Example Demonstrates:

  • Grid-based pathfinding with arcade.astar_calculate_path()
  • Converting path to waypoints for FollowPathUntil
  • Dynamic re-pathing when target moves
  • State machine: patrol (fixed path) → chase (dynamic path) → attack
  • Clear separation: pathfinding calculates, Actions executes

Value Proposition:

  • FollowPathUntil handles smooth path following
  • Easy to switch between paths with state transitions
  • Natural integration with state machines

Priority 3: Collision + Callback Patterns

3.1 Collision Detection Comparison

Target: Beginners to Intermediate

Format: Side-by-side example

Location: examples/collision_patterns.py

Show Before/After:

# WITHOUT Actions - Manual tracking
class Bullet:
    def update(self):
        self.center_y += self.speed
        # Check collision every frame
        hits = arcade.check_for_collision_with_list(self, enemy_list)
        if hits:
            for enemy in hits:
                enemy.remove_from_sprite_lists()
            self.remove_from_sprite_lists()
        # Check off-screen
        if self.bottom > WINDOW_HEIGHT:
            self.remove_from_sprite_lists()

# WITH Actions - Declarative
def bullet_collision_check():
    hits = arcade.check_for_collision_with_list(bullet, enemy_list)
    off_screen = bullet.bottom > WINDOW_HEIGHT
    if hits or off_screen:
        return {"hits": hits, "off_screen": off_screen}
    return None

def handle_collision(data):
    bullet.remove_from_sprite_lists()
    for enemy in data["hits"]:
        enemy.remove_from_sprite_lists()

move_until(bullet, velocity=(0, 5), 
          condition=bullet_collision_check, 
          on_stop=handle_collision)

Demonstrates:

  • Single collision check (in condition)
  • Data passing from condition → callback
  • No manual sprite update loops
  • Sound effects in callbacks

3.2 Sound Effect Integration

Target: Beginners

Enhancement: Add to invaders.py and collision_patterns.py

Show:

def handle_explosion(data):
    arcade.play_sound(explosion_sound)
    for enemy in data["hits"]:
        enemy.remove_from_sprite_lists()

Priority 4: CallbackUntil Temporal Patterns

4.1 Temporal Effects Showcase

Target: Intermediate

Location: examples/callback_temporal_effects.py

Demonstrates CallbackUntil advantages:

  1. Periodic State Checks - Check game state every 0.1s instead of per-frame
  2. Timed Sequences - Color cycling, status effect timers
  3. Performance - Interval-based updates for expensive operations
  4. Shader/Particle Updates - Frame-independent updates

Code Examples:

# Periodic enemy spawning
def spawn_wave():
    if len(enemies) < MAX_ENEMIES:
        spawn_enemy()

callback_until(game, spawn_wave, 
              condition=infinite,
              seconds_between_calls=2.0)

# Status effect with state object
class PoisonEffect:
    def __init__(self, target):
        self.target = target
        self.tick_count = 0
        
    def apply_damage(self):
        self.target.health -= 5
        self.tick_count += 1

poison = PoisonEffect(player)
callback_until(player, poison.apply_damage,
              condition=lambda: poison.tick_count >= 10,
              seconds_between_calls=0.5,
              tag="poison")

Priority 5: Complex Behavior Demonstrations

5.1 Boss Battle Example

Target: Advanced

Location: examples/boss_battle.py

Why This Shows Actions Value:

  • State machine for boss phases
  • Complex attack patterns with sequence() + parallel()
  • Vulnerability windows with BlinkUntil
  • Formation spawning with arrange_* functions
  • Pattern transitions based on health

Key Patterns:

# Phase transition in state machine
class BossStateMachine(StateMachine):
    phase1 = State(initial=True)
    phase2 = State()
    vulnerable = State()
    
    take_damage = phase1.to(phase2, cond="health_below_50")
    
    def on_enter_phase2(self):
        # Stop old pattern
        Action.stop_actions_for_target(self.boss, tag="attack")
        # Start new pattern
        self.spawn_minion_wave()
        self.start_spiral_attack()
    
    def spawn_minion_wave(self):
        minions = arrange_circle(
            count=8, center_x=400, center_y=300, radius=200
        )
        # Each minion attacks player
        for minion in minions:
            self.setup_minion_ai(minion)

5.2 State-Based Enemy AI

Target: Intermediate to Advanced

Location: examples/enemy_ai_states.py

Demonstrates:

  • Patrol → Chase → Attack → Flee state machine
  • Manual patrol paths with FollowPathUntil
  • Distance-based state transitions
  • Health-based flee behavior
  • Attack patterns with sequence()

Value Over Vanilla:

  • No nested if statements checking states
  • Clear state transition logic
  • Easy to add new states
  • Animations tied to states with CycleTexturesUntil

Priority 6: Code Comparison Documentation

6.1 Before/After Gallery

Location: docs/code_comparisons.md

Side-by-side examples showing code savings:

  1. Sequential Behavior

    • Before: 30 lines of frame counting and state flags
    • After: 8 lines with sequence()
  2. Parallel Effects

    • Before: Multiple state variables and conditionals
    • After: parallel() composition
  3. Boundary Bounce

    • Before: Manual boundary checking and reversal
    • After: MoveUntil with boundary_behavior="bounce"
  4. Path Following

    • Before: Manual interpolation and rotation
    • After: FollowPathUntil with rotate_with_path=True
  5. Formation Management

    • Before: Nested loops calculating positions
    • After: Single arrange_grid() call

Priority 7: Enhanced Existing Examples

7.1 Enhance invaders.py

  • Add more inline comments explaining why Actions helps
  • Add sound effects with callbacks
  • Document collision + callback pattern

7.2 Enhance pymunk_demo_platformer.py

  • Link back to Arcade's original platformer tutorial
  • Show diff/comparison
  • Highlight state machine benefits
  • Document moving platform integration

7.3 Create pattern_comparison.py

  • Show vanilla Arcade zigzag movement (manual)
  • Show Actions zigzag movement (create_zigzag_pattern)
  • Side-by-side code comparison

Priority 8: SpritePool Advanced Example

8.1 Bullet Hell Demo

Target: Advanced

Location: examples/bullet_hell.py or enhance space_clutter.py

Demonstrates:

  • Managing 1000+ bullets with SpritePool
  • Zero-allocation wave spawning
  • Performance comparison metrics
  • Memory profiling results

Value: Shows real performance benefit of SpritePool

Implementation Roadmap

Phase 1: State Machine Patterns (Weeks 1-2)

  1. Write state machine patterns documentation
  2. Create small pattern examples
  3. Consider refactoring case study

Phase 2: Core Examples (Weeks 3-4)

  1. Pathfinding library integration example
  2. Collision patterns comparison
  3. CallbackUntil temporal effects
  4. Code comparison documentation

Phase 3: Complex Behaviors (Weeks 5-6)

  1. Boss battle example
  2. Enemy AI state machine example
  3. Enhance existing examples with comparisons

Phase 4: Performance (Week 7)

  1. Bullet hell / SpritePool advanced
  2. Performance documentation

Success Criteria

Every deliverable must:

  1. Show clear code reduction or architectural improvement
  2. Include comments explaining "why Actions"
  3. Compare to vanilla Arcade approach (inline or separate)
  4. Demonstrate reusable patterns

Metrics:

  • Line count reduction examples
  • Complexity reduction (cyclomatic complexity)
  • Developer velocity improvements
  • Maintainability improvements

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions