Alias ArchiveArchive in progress
Archive in progress

Web Combat Specimen: From the Main Game to a Deployable Demo

Website Production Notes01 / SERIES

A record of extracting Watchman's movement, attacks, evasion, poise break, and execution loop into a web demo, including asset boundaries, feel calibration, Web export, and loading interaction.

Filed
Field
Other
Edition
EN / Reading copy
The Watchman web combat specimen inside the Games page
The combat specimen is embedded in the project archive rather than presented as a separate promotional page.

I wanted the Games page to contain something genuinely playable, but the goal was not to build a miniature edition of Watchman. A more useful approach was to extract the smallest complete combat loop from the main game: the character can move and jump, attack and evade; the enemy has poise and becomes executable after a stance break; roughly one minute of interaction is enough to communicate the basic rhythm.

The resulting demo runs directly in a browser. Visitors do not need Godot or a game client. Before it felt like the main game, however, it went through several familiar failures: the character walked backwards, attacks caused sliding, the enemy appeared to teleport, the platform blocked movement but could not be landed on, point-blank attacks dealt no damage, rapid inputs were occasionally dropped, and keyboard control still required an extra click after loading.

These problems all point to the same conclusion: when combat feel is ported, running is only the minimum requirement; the real test is whether the behaviour still obeys the contracts of the main game.

The combat specimen is embedded in the Games page and can be played in-browser to test movement, attacks, evasion, stance breaks, and executions.Play the demo on Games ↗

Objective: port one loop, not the whole game

The scope was deliberately narrow: a fixed level and attack value, one simple enemy, one raised platform, and six necessary actions—move, jump, attack, evade, break poise, and execute. The demo does not read saves or connect to quests, equipment, maps, or progression, and it does not share runtime scripts with the main game.

This serves two purposes. The web package remains small enough for static hosting, and the demo can be verified in isolation rather than silently depending on every future change in the main project.

Port map from the main game to the web combat specimen

Isolation does not mean reinvention. The demo has a minimal scene and controller of its own, but animation assets, frame data, audio, typography, and essential combat rules still treat the main game as their source of truth. It is a slice of the game, not a second development branch.

Asset boundary: an allowlist, not a copied directory

Copying the project directory would have been faster and much harder to control. Unrelated resources, editor caches, and main-game scripts would enter the web package together, making it difficult to answer a basic question: what does this demo actually use?

The final solution is an explicit allowlist. The sync script copies only 31 items from the main project: player idle, run, jump, evade, attack, hit, and death animations; the small enemy’s animations and manifest; five forest background layers; the pixel font; and audio for swings, hits, breaks, rolls, death, growls, and execution. Nothing outside the list enters the demo.

This apparently simple file-management step establishes the most important engineering boundary. Every dependency can be named and inspected, then synchronized again when an approved source asset changes.

The first implementation: functional, but unlike the game

The first build ran quickly and exposed its problems just as quickly. The character faced the wrong way, movement carried inertia absent from the game, attacks slid across the floor, and landing on the raised platform left the player fixed on a crouched frame. The enemy shifted abruptly on contact, attacks failed at very close range, and one hit caused an excessively long stagger. Audio, damage numbers, and the existing pixel font were also missing.

These were not independent cosmetic bugs. They were the result of substituting familiar platform-game approximations for Watchman’s actual rules.

Visible symptomUnderlying causeCorrection
Character walks backwardsSprite-facing convention differs from the generic assumptionRead and preserve the main game’s orientation rule
Attack causes slidingThe attack state does not own horizontal movementFreeze or constrain movement according to the main state
Enemy appears to teleportA blocking body collision was added even though the game has noneRemove body pushing; retain only hit and hurt interactions
Platform cannot be landed on / landing freezes a crouch frameOne-way platform, landing detection, and animation state are entangledSeparate landing logic from animation-state changes
Point-blank attack missesThe hit test relies too heavily on facing and centre distanceUse attack reach and allow zero-distance overlap
Every hit causes a long staggerThe player’s poise contract was omittedRestore poise and shorten ordinary hit stun
Porting boundary

If a prototype is playable but does not feel like the main game, stop polishing it. Return to orientation, state timing, collision layers, attack reach, poise, and movement rules; do not cover an incorrect premise with more patches.

Returning to the source: extracting combat contracts

The repair no longer worked backwards from the demo’s appearance. It compared each behaviour directly with the main project. Character animation returned to the existing frame data and foot anchors. Movement during attacks, hitstop, and knockback were arranged around the original state logic. Blocking body collision was removed from the enemy, allowing the two characters to approach and overlap; contact matters only when an attack actually lands.

