An Engine for Multiple Adventures

Category: SDL Adventure Game

The game is in good shape now — it runs on the desktop, on iOS, in a terminal, and in the browser. So I started thinking about what comes next: more adventures. But first the code had to stop being one adventure with the engine baked in.

One hardcoded adventure

The building blocks were already generic — a scene framework, an animation engine, audio — but the adventure itself was hardcoded. A GameScene enum listed the five scenes (intro, playground entrance, playground, outro, example), a switch mapped each value to its Scene, and the init/load/free loops ran over that fixed list. The player was a Fox struct with fox-specific animation fields, and even the puzzle inventory — has_key, has_peg, has_acorns — lived right on it.

To add a second adventure I’d have had to fork all of that. So I didn’t write a second adventure yet; I made the engine able to hold one.

An adventure registry

The first change was to make the engine run an adventure rather than the adventure. I added a small Adventure descriptor — an ordered table of scenes, an entry scene, and where its assets live — and the engine now drives whichever adventure is current. scene_instance() and set_active_scene() take plain indices into the current adventure’s table; the hardcoded enum and switch are gone, and the engine no longer includes a single scene’s header.

The existing game became the first content module, registering itself with the engine. Same scenes, same flow, no gameplay change.

A generic actor

The fox got the same treatment. Instead of a bespoke Fox with walking / talking / sitting / waving fields, there’s now a generic Actor: a small state machine driven by an ActorSpec, which is just data describing a character’s animations, walking speed, footstep sound, and asset folder. The fox is one spec. The next protagonist I have in mind — Gina Gallina, a chicken — will be another spec, not another copy of the movement code. The inventory moved off the actor and into the scenes that use it, so the engine carries nothing adventure-specific.

I kept the name actor on purpose; it’s the word I reached for when I first pulled the fox out into its own thing, and it’s the right one for something positioned, animated, and scripted.

A home per adventure

Finally, some structure. Each adventure now lives in its own directory: src/adventures/vania_fox_the_slide/ holds its scenes, its actor spec, and an assets/ subtree with the sprites, sounds, and .anim files. Only the shared engine stays under src/. Adding an adventure is, by construction, adding a directory.

None of this changed how the slide puzzle plays — that was the whole point of doing it as a refactor. But the engine is finally an engine. Next up: a small hub to choose an adventure, and then Gina’s story.