October 2, 2025 By WBG Development Team
wildermine refactoring architecture optimization

Wildermine Phase 3: The Big Refactor Begins

After achieving 248x performance gains in Phase 2, we're tackling the riskiest optimizations yet: viewport culling, delta-based history, and architectural improvements

Wildermine Phase 3: The Big Refactor Begins

Wildermine Phase 3: The Big Refactor Begins

After successfully completing Phase 1 and Phase 2 optimizations—achieving 248x faster paint operations and 99.7% memory reduction—we’re now embarking on Phase 3, our most ambitious refactoring effort yet.

This phase targets the architectural foundations of Wildermine’s level editor, with changes that carry higher risk but promise transformational improvements in performance, maintainability, and scalability.

What We’ve Accomplished So Far

Before diving into Phase 3, here’s what we’ve achieved:

Phase 1: Foundation Cleanup ✅

  • Removed dead code and unused imports
  • Added strategic memoization to prevent unnecessary re-renders
  • Cleaned up console noise
  • Improved developer experience

Phase 2: Copy-on-Write Revolution ✅

  • 248.6x faster typical paint strokes (3.296ms → 0.013ms)
  • 543.7x faster raw cloning operations (3.317ms → 0.006ms)
  • 99.7% memory reduction per stroke (168.8 KB → 0.5 KB)
  • 40.8x faster large brush operations (3.372ms → 0.083ms)
  • Consolidated building offset logic into single source of truth
  • Optimized React component re-renders
  • All verified with comprehensive performance test suite (11 tests)

Read the full Phase 2 breakdown →

With these foundations solid, we’re ready for the big changes.

Phase 3: The Challenges Ahead

Phase 3 tackles four major areas, ordered from lowest to highest risk:

1. Viewport Culling Optimizations (Low-Medium Risk)

The Problem: Currently, Wildermine renders all 3,600 tiles (60×60 grid) every frame, even though most are off-screen.

The Solution: Calculate visible viewport bounds and skip rendering tiles outside the camera view, with a small margin to prevent pop-in.

Expected Impact: 2-3x rendering performance improvement

Why It’s Lower Risk: This optimization doesn’t change data structures—it just adds intelligent skipping to the render loop.

2. Delta-Based History System (Medium-High Risk)

The Problem: The undo/redo system currently stores full level clones. Each snapshot contains 3,600 cells × 6 layers = 21,600 values, even when only 10-50 cells changed.

The Solution: Implement a delta-based approach that stores only what changed:

interface HistoryDelta {
  type: 'paint' | 'building' | 'erase';
  cellChanges: {
    x: number;
    y: number;
    layer: number;
    oldValue: TileCode;
    newValue: TileCode
  }[];
  buildingChanges?: {
    added?: BuildingPlacement[];
    removed?: BuildingPlacement[]
  };
}

Instead of storing 3,600 cells per action, we’ll store only the 10-100 cells that actually changed.

Expected Impact: 95%+ memory reduction for history stack

Why It’s Riskier: Changes core undo/redo behavior. Must ensure perfect correctness—any bugs could corrupt level data.

3. Split CanvasRenderer (High Risk)

The Problem: CanvasRenderer.ts is 1,674 lines long and violates single responsibility principle. It mixes terrain rendering, building rendering, effects, and UI logic.

The Solution: Split into four focused classes:

RendererCoordinator (orchestrates rendering pipeline)
├── TerrainRenderer (tiles, autotiles, layers)
├── BuildingRenderer (building sprites, placement)
└── EffectsRenderer (highlights, previews, cursors)

Expected Impact: Better maintainability, easier to add features, potential performance improvements from specialized renderers

Why It’s High Risk: Major architectural change touching critical rendering code. We’re splitting this into four separate sub-tasks (A, B, C, D), each tested and committed independently.

4. Consolidate State Management (High Risk)

The Problem: Currently mixing zustand store + component useState, with manual synchronization creating inconsistencies.

The Solution: Establish clear guidelines—zustand for global editor state, useState for local UI-only state. Remove manual synchronization.

Expected Impact: Cleaner state management, fewer bugs, better developer experience

Why It’s Highest Risk: State management touches every part of the editor. Doing this last, after proving other changes work.

Our Approach: Systematic Risk Management

We learned valuable lessons from Phase 2. When we implemented copy-on-write, we built a comprehensive test harness that gave us confidence the optimization was correct before shipping it.

For Phase 3, we’re applying similar rigor:

One Task at a Time

Each task is worked on, tested, and committed independently. If something breaks, we know exactly what caused it.

Small Blast Radius

For high-risk changes (like splitting CanvasRenderer), we break them into even smaller sub-tasks:

  • Part A: Extract TerrainRenderer → test → commit
  • Part B: Extract BuildingRenderer → test → commit
  • Part C: Extract EffectsRenderer → test → commit
  • Part D: Create RendererCoordinator → test → commit

Comprehensive Testing

After each change, we run:

Functional Tests:

  • Load level editor, create new level
  • Paint terrain with different brush sizes
  • Place all building types
  • Undo/redo 20+ times
  • Switch terrain types, use eraser
  • Save/load level, test in play mode
  • Pan camera, zoom in/out

Performance Tests:

  • React DevTools Profiler during painting
  • Monitor FPS (target: 60fps consistently)
  • Memory usage tracking
  • Verify no memory leaks after 100+ undo/redo

Technical Checks:

  • TypeScript compilation passes
  • No new console errors/warnings
  • Dev server runs cleanly
  • Careful git diff review

Rollback Plans

Every task has a documented rollback plan. Because we commit after each sub-task, we can revert individual changes without losing all progress.

Why This Matters

Performance optimization isn’t just about making things faster—it’s about creating a tool that gets out of the player’s way and lets creativity flow.

Phase 1 and Phase 2 proved that Wildermine’s level editor could be incredibly responsive. Phase 3 will ensure it stays that way as we add more features, larger levels, and more complex tools.

By the time Phase 3 is complete, we expect:

  • 40-60% memory reduction from delta-based history
  • 2-3x rendering performance from viewport culling
  • Much better code organization enabling faster feature development
  • Fewer bugs from cleaner state management
  • Easier onboarding for future contributors

Document-Driven Development with Claude Code

One approach we’re taking with Phase 3 is creating detailed refactoring documents that guide the work. Our 03-optimizations.md document breaks down each task into 10-15 concrete steps with checkboxes, success criteria, risk assessments, and rollback plans.

This serves multiple purposes:

  • Planning: Forces us to think through the entire change before touching code
  • Guidance: Provides step-by-step instructions for implementation
  • Progress Tracking: Clear visibility into what’s done and what remains
  • Documentation: Future maintainers can understand why changes were made

We’re also using AI assistance (Claude Code!) to help execute these plans systematically, with the document serving as a shared roadmap between human and AI collaborators.

What’s Next

We’re about to start Task 1: Viewport Culling—the lowest-risk, highest-visibility win. It should provide an immediate FPS boost and build confidence for the riskier changes ahead.

Stay tuned for Part 2 of this series, where we’ll share the results of Phase 3—the performance metrics, the challenges we encountered, and the lessons learned from this major refactoring effort.

Want to follow along with Wildermine’s development? Check out our other technical deep-dives and progress updates!


Phase 3 at a glance:

  • 🎯 4 major tasks ordered by risk
  • 📉 40-60% memory reduction expected
  • 🚀 2-3x rendering performance improvement
  • 🏗️ Better architecture for long-term maintainability
  • Systematic approach with comprehensive testing
WBG Logo

Written by WBG Development Team

Part of the passionate team at Wrinkled Brain Games, creating innovative gaming experiences.