Poise returned to the loop as well. Ordinary hits reduce it without placing the target in a long stagger every time. Only when poise reaches zero does the enemy enter a broken state and become executable. Execution detection is wider than ordinary attack reach: pressing F makes the player approach the performance position automatically before the execution begins, rather than demanding pixel-perfect placement.

Rapid attacks received an input buffer of roughly 0.35 seconds. If the player presses attack again before the current animation is finished, the command is retained and triggered when the follow-up window opens. The buffer does not make the combo faster; it prevents a valid rapid input from disappearing between frames.

The running web combat demo with player, enemy, health, stamina, and poise displays
The running specimen retains health, stamina, and poise information; execution follows a broken state rather than an ordinary hit.

The main game’s audio, damage numbers, and pixel font were also restored. Their earlier absence was not a limitation of the web platform; they had been treated incorrectly as decoration to add later. Swing audio, hitstop, floating values, and letterforms all participate in feedback. Removing any one of them makes the action feel thinner.

Web packaging: placing the engine behind the archive

Once isolated, the Godot scene exports as a browser-executable Web build. The current package contains seven files and is about 10.6 MiB. Its WebAssembly body is distributed as a gzipped static file and decompressed locally through the browser’s DecompressionStream. Visitors need only a modern browser with WebAssembly support; Godot does not have to be installed.

The Games page does not download those 10.6 MiB on arrival. It first presents an archive-style launch panel. Only after the visitor chooses to enter the combat specimen does the page create the iframe and begin loading. People who do not play incur no game-resource cost, and the page’s initial render remains independent of the engine.

Godot’s native loader is hidden behind a loading bridge that matches the archive. The outer page listens to real download progress and displays the current package and percentage. When the inner engine finishes initialization, it sends a ready message through postMessage, and the page reveals the canvas. Failure retains an explanation and retry path instead of ending on an unexplained black screen.

The custom Godot web-demo loading bridge showing 98 percent real progress
The native loader is replaced by an archive-style bridge; the displayed 98 percent is real transfer progress, not a decorative animation.

The last issue occurred after loading had already succeeded. On desktop, keyboard input did nothing until the game frame received another mouse click because focus remained in the outer page. The ready signal now transfers focus to the iframe, and the inner page explicitly focuses the Godot canvas. The original launch click can therefore continue naturally into game control.

Verification: automated boundaries, manual feel

No single kind of test is sufficient here. Build and automated checks verify resource paths, static output, page states, and the message bridge. Desktop and mobile previews cover dimensions, fullscreen behaviour, scrolling, loading failure, and keyboard focus. Movement, attack timing, point-blank hits, platform landings, stance breaks, and executions still require continuous hands-on play.

The most valuable reports were the ones automation finds difficult to phrase: “movement has inertia,” “the attack slides,” “the enemy looks like it teleports,” and “the execution range is wrong.” These are not vague opinions. They are difference reports between the main game’s feel and the port. Translating each difference into a state, collision, or timing problem is what completes the port.

Conclusion: a demo as a specimen of combat contracts

Working rules
  • Reduce scope, not rules: retain only one loop, but source every behaviour inside it from the main game.
  • Admit assets through an allowlist: keep size, provenance, and update paths inspectable.
  • Resolve presentation failures at the contract layer: orientation, collision, poise, input buffering, and execution movement cannot be approximated by appearance.
  • Make the engine obey the web experience: lazy loading, real progress, recovery, and focus handoff are part of the demo itself.
  • Automation protects engineering boundaries; manual play decides whether the feel survives.

The value of the web demo is not merely that the website now contains a game. It separates Watchman’s smallest set of combat contracts from the complete project and forces every implicit rule to become explainable, testable, and deployable. As the main game changes, the specimen can remain a direct comparison point—not a showcase of everything, but a check that the most basic combat rhythm still holds.

Related reading

04 / LINKS
C01

Combat Feel Design: Stance Breaks, Executions, and Pacing

How Watchman uses stance, stance breaks, executions, and parry windows to establish the weight of Soulslike combat.

Read post ↗
C02

Asset Pipeline: Repacking, Manifests, and Management Tools

Purchasing assets is only the beginning; the real cost of hundreds of packs lies in atlas repacking, manifest generation, and long-term management.

Read post ↗
C03

AI-Assisted Pixel Boss Production: The Stone Giant Pipeline

A production note on moving from incompatible high-resolution concept art to a game-ready pixel boss, including style anchoring, animation constraints, and iteration failures.

Read post ↗
C04

Building Alias Archive: Multi-Agent Collaboration, Astro Migration, and Static Delivery

A complete account of Alias Archive, from its anonymous content boundary and four-field trilingual model to agent handoffs, Astro migration, Impeccable-led interface refinement, and Cloudflare Pages delivery.

Read post ↗