Rapid-fire microgames in the style of WarioWare, made with Godot 4.7.
Each microgame lasts a few seconds. You see a one-word prompt, then you have to work out what to do before the fuse runs out. Win to score, lose to drop a heart. Between games, Wirt (the host, a kid in a floppy cone hat) reacts to how you did.
A run has three stages. Each stage is 10 microgames and then a boss. Every 4 wins within a stage the game speeds up. Beating a boss is worth 5 points and gives a heart back. Losing to a boss costs a heart, and you fight it again. After the third boss the run loops back to stage one, faster and at full difficulty.
| Stage | Look borrowed from | Boss | Boss fight |
|---|---|---|---|
| 1 Graveyard Shift | 8 Bit Evil Returns | Mr Hat | Left/right as Jon, who fires stakes on his own. Dodge top-hat tornadoes and, later, diving bats |
| 2 Tlaloc’s Temple | Tlaloc’s Curse | Tlaloc | Breakout against his stone face. Rain and darts come in the angry phase |
| 3 Snail Lord’s Swamp | 8 Bit Evil Returns + Hemlock’s Tower | Snail Lord | Tap the goo, crows and toads before they crack the screen. Tap him when he comes out of his shell |
Difficulty is 1 in stage one, 2 in stage two and 3 in stage three and every later lap.
| Action | Keyboard | Gamepad | Touch |
|---|---|---|---|
| Move | Arrow keys / WASD | D-pad / left stick | On-screen arrows |
| Action | Space / Z / Enter | A | On-screen A button |
| Pointer games | Mouse | — | Finger |
WirtWare is portrait-first: the game is a 720×1280 (9:16) canvas, laid out for a phone held upright. On phones, each microgame shows only the buttons it needs, along the bottom edge. On tall phones they sit in the spare space under the game. On shorter ones they float over the game’s floor.
Most microgames change their look per stage, using the stage’s art.
| Prompt | Folder | What you do |
|---|---|---|
| DODGE! | dodge |
Move left and right to avoid falling things until time runs out |
| PUMP IT! | pump |
Mash the action button to blow something up until it pops |
| CATCH! | catch |
Slide the basket under the falling treat |
| STOP! | stop |
Press the button while the needle is in the glowing zone |
| POP ‘EM! | pop |
Tap every ghost / spirit / wisp |
| JUMP! | jump |
Jump over the obstacles |
| COPY! | copy |
Press the arrow sequence shown, in order |
| DRAW! | duel |
Wait for “FIRE!”, then shoot. Too early or too late loses |
| LAND! | land |
Hold the button to brake, and touch down slowly |
| SORT! | sort |
Send each item to its bin |
| WHACK! | whack |
Press the arrow that matches the hole something pops out of. A wrong swing loses |
| SCRUB! | scrub |
Hold and scrub the grime off |
| SLICE! | slice |
Swipe through everything before it falls |
| TRACE! | trace |
Drag along a wiggly path from start to finish without leaving it |
| FLICK! | flick |
Flick the ball into the target. One shot |
| FEED! | feed |
Drag each snack into the mouth |
| WIND IT! | crank |
Spin your finger around the crank until the box pops |
| FOLLOW! | follow |
Keep your finger on the wandering light until time runs out |
| SWIPE! | swipe |
Swipe the way each arrow points. Red arrows mean the opposite way |
New ones, each a nod to another game in the Scareathon arcade:
| Prompt | Folder | Homage to | What you do |
|---|---|---|---|
| LEAP! | leap |
Salmon Run 2 | Time the button to leap a salmon up the waterfall steps |
| CARVE! | carve |
Jack O’Lantern | Drag along the dotted face to carve the pumpkin |
| PET IT! | pet |
Cryptlins | Rub the gremlin, but stop when it bares its teeth |
| GLIDE! | glide |
Daughter Of The Wind | Steer the glider through the gaps in the clouds |
| BLAST! | blast |
Denver Vs The Universe | Shoot the saucer before it abducts a building. Shots are limited |
| SLIDE! | slide |
Penguin Slide | Steer the penguin through the slalom gates |
| JAM! | jam |
One Man Band | Hit the button on each note |
| PHONE HOME! | phone |
Phone Home | Mash to pedal until the bike lifts off past the moon |
| SHAKE! | shake |
Snow Globe | Rub back and forth to shake the snow up |
| CLIMB! | climb |
Hemlock’s Tower | Alternate left and right to climb the tower |
scenes/main.tscn Entry scene (just runs scripts/main.gd)
scripts/main.gd Game loop: stages, bosses, intermissions, speed-ups, lives, best score
scripts/stages.gd The three stages: names, colours, art folder, boss
scripts/microgame.gd `Microgame` base class that every game and boss extends
scripts/microgame_fx.gd Sparks and floating words drawn over a microgame
scripts/mascot.gd Wirt, the host, drawn and animated in code
scripts/backdrop.gd The between-games scene for each stage
scripts/sfx.gd Sfx autoload: sound effects, jingles and stage music, made in code
scripts/hearts.gd Lives display
scripts/touch_controls.gd On-screen buttons for phones
art/<stage>/ Pixel art borrowed from the arcade games (sizes in art/sizes.txt)
bosses/<name>/<name>.tscn One folder per boss (named in Stages.THEMES)
microgames/<name>/<name>.tscn One folder per microgame (found automatically)
tools/autopilot.gd Plays by itself, for recording the arcade attract video
tools/shots.gd Saves screenshots every so often, for checking the look
tools/mascot_preview.tscn Wirt in every mood side by side
build/ Web export, served by GitHub Pages
microgames/<name>/<name>.tscn with a Node2D root. Give the root a script that extends Microgame._init():
extends Microgame
func _init() -> void:
prompt = "SHAKE!" # the big instruction word
controls_hint = "ARROW KEYS" # small hint under it
duration = 4.0 # seconds before speed-up
win_on_timeout = false # true for "survive until time's up" games
touch_hint = "TAP THE BUTTON" # hint shown on touch screens instead
controls = Controls.BUTTON # touch buttons: BUTTON, LEFT_RIGHT, ARROWS or POINTER
_on_start(). difficulty (1–3) and stage (0–2) are already set at this point. Stages.theme(stage) gives the stage’s colours, and draw_sprite("graveyard/ghost", frames, anim_frame(8, frames), pos, 4.0) draws its art.win() or lose() when the outcome is decided. Guard input with is_playing().Sfx.play("pop"), burst(pos, color), popup("+1", pos) and shake(12). Main already plays the win/lose sounds and shakes the screen on a loss.BUTTON, LEFT_RIGHT, ARROWS), keep the action above CONTROLS_TOP (y = 1060), because on shorter phones the buttons cover the area below it. POINTER games can use the whole screen.The main loop picks up the new folder automatically. Speed-ups work through Engine.time_scale. Use delta, timers and tweens as normal and they all speed up together.
Command-line options (after --):
| Option | Effect |
|---|---|
--game=<folder> |
Play only that microgame, over and over |
--stage=<0-2> |
Start on that stage |
--games=<n> |
Play n microgames per stage (1 gets to the bosses fast) |
--autopilot |
Start right away and play some games by itself |
--shots=<folder> --every=<s> |
Save a screenshot every s seconds (needs a window, not --headless) |
--mute |
No sound |
godot --path . -- --autopilot --stage=1 --games=1 --shots=C:/tmp/shots --every=0.5 --mute
godot --path . res://tools/mascot_preview.tscn
WirtWare runs as a cabinet in the Scareathon arcade. The page loads https://sclondon.github.io/WirtWare/build/index.html in a 9:16 iframe. At game over the game posts { type: 'PLAYER_DIED', score } to the parent page, where the score is microgames won plus 5 for each boss beaten.
To publish a new build:
godot --headless --path . --export-release "Web" build/index.html
git add build && git commit -m "Update web build" && git push
Then bump the ?v= cache-buster on WIRTWARE_URL in the arcade page (src/pages/Arcade/games.tsx in scareathon-v3) to the new commit hash.
To re-record the attract video, run the game on autopilot with the movie maker, then convert the result to a 540×960 mp4 in public/game-recordings/WirtWare.mp4:
godot --path . --write-movie attract.avi --fixed-fps 30 --resolution 720x1280 --quit-after 560 -- --autopilot