One game in active development, one shelved for now, and a shelf of prototypes that
taught us how to make the first two.
In development
Sentinels of Gleamwood
A controller-first 2D action roguelite in the Dead Cells and Hades lineage. Built in
Unity 6 for Windows, coming to Steam.
Steam page not open yetWishlisting opens when the store page goes live.
A blade, a bow, and a meter
Your kit is two slots wide. Grounded hits build juggle points; at sixty the enemy
launches and hangs at the apex for eight tenths of a second, which is exactly as
long as your air combo gets. Executions run on a separate meter and land on the
swing after the one that fills it. Each enemy can be executed once.
Statuses are keys
Ignite and Sticky Arrows do damage over time, and they also unlock finishers. Three
arrow stacks then a dash gets you an Explosion. Set something alight and follow
with steel for a Firestorm. Pierce an airborne enemy and it leaves through the side
of the screen.
Movement you have to buy
The wall jump and the dash cost 200 Gleam each at the hub. The generator knows what you own and refuses to build rooms you can't clear,
so buying one visibly widens the game.
You keep your Gleam when you die
Gleam comes home whether you clear the run or die in the second biome. Spend it at
the hub Shopkeeper on Vigor, Might, Honed Edge, movement, and permanent weapon
unlocks. Weapon upgrades inside a run are run-scoped and never touch the shared
definition.
02
What one hit actually does
Every hit in the game walks the same eleven steps in the same order. Describe a hit
with the switches and the spine below shows which steps it runs, which it skips, and
which it never reaches.
01
A dead enemy ignores the hit. The hit is timestamped.
applied
02
Execution readiness is captured now, before this hit's points are added.
applied
03
Meters accrue. Juggle points only while the enemy is grounded. Execution points always.
applied
04
On-hit statuses apply.
applied
05
Feedback fires: hitstop, hit flash, the prefab's hurt sound.
applied
06
Damage applies, and only when MaxHealth is above zero.
applied
07
If readiness was captured true, the execution fires.
applied
08
At zero health the enemy dies. Death wins over juggle, armor and hitstun.
applied
09
An air hit on an already juggled enemy resets its juggle points. This is the anti-infinite rule.
applied
10
A full juggle meter launches the enemy from any state, armor or not.
applied
11
Super armor is consulted last and suppresses the hitstun only. Otherwise the enemy enters hitstun.
applied
Outcome: Set the switches above to resolve a hit.
Figure 2.1. The order is the point. Readiness is captured
at step 02 but spent at step 07, which is why the finisher lands on the swing after
the one that fills the meter rather than on the swing that fills it.
The world
Ten biomes. You'll see five to seven.
The Emberfall Clearing is always first and the Demon King is always last. What comes
between is a branching web, and you choose the route at every rest.
The Emberfall ClearingGreyboxAlways first
Emberfall DepthsGreybox
The CinderwayGreybox
The Ashen VaultsGreybox
The Pyre CrownGreybox
The Sunken MireGreybox
The Splintered SpireGreybox
The Hollow DeepGreybox
GalewatchGreybox
The Demon KingGreyboxAlways last
Level art is still greybox. The biomes already differ in size, branching and enemy
roster. They do not yet differ in appearance. That, and the remaining bosses, are
what we are building now.
Bosses
Three authored, seven slots open
Every biome has a boss arena and every arena generates. Three of them have a fight
authored in. The other seven still build the corridor, seal the doors and spawn the
adds, and then stop, because the fight itself is data that has not been written yet.
Boss roster, by state
Slot
Kit
State
Krag
Lunges and slams, and turns over into a second phase at half health.
Authored
The Cinder Shepherd
Relocates between perches and calls waves of adds. Reaching him means going through them.
Authored
The Pyre Regent
A straight sword fight until half health, when the arena's fire columns light.
Authored
Seven further slots
Arena, corridor, sealed doors and staggered adds all generate. No boss definition.
Not authored
Figure 7.1. A boss is a definition, not a special case in
the code, which is why an empty slot degrades to an arena full of adds rather than to a
crash. Conversations rotate per encounter and the count persists in your save.
The authoring
Where the writing will go
Dialogue, boss conversations and the story panels are content. A writer opens a
text file, or the authoring tool inside the editor, types the lines, and the game
reads them on the next launch. There is no programmer in that loop and there is no
rebuild.
The shape is four levels deep and it is the same everywhere in the game. A dialogue
set belongs to one speaker and holds every beat that speaker has. A beat is keyed
by a trigger, so an intro and a victory line advance independently. Inside a beat,
encounters rotate, so the first time you meet someone you get the first encounter
and the fourth time you get whatever the writer put there for the fourth time.
The rotation persists in the save file, keyed to the dialogue id. That is why a
boss can open with something different on your second run, and it is a content
decision rather than a code change.
The writing for this game has not been done yet. What sits beside this paragraph is
the surface it will arrive through, with the fields left empty and the keys already
in place. The importer, the save binding and the rotation are finished and covered
by the test suite. The words are the part that is missing, and nothing in the
engineering is waiting on them.
Dialogue/Boss_Example.ini
; A set belongs to one speaker.[Dialogue:boss-example]speaker =
portrait =
; Beats are keyed by trigger.[Beat:boss-example/intro]; Encounter 1, first meeting.line.1 =
line.2 =
; Encounter 2, and so on.line.1 =
[Beat:boss-example/defeat]line.1 =
Every key on that file is one the game already reads. Dialogue is also tier three
of the five modding tiers, so a translator works through the same surface the
writers do, with no Unity and no compiler.
Under the hood
Tuned as data
Every enemy is a finite state machine authored as data: states, transitions,
conditions, attack phases, armour budgets and reactions, all as ScriptableObject
sub-assets. Most of the shipped roster needed no new engine code, because a new
enemy is usually a new arrangement of parts that already exist.
The run web, all ten biomes, every boss and their tunables live in a single text
file that an editor command imports and validates. A typo raises an error and
leaves the field alone rather than silently wiping the wiring.
Levels are a pure function of your seed, so a suspended run regenerates instead of
serialising geometry. And before a layout ships, a reachability auditor floods it
using the shipped controller's real movement numbers. It sweeps the same collider
box and the same jump arc the player has, so generation cannot strand you behind a
gap you are unable to clear.
657PlayMode tests passing
9Enemy definitions
5Modding tiers
2Validators, one a build gate
Modding
Rebuild the whole run without opening Unity
Five override tiers, all plain text sitting next to the executable. Retune an enemy
or declare a brand-new behaviour graph. Clone a weapon and rewrite its combo. Translate
every line of dialogue. Reskin the player. Or re-web the entire game, choosing which
biomes appear, in what order, where it branches and where it ends.
A mod is a campaign, and a save slot is bound to one the moment it's created, so
a save from one campaign cannot be opened by another. Every template ships generated
from the live build and carries the real current values, so the templates stay in
step with the game.
Mods/mycampaign/RunWeb.ini
[Plan]entry = start
[Node:start]biome = emberfall
rest = Rest_EmberTrail
next = t2-a, t2-b, t2-c
[Node:t2-b]biome = ashen-vaults
rest = Rest_EmberTrail
next = t3-b, t3-c
; skip the fight, and the reward with itbypass = t3-a
Also from the studio
A top-down arcade shooter in Unreal Engine 4, with 187 C++ files in the game
module. Behaviour trees drive the enemies, with custom tasks, services and
decorators, weight-based swarm evaluation and a shared target distributor. On top
of that sit a combat director and an encounter subsystem that decide what shows up
and when.
Shifter was a team project, and the parts we wrote are the player pawn and its
controller, the AI movement component and controller, the combat director, and the
encounter subsystem. Development is paused while Gleamwood has our attention.
Earlier work
Prototypes and experiments
The things that taught us what we know, all of them open source.
GGJ 2018 prototype
Infected
A Global Game Jam 2018 submission. Fast-paced gameplay created during the 48-hour
game jam challenge.