From Working Code to Well-Designed Code
In 2019, a p5.js simulation was built to model C.S. Lewis’s Narnia: humans wandered aimlessly, the White Witch froze any human she touched into a gray statue, and Aslan hunted down the nearest statue and revived it. The physics were elastic. The behavior was emergent. It worked.
The Narnia Simulation Saga asks the next question: what does the same simulation look like when you apply OOP principles? Starting from Stage 7 — a clean modern TNT shell with the Stage 6 logic preserved intact — each subsequent stage improves one design decision, explains why, and documents the result.
By the end of the saga, novices will have a working understanding of JavaScript class design, inheritance, encapsulation, and how a well-designed simulation is controlled with a Bootstrap panel.
The story that inspired it all is C.S. Lewis’s The Lion, the Witch and the Wardrobe — published in 1950, the first and most beloved of the Chronicles of Narnia series. If you want to meet the characters before exploring the code, the TNT Narnia movie clip collection features five scenes from the 2005 film: the trailer, the White Witch, Aslan’s sacrifice, his resurrection, and the healing breath — which is exactly what Aslan does in the simulation every time he reaches a frozen Statue.
- Classes and encapsulation — what a class is, what it hides, and why that matters
-
Coupling and global state
— why
Molecoolreading a globalnumStatuesis a design smell, and how to fix it - Constructor functions vs. ES6 classes — the same object, written two ways; what changed and why
-
Dependency ordering
— why
Gridmust load beforeMolecool; how module systems solve this - Control panel design — from a single slider to a full Bootstrap control panel that influences the sketch without touching its drawing logic
The simulation has four kinds of Molecools: Human,
Witch, Lion, and Statue.
They share common behavior — position, velocity, display, collision —
but each has unique behavior. The kind property currently
drives everything with if statements and string comparisons.
The saga’s inheritance goal: replace that pattern with four
subclasses of a base Molecool class, each with its own
setColor(), update(), and
interact() behavior. When you see four if
statements that dispatch on a type string, you are looking at the
problem that inheritance solves.
From 2019 to 2026 — and Beyond
The original Narnia Simulation built in late 2019. Four humans, a White Witch, and Aslan interact on a canvas. Stage 6 introduced intentional direction for Aslan — he seeks the nearest statue and turns red when hunting. All elastic collision physics and character interactions are intact. This is the baseline the SPARK saga improves upon.
Stage 6 logic preserved intact in a modern Bootstrap 5 app with no PHP dependency. CDN p5.js, Narnia-themed hero, two-column layout (canvas + character legend), and a S.P.A.R.K. chat log documenting every design decision. The foundation all future OOP stages build upon.
First OOP improvement: Molecool.setColor() no longer
reads the global numStatues; Grid.display()
no longer reads shouldRefreshBackground.
Slider wiring moves into setup().
Identical simulation behavior; encapsulation introduced.
Grid and Molecool rewritten as true
ES6 class declarations — a
constructor() method and class-body methods shared
via the prototype instead of re-created per instance.
Identical simulation behavior; modern syntax and the structural
foundation for Stage 11 inheritance.
Molecool reads global numStatues;
Grid reads global flag — replace with parameters.
Teaches: encapsulation, parameter passing.
fail-fast pattern) and
the HTML script-order comment together make the
Grid-before-Molecool
dependency explicit without requiring a separate stage.
class syntax
✓ done
Grid and Molecool rewritten
as ES6 classes. Same behavior; modern syntax.
Teaches: class declaration, constructor,
this, prototype chain.
Human, Witch,
Lion, Statue
Replace the kind-string dispatch with four subclasses.
Each overrides setColor() and interact().
Teaches: extends, super(),
polymorphism.