NEON PRECINCT

Manual 4 — Reference

As of 2026-10-03 · Engine team · Release bundle manual/ref.html

Every item of each tool, in section order, with its meaning · unit · default. The “?” in the tools links to the matching section here.

Units and coordinates

TermMeaning
CoordinatesThe screen is 960 wide × 540 tall. Positions and sizes of characters · stages · obstacles are all px on this basis. If you made art on a 480 basis (base 480), the engine supports drawing it at 2× — choose 480 in Character Forge “Name and stats” → “Base resolution” for characters, and in Stage Forge step 8 “Obstacle definitions” → “Base width” for obstacles.
Background art coordinatesA background layer's vertical position (Y) · the floor image position · horizon Y are on a half-size screen (480 × 270). This differs from the floor lines (floor top · bottom), so enter the floor lines first before adding art and the tool aligns it for you.
FrameUnit of time. 1 frame = 1/60 s; 60 frames = 1 s. Startup · active · recovery, cooldowns, invincibility and so on are all in frames.
Floor bandThe strip characters can walk up and down (depth) in — from floor top to floor bottom. Wider makes dodging easier.
DepthDistance in the screen's up-down direction. An attack hits only when depth is close as well as horizontal reach.
GateThe right end of the stage area where a wave ends (horizontal px). The camera stops here, and it opens only after that wave's enemies are all defeated.
Multiplier1 is the default. 2 is double, 0.5 is half.
Damage · HPDamage is subtracted straight from HP. Difficulty (enemy HP · damage multipliers) is applied on top.

Sprite Forge

1 Add images

Add one PNG per action pose. They line up in file name order, and the English word in each file name assigns the action (see the “File names” table in chapter 2).

ItemMeaning · unit · default
FileChoose PNGs Sorted by file name. Transparent PNGs stay as they are; solid backgrounds are Choose several at once. Put the character name in front of the file names (officer_idle_1.png) and that front part becomes the character name.

2 Remove background

Removes the background from images with a solid background. If you add only transparent images, this step doesn't appear.

ItemMeaning · unit · default
ButtonAuto from cornersTreats the color of the image's four corners as background. Usually enough.
ButtonCorner color per imageWhen background colors differ between images — uses each image's own corner color.
ButtonSuggest a background color for next timeSuggests a background color for making new art — one the character doesn't use, so it's removed cleanly.
FileSuggest from concept artAdd one character concept image and it suggests a background color that isn't in that image.
FieldToleranceHow similar a color to the background gets removed. Higher removes more (lower it if edges get eaten). example 60

3 Align and assign

Crops each image to its content, aligns the feet to the same height, and places them in equal cells. This alignment decides how accurate the anchor (foot position) is.

ItemMeaning · unit · default
FieldTarget height (px)The character's height in game (px on the 960 basis). Default 140. Match hero and enemy heights here. example 140
FieldDefault facingWhich way the character in the art faces. The engine flips it for the other direction.
FieldVariant set nameFiles whose names start with v_, contain +, or contain this name go into the variant set (power-up · rage look) cells.

4 Finished sheet

The sheet with cells joined in one row. Download with “Save character JSON” in the bottom bar. “Merge into existing character” replaces only the art (sheet · cell size · anchor · facing) and keeps actions · moves · stats · effects.

5 Pixel cleanup

Generated art is soft art that looks like pixel art. This fits it to pixel rules — remove edge background · fill holes · match colors to reference frames · reduce to a palette · clean alpha. It uses rules only, no trained model.

ItemMeaning · unit · default
ButtonSheet assembled above (step 4)Cleans up the sheet you just made in steps 3 · 4.
FileLoad a sheet imageCleans up an existing sheet image (PNG). Image only, no character JSON.
FileCharacter JSON (to swap art only)Add a character JSON and it cleans that sheet, then puts the result back into the same character, replacing only the art.
FieldFrame count (cell width may be fractional)How many cells to split the sheet into. Cell width = sheet width ÷ frame count. example 1
FieldReference frames (e.g. 0-3)Cell numbers (range) used as the reference for color · size. Usually the idle cells (0-1). Other cells are color-matched to these.
FileLoad palette (.gpl)Uses the same color list (GIMP palette) as another character. Reducing to a loaded palette keeps colors consistent between characters.
ButtonClean upRuns the cleanup with the settings above.
ButtonAfterToggles between before and after cleanup.
ButtonShow filled holesMarks the spots filled by hole filling in color.
Button2×Zoom (2× · 3× · 4×) — view only.
ButtonDark backgroundPreview background color — view only.
ButtonLight backgroundPreview background color — view only.
ButtonPink backgroundPreview background color — good for spotting leftover background specks.
ButtonFoot jitter checkChecks whether the foot position jitters between cells. Find it here when walking · idle look shaky.
ButtonFlicker checkChecks for a color · shape that pops up in just one cell between others.
ButtonShow changesMarks what the cleanup changed.
ButtonCleaned sheet PNGDownloads just the cleaned sheet image.
ButtonPalette .gplDownloads the palette used for cleanup (to use the same colors on another character).
ButtonCharacter JSON (art only)Downloads the loaded character JSON with only the cleaned art put in.
ButtonApply to sheet 4Puts the cleaned art back into the step 4 sheet (then save it as character JSON).

Character Forge

1 Load sprite sheet

Opens a sheet image (PNG) or an existing character JSON. One sheet is one character. Choose an Aseprite JSON along with it to use its cell data as is.

ItemMeaning · unit · default
FileChoose PNG (+ Aseprite JSON optional) One sheet is one character. An existing Character JSChoose one of sheet PNG · character JSON · Aseprite JSON (or PNG + Aseprite JSON).
ButtonKeep settings, replace art onlyKeeps the current settings (actions · moves · stats) and replaces only the sheet art. The cell count must match.

2 Frame split

How many cells to split the sheet into. Detected automatically; fix it if wrong.

ItemMeaning · unit · default
FieldFrame widthWidth of one cell (px). Frame width × frame count = sheet width. example 459
FieldFrame countNumber of cells. example 43

3 Anchor and facing

The anchor is the point under the character's feet — where it touches the floor in game. Facing is the way the character in the art looks.

ItemMeaning · unit · default
FieldCenter XHorizontal position of the anchor within the cell (px). Usually the middle of the body. example 278
FieldFoot YVertical position of the anchor within the cell (px) — the height of the soles. Raise it if the character looks like it floats, lower it if it sinks in. example 196
Button◀ LeftThe character in the art faces left.
ButtonRight ▶The character in the art faces right.

· Name and stats

A small section inside step 3: name · HP · speed · size · behavior.

ItemMeaning · unit · default
FieldDisplay nameThe name shown on screen (HUD · boss name).
Fieldid (letters · numbers)The name that refers to this character in stages · games. Letters · numbers · _ only. If blank, it's made from the display name (a non-colliding code if the name has no Latin letters).
FieldMax HPHP (default 100). Enemy tier · difficulty multipliers are applied. example 180
FieldMove speedWalking speed (px/frame). Characters made in Sprite Forge start at 1.45. For the hero it's handling; for enemies, how fast they chase. example 2.106
FieldDraw scaleScales only the art (hitboxes stay the same). 1 is the default. example 1.1471
FieldRun speed multiplierRun speed = move speed × this value (dashMul). Blank uses the engine default. example 1.754
FieldDash attack multiplierDamage multiplier for attacks while running (dashAtk, default 1.7).
FieldBase resolutionWhich screen size this character was drawn for (base). 960 is the default (pixels around 128px, no scaling). If you drew it small for a 480 × 270 screen (pixels around 64px), choose 480 — the engine draws it at 2×. example 960
FieldBehavior styleHow it behaves when used as an enemy — humanoid (walks up and hits) · tank (keeps distance, shells · rushes) · flyer (floats, fires · dives) · grappler (grabs and throws). See “Enemy design” below. example humanoid
FieldBuild · traitsTurns the four traits below on and off.
ToggleLaunch immune — not launched by launching attacksnoLaunch. For heavy enemies · bosses.
ToggleCan't be grabbed — the hero can't grab itnoGrab. For big enemies · floating enemies.
ToggleAir invincible — can't be hit while airborneairInv. For enemies that dodge jump attacks.
ToggleKnocked down by any attackalwaysDown. For grunts that always fall to a single hit.

4 Special skills

Turns on special skills for enemies · bosses. Several can be on at once; the ones you turn on come out as “Spawn options” JSON to paste into “Other options (JSON)” of a Stage Forge wave. What's available depends on the behavior style. See the “Special skills” table below.

ItemMeaning · unit · default
ToggleGrabTurn on to use this special skill. Settings · defaults · meanings are in the “Special skills” table below.
ToggleCollapsing floorTurn on to use this special skill. Settings · defaults · meanings are in the “Special skills” table below.
ToggleMortarTurn on to use this special skill. Settings · defaults · meanings are in the “Special skills” table below.
ToggleSuper modeTurn on to use this special skill. Settings · defaults · meanings are in the “Special skills” table below.
ToggleForbidden spellTurn on to use this special skill. Settings · defaults · meanings are in the “Special skills” table below.
ToggleCloneTurn on to use this special skill. Settings · defaults · meanings are in the “Special skills” table below.
ToggleInvincible counterTurn on to use this special skill. Settings · defaults · meanings are in the “Special skills” table below.
FieldSpawn options (paste into the stage)Settings JSON for the special skills you turned on. Copy and paste it into “Other options (JSON)” of an enemy group in a Stage Forge wave.

Special skills

Grab (grab · styles humanoid) — Grabs when close, lifts and throws. Needs reach · lift · throw cells.

FieldMeaningDefault
holdTimeHold time (frames)110
struggleNPresses to break free18
holdXHeld person X-48
holdZHeld person height120
throwDirThrow directionalt
throwKbThrow strength9
throwLiftThrow height8
holdHideHeroHide hero while holdingFalse

Collapsing floor (quake · styles humanoid, tank) — Rides on the active window of the chosen attack. A crack runs out and becomes a hole.

FieldMeaningDefault
fromTrigger HP (0~1)1
coolCooldown (frames)420
holeWHole width56
holeHHole height36
maxMax holes5
bigWBig hole width96
bigAfterHP for big holes0.35
collapseUntil collapse (frames)36
holeArtHole image id

Mortar (mortar · styles humanoid, tank) — Fired upward, it drops after a shadow telegraph. The aim point is fixed the moment it fires.

FieldMeaningDefault
warnShadow telegraph (frames)42
radiusBlast radius117
fallFall speed12
hStart height420
coolCooldown (frames)210
dmgDamage999
artFalling shell id

Super mode (ultra · styles humanoid, tank) — Runs invincibly to the far side from the hero, then fires from where it stands. Needs run cells.

FieldMeaningDefault
fromTrigger HP (0~1)0.8
firstFirst trigger (frames)150
gapCooldown (frames)270
speedRun speed7
edgeDistance from the edge80
laneDepth matching speed3
movesMoves used at the edge (comma)

Forbidden spell (forbid · styles humanoid) — While the screen freezes, it casts “don't do this.” It doesn't block — breaking it is punished.

FieldMeaningDefault
atTrigger HP (comma)0.75,0.45,0.2
orderForbid order (| groups mean one of them)combo|jump, kick|punch, up|down
durationDuration (frames)720
graceGrace (frames)30
penaltyShare taken when broken (comma)0.5,0.75,1.0
releaseRelease at (share of max HP)0.15
bInFade to dark (frames)30
bHoldMagic circle (frames)110
bOutFade back (frames)26
dimDarkness (0~1)0.86
markFxFloor mark id

Clone (summon · styles humanoid, tank) — Summons a weak copy of itself. Clones aren't registered as bosses.

FieldMeaningDefault
charClone character id
hpMulHP multiplier0.4
dmgMulDamage multiplier0.6
speedMulSpeed multiplier1
maxMax count1
coolCooldown (frames)420
fromTrigger HP (0~1)0.95
dieWithOwnerFalls with its ownerTrue
noForbidForbid spell doesn't affect clonesTrue

Invincible counter (counter · styles humanoid, tank, flyer) — When hit in a string, hits back invincibly. Stops the stick-close-and-mash strategy.

FieldMeaningDefault
counterHitsConsecutive hits3
counterWinWindow for those hits (frames)90
counterMoveCounter move number (from 0)0
counterInvInvincible while countering (frames)70
risingInvInvincible when rising to counter (frames)40
counterOnComboCount a combo hit as consecutiveTrue

5 Action assignment

Which cells to use, in what order and at what speed, for each action (idle · walk · hurt …). Actions you didn't draw use another action per the fallback table. See the “Action cells” table below.

ItemMeaning · unit · default
ButtonBaseAction assignment for the base look.
Button+ VariantAdds a variant set (power-up · rage look). Each variant has its own action assignment.
Button+ Add attackAdds another hand · foot attack (chains up to 3 hand hits · 2 foot hits).
ButtonClear selected actionClears the cell assignment of the selected action (it then uses another action per the fallback table).

Action cells · fallbacks

ActionRequiredUsed instead when missing
idleYes—
walkYes—
hurt—idle
down—hurt
jump—idle
jatk—First hand attack
jkick—First foot attack · else jump attack
dash—walk
carry—idle
push—walk
throw—Hand finisher
grab—First hand attack
dashatk—Basic attack
blitz—Jump kick
guard—idle
rest—idle
wreck—Darken idle cells

6 Attack values

Timing · damage · reach for each attack. The table above has one row per move; below is for giving each cell its own hitbox. See the “Attack columns” table below for what each column means.

ItemMeaning · unit · default
ButtonBreath OffBreath (fire · breath reaching forward) — when on, a long hitbox reaching forward instead of a melee hitbox.
ButtonProjectile OffProjectile (shot) — when on, it fires a shot instead of a melee hitbox. The shot image is in step 9 “Shot images”.
FieldBody half-width hwHalf-width of the character's body (px) — the hurtbox · collision width. Set automatically from the art width when the sheet is loaded. example 41
FieldAttack reachBase reach (reach, px). Each move's reach × multiplies this. example 97
FieldHurtboxShows · adjusts the hurtbox in the preview.
Attack columnsMeaning
AttackMove name. Combos · special skills refer to it by this name.
TypeHand / foot — which button it comes out on. Moves of the same type chain in order.
Startupstartup, frames. From the button press until the hitbox appears. Shorter is faster.
Activeactive, frames. How long the hitbox is live. When it ends, you can chain into the next hit.
Recoveryrecover, frames. From the end of the hitbox until you can move again. Longer means a bigger penalty for whiffing.
Hit framehitFrame. Cell number of the hitting pose. When set, that cell shows up timed to the start of the hitbox (blank spreads cells evenly over the whole time).
Damagedmg. Amount taken from HP.
Reach ×reachMul. Multiplier on base reach (attack reach). 1.3–1.7 for far-reaching moves like kicks.
Launchlaunch. When on, the hit enemy is lifted into the air. Usually only on the last hit.
EffectWhich of the effects added in step 9 to attach to this move.
Per-cell hitbox — cell · reach × · depthFor giving a cell its own hitbox. Reach × · depth (px) change only on that cell.
Values with no field in the tool (write directly in JSON)Shake (shake) · freeze (freeze, frames) · knockback (knockback) · launch height (lift) · multi-hit (hits · hitGap) · angled knockback (angled) · damage as a share of max HP (dmgPct) have no field in the tool. Open the saved character JSON in a text editor and write them in that move's entry (inside attacks or kicks); only that move uses the value. Example: "shake": 12, "freeze": 8. They're kept even if you reopen and save in Character Forge.

7 Command combos

Special moves done by pressing buttons in order (up to 5 per character). See the “Combo fields” table below.

ItemMeaning · unit · default
Button− StepRemoves one input step (minimum 2).
Button+ StepAdds one input step (maximum 4).
ButtonLaunchThis combo launches the opponent (launch). Press to switch to “No launch”.
ButtonArmorArmor while performing (not interrupted when hit, takes reduced damage). On by default.
ButtonNo launchThis combo doesn't launch the opponent. Press to switch to “Launch”.
Button+ Add comboAdds a combo.
Combo fieldsMeaning
NameCombo name. Shown by this name in the move list · special skills.
Inputinput. 2–4 steps. Each step is hand · foot · jump · special or a simultaneous press (hand+foot, etc.). Buttons pressed within 6 frames merge into one step.
FramesCells this combo uses.
Startup · active · recovery · damageSame as the attack columns.
Hits · gaphits · hitGap. Combos that hit several times (multi-hit) and the frames between hits.
Knockback · launchknockback · lift. How far the hit opponent flies and how high it rises.
Shake · freezeshake · freeze (frames). Screen shake and the pause at impact (hitstop).
Armorarmor. While performing, hits don't interrupt it — it just takes reduced damage (on by default). armorTo (frames kept) · armorCut (damage multiplier taken, default 0.5).
Invincibleinv. Invincible frames right after activation (default 0).
Super gaugecost. Super gauge slots used (shown as “Super 1” in the move list).

Choices for an input step — hand Hand · foot Foot · jmp Jump · spc Special · hand+foot Hand+Foot · hand+jmp Hand+Jump · hand+spc Hand+Special · foot+jmp Foot+Jump · foot+spc Foot+Special · jmp+spc Jump+Special

8 Preview

Plays actions · moves. Turn on “Show hitboxes” to overlay attack boxes (red) · hurtboxes (green).

ItemMeaning · unit · default
ButtonAction · move · effect namesAction · move name buttons — press to play that action or move. The buttons depend on the loaded character.
ButtonGrabTurn on to use this special skill. Settings · defaults · meanings are in the “Special skills” table below.
ButtonShow hitboxesOverlays attack boxes · hurtboxes · collision boxes.

· Other

Below the preview — other effects attached to actions, such as dash effects · auras.

ItemMeaning · unit · default
ButtonAction · move · effect namesEffect name buttons — press to preview that effect. They depend on the effects added in step 9.
ButtonTurn offTurns off this other effect.

9 Effect

Effect art attached to moves (sword trails · flames, etc.). Pick the effects added here in the “Effect” column of the step 6 attack table.

ItemMeaning · unit · default
ButtonDeleteDeletes this image.
ButtonBehindDraws the effect behind the character (default is in front).
ButtonLoopLoops the effect (auras, etc.).
File+ Add effect imageAdds a horizontal effect sheet PNG.

· Shot images

Projectile (shot) art. Moves with projectile on fire this image.

ItemMeaning · unit · default
File+ Add shot imageAdds a shot sheet PNG.

10 Pose edit

Move · erase · flip · resize the art in each cell. Parts moved outside the cell are cropped when saved, so a warning appears.

ItemMeaning · unit · default
ButtonOpen pose editorOpens the pose editor.

11 Character JSON

The character JSON to be saved. Download with “Save character JSON” in the bottom bar.

ItemMeaning · unit · default
ButtonEmbed PNG: onPacks the sheet art inside the JSON (keep this on — if off, you have to carry the image file separately).
ButtonCopyCopies the JSON to the clipboard.

Stage Forge

1 Preview

Draws the stage. Move the camera with the bar below; on wide screens you can keep it pinned at the top while editing the sections below.

ItemMeaning · unit · default
ButtonFloor bandShows the band characters walk in (floor top ~ bottom) in the preview.
ButtonGates · enemy spawnsShows each wave's gate line and where enemies appear.
ButtonAuto scrollScrolls the camera to the end automatically.
ButtonPin previewKeeps the preview pinned at the top of the screen (on by default on wide screens, remembered).

2 Basic info

Name · music · floor lines. Enter the floor lines before adding background art and the art is placed to match them.

ItemMeaning · unit · default
File+ Load stage JSON (continue editing)Opens a saved stage JSON to keep editing.
FieldStage nameThe name shown on screen (stage name · results).
Fieldid (letters · numbers)The name that refers to this stage in the game. If blank, made from the name (a non-colliding code if it has no Latin letters).
FieldBGM (blank uses the game's shared track)A track used only in this stage (URL or file). Blank uses Game Forge's default BGM. The number beside it is this track's volume multiplier (1 default).
File+ BGM filePacks a track file (ogg · mp3) in directly.
FieldBoss BGM (blank continues the track above)Track to switch to on the boss wave. Blank keeps the track above.
File+ Boss BGM filePacks the boss track file in directly.
FieldHorizon YHorizon height of the procedural background (default street art). Background art coordinates (270 basis). Unused when art fills everything. example 162
FieldFloor topInnermost (top of screen) height characters can walk. px on the 960 × 540 basis (e.g. 340). example 340
FieldFloor bottomFrontmost (bottom of screen) height characters can walk (e.g. 512). The difference from the top is the floor band width. example 512
ButtonHide dotted lineWhether to show the gate line on the game screen (handy while testing).

3 Theme

Colors and props of the procedural background (night street) the engine draws when there's no art. Unused when art fills everything.

ItemMeaning · unit · default
ButtonBuildingsDraws building silhouettes in the procedural background.
ButtonStreetlightsDraws streetlights in the procedural background.
ButtonForeground silhouettesDraws foreground silhouettes passing in front of characters.

4 Floor and background images

Adds the floor image (parallax 1.0 — same speed as the screen) and background layers (the smaller the parallax, the farther). See the “Background layers” table below for layer fields.

ItemMeaning · unit · default
File+ Floor image (horizontally tiling PNG)The floor image characters stand on. Repeats horizontally. When added, its top edge aligns to the floor top.
ButtonAlign background · floor verticallyAfter changing the floor lines or horizon, press to re-align the bottom of every background layer and the floor image to the floor line.
File+ Add background layers (multiple allowed)Adds background art as layers. Add the farthest first.
ButtonOpaqueWhether to add an image with transparent parts as opaque. Leave it transparent and turn on “Front” to make a foreground drawn in front of characters.
ButtonProcedural background onThe engine's default night-street background. Turn off if art fills everything.
ButtonTileRepeats this layer horizontally (art whose left and right edges connect).

Background layer · floor image fields

FieldMeaning
ParallaxScroll speed relative to the camera. 0.2 far background · 1.0 same as the floor · 1.2+ objects in front.
YHeight of the layer art's top edge (background art coordinates, 270 basis). When added, its bottom aligns to the floor.
ScaleSize of the layer art.
TileRepeat horizontally.
FrontForeground drawn in front of characters.
Floor image Y · scaleHeight of the floor image's top edge (270 basis) and its size.

5 Waves

The unit enemies come in. For each wave the camera moves to the gate (end of the area), and defeating all enemies leads to the next wave. See the “Wave card” table for card fields, “Enemy archetypes” for types, and the “Spawn options” table for other options.

ItemMeaning · unit · default
File+ Load character listLoads characters to choose as enemies (a game JSON · several character JSONs). “Play in engine” also uses this list.
ButtonClothes onlyApplies the color field's hue to clothes only (skin · hair stay).
ButtonPressA string of attacks right after landing a hit (press). Turn on for an enemy that keeps pushing.
ButtonChargeA charge sprinting in from the screen edge (charge).
ButtonCollapsing floorThis enemy's slam collapses the floor (quake — special skill).
ExpandOther options (JSON)Write options without a field as JSON, or paste text from Character Forge special skills. Use null to remove an option. See the “Spawn options” table for the list.
ButtonUse foot movesThis enemy also uses foot attacks (useKick).
ButtonUse combosThis enemy uses command combos (useCombo).
Button+ Enemy groupAdds another enemy group to the wave.
ButtonComboChoose the combos this group uses (blank for all).
Button+ Add waveAdds another wave. Place its gate at least 700 after the previous wave.
ButtonBothAppears in both 1P · 2P.
Button1PAppears only in 1P.
Button2P (coming in an update)Only in 2P — 2P co-op is coming in an update.

Wave card

FieldMeaning
GateEnd of this wave's area (horizontal px). First gate 1200 or more, 700 or more between waves.
Max at onceMaximum number on screen at once (blank for all).
Hint · numberText briefly shown at the start of the wave and how long it shows (frames, default 240).
TierGrunt · elite · boss · final — HP · size · moves used · score differ (“Enemy tiers” table).
CountNumber of enemies in this group.
SideRight ▶ · ◀ left · both ◀▶.
ColorTint (crimson · blue · violet · gold · pale · silver · bronze · steel). Makes the same art look like a different enemy.
Display nameRenames only this group (boss names, etc.).
TypeEnemy archetype — choosing one fills in behavior options at once (“Enemy archetypes” table).
Combo frequency (0~1)Combo frequency for this placement only (comboFreq) — the chance of choosing a combo when one is within reach. Blank uses the character value → tier default. The old comboBias is also read.
ModesBoth · 1P only · 2P only.
CharacterAuto (distributed among characters with the grunt role) or a specific character.
DropItem dropped when the wave is cleared (defined in step 9).
BannerLarge text shown at the start of the wave (e.g. BOSS).

Enemy tiers

Tier multipliers apply to the character’s HP · size. Rage is switching to the variant look (or a red tint if none) when HP drops below that ratio.

TierHPSizeMoves usedRageScore
Grunt (grunt)× 1× 11 hand-type hit—120
Elite (mini)× 2.4× 1.251 hand-type hit—600
Boss (boss)× 5.6× 1.5All hand · foot · combo35%2000
Final (final)× 9.0× 1.7All hand · foot · combo45%5000

Behavior styles

StyleBehaviorActions used
humanoidApproaches and hits. Weaves in depth as it closes inidle · walk · attack
tankKeeps distance and shells, swats when close, rushes periodically. No jumping · launch immuneidle · walk · attack
flyerFloats, fires and dives. Ground attacks don't reach itjump (hover) · jatk (dive) · attack
grapplerGrabs and throws. Launch immuneidle · walk · first attack (grab pose)

Enemy archetypes

Choosing one under “Type” on a wave card fills in these behavior options at once.

TypeTierDescription
Relentless brawlerGruntSticks close and hits in a string. Gives you no room to back off
Off-screen chargerGruntRuns in from the screen edge, kicks, and exits the other side
Counter swordsmanEliteHits back once it has taken enough hits, and punishes whiffs
Lunging rusherEliteBacks off, then lunges in all at once
Artillery tank (boss)BossFires from range, breathes when close, rushes now and then
Teleport → phase-2 bossBossAppears behind you when you're far. When defeated, its true form rises
Landing flyer bossBossFloats and throws, then dives. The only opening is while it's landed
Counter · desperation final bossFinalHits back and punishes whiffs. When defeated, it rises in another form
Grab-and-throw powerhouseEliteGrabs you up close. Mash to break free

Spawn options (Other options JSON)

Values written in “Other options (JSON)” of a wave’s enemy group. Units are frames · px; multipliers default to 1.

OptionMeaning
airInvCan't be hit while airborne
alwaysDownKnocked down by any attack
armorSuper armor (ignores stagger). On by default
bandTank — distance kept from the hero
blinkTeleport — vanishes when you're far and appears behind you
breathRangeDistance at which it uses breath
chargeA charge sprinting in from the screen edge
chargeGapTank — rush cycle (frames)
comboFreqCombo frequency — the chance of choosing a combo when one is within reach (0 ~ 1). The old name comboBias is also read
combosList of combo names to use (blank for all)
coolRest frames between attacks (smaller is more aggressive)
counterFxEffect shown in counter stance
counterFxLifeCounter effect length (frames)
counterHitsInvincible counter — number of consecutive hits
counterInvInvincibility while hitting back (frames)
counterMoveMove number used to hit back (from 0)
counterOnComboCounts a single combo hit as consecutive hits
counterWinInvincible counter — time window for those hits (frames)
desperateAn area-wide instant kill used when HP runs out
diveRangeFlyer — dives when within this distance
diveSafeFlyer — doesn't attack while descending
dmgMulDamage multiplier
forbidForbidden spell (special skill)
grabGrab (special skill)
holdHideHeroHides the hero while holding (when the art already shows them)
holdTimeHold time (frames)
holdXHorizontal spot to place the held hero
holdZHeight to place the held hero
hoverFlyer — hover height
hpMulHP multiplier (on top of the tier default)
kiteThrows from a distance, then dives
landHitsFlyer — after landing, takes this many hits then counters and rises
landTFlyer — frames it rests after landing
liftBlastImpact hitting the ground as it rises
mortarMortar (special skill)
nameDisplay name
nextFormNext form after defeat (phase-2 boss)
paletteOnly changes colors to use it as a different enemy
partPart battle — fight the boss split into parts
pressPressure that chains right after landing a hit
punishRangeDistance for punishing whiffed attacks
punishWhiffPunishes whiffed combos
quakeCollapsing floor (special skill)
rageHP ratio that triggers rage (0 means no rage)
reachMulReach multiplier
risingInvInvincibility when rising with a counter (frames)
rushA rush closing the distance and lunging in
scaleSize multiplier
speedMulMove speed multiplier
struggleNPresses needed to break free when grabbed
summonClone (special skill)
throwDirThrow direction — back · front · alt · random
throwFlyFrames it doesn't slow down while thrown
throwKbThrow speed
throwLiftThrow height
tintTint
ultraSuper mode (special skill)
useComboUse combos
useKickUse foot attacks

◆ Placement editor

Drag gates · obstacles · enemy groups on the stage. Each wave shows its placeable range and problems (⚠).

ItemMeaning · unit · default
ExpandPlacement rulesExpands the rules for gates · obstacle ranges · enemy spawn spots.
Button+ Wave obstacleAn obstacle that appears only in this wave's span.
Button+ Always-on obstacleAn obstacle placed from start to finish.
ButtonDeleteDeletes the selected item.
ButtonNormalTier of the selected enemy group.
Button+ Add enemy groupAdds an enemy group to this wave.

6 Clear cutscene

The cutscene after clearing the stage (video or slides). If none, it goes straight to the next stage.

ItemMeaning · unit · default
FieldVideo URL (mp4/webm)Cutscene video URL. You can also pack in the file directly.
File+ Add slide images (instead of video)Shows several images in turn. Each can have text.
ToggleContinue musicKeeps the stage track playing through the cutscene (keepBgm).

7 Obstacle placement

Places obstacles defined in step 8 on the stage. Each placement can have its own size · drop.

ItemMeaning · unit · default
Button+ Add obstaclePlaces one obstacle (starts with the project's first obstacle).

8 Load obstacles

Loads obstacles (obstacles.json) made in Asset Forge. Loaded obstacles appear in the step 7 placement list. Create · edit them in Asset Forge “Properties”.

ItemMeaning · unit · default
File+ Load obstacle JSONLoads obstacles.json (several allowed; the same id is replaced by the newer one).

9 Load items

Loads items (items.json) made in Asset Forge. Loaded items can be chosen as drops for waves · obstacles. Create · edit them in Asset Forge “Properties”.

ItemMeaning · unit · default
File+ Load item JSONLoads items.json (several allowed; the same id is replaced by the newer one).

10 Stage JSON

The stage JSON to be saved. Download with “Save stage” in the bottom bar.

ItemMeaning · unit · default
ButtonCopyCopies the JSON to the clipboard.

Game Forge

1 Game info

Game-wide settings — title · supported modes · difficulty · slash mode · continue · results screen.

ItemMeaning · unit · default
FieldGame titleFile name · browser tab · title screen title.
FieldSupported modesWhich of 1P · 2P the game supports (2P co-op is coming in an update).
FieldDifficulty selectAdds a difficulty row to the title. Levels are in the “Difficulty” table below — enemy HP · damage · rest time multipliers. example on
ButtonReset to defaultResets this section to defaults.
FieldTitle screen menuWhether to show the title menu (start · difficulty · slash).
FieldSlash modeA mode toggled separately from difficulty. When on, the hero's attack range × reach (default 1.5) and hurtbox × hurt (default 0.7). Enemies stay the same. example on
ToggleOn from the startStarts with slash mode on by default.
FieldContinueContinue after game over — countdown (countdown seconds, default 10) · count (limit, 0 = unlimited) · share of score kept on continue (scoreKeep, default 0.5). example on
FieldResults screenShows a results screen when the game ends. example on
ToggleTimeTime taken on the results screen.
ToggleEnemies defeatedNumber of enemies defeated on the results screen.
ToggleHigh scoreHigh score on the results screen (remembered by the browser).
File+ Load a game JSON in progress (continue editing)Opens a saved game JSON (or the sample game package) to keep editing.

Difficulty

Multipliers for enemy HP (hp) · damage (dmg) · rest between attacks (rest, higher attacks less). The hero’s abilities · telegraph times stay the same. Names · multipliers can be changed in difficulty.levels of the game JSON.

LevelNameEnemy HPEnemy damageRest time
easyEasy0.750.71.4
normalNormal111
hardHard1.351.30.8

2 Character

Characters used in the game and their roles (hero · grunt · boss). With several heroes, a character select screen appears.

ItemMeaning · unit · default
File+ Add character JSON (multiple allowed)Adds character JSONs. Set each row's role with the hero · grunt · boss tags.

3 Stage order

Play order. Top to bottom.

ItemMeaning · unit · default
File+ Add stage JSON (multiple allowed)Adds stage JSONs. Reorder with the arrows, remove with ×.

4 Items and obstacles

Item · obstacle definitions the stages use (items.json · obstacles.json) and shared effect art.

ItemMeaning · unit · default
File+ Add item / obstacle JSON (multiple allowed)Adds items.json · obstacles.json. Missing ones show up in step 9 Check.
FieldHit sparkSpark art shown on hits (horizontal sheet PNG + frame count). Blank uses the engine default.
FieldPowered hit sparkSparks on strong attacks · while powered up.
FieldExplosiveExplosion art for explosive obstacles · enemies blowing up.

5 Title · release

Subtitle and title text, plus building for release.

ItemMeaning · unit · default
FieldSubtitleSmall text under the title.
ToggleDon't draw title text on the title screenTurn on when the title art already contains the title (title · subtitle aren't drawn).
ToggleBuild for release (hide authoring items)Turn on when building a game for others — authoring buttons are hidden and “Press Enter to start” · the first-time guide appear.

6 Presentation

Notice screen · opening · ending · tracks · credits. Steps you don't add are skipped. The number beside each track is its volume multiplier (1 default).

ItemMeaning · unit · default
File+ Title background imageTitle screen art (960 × 540 recommended).
File+ Character select backgroundArt for the select screen shown when there are several heroes.
File+ Copyright notice · studio logo (shown first when the game opens)The notice screen shown first when the game opens (several images). If “Skippable”, press to advance.
FieldIntro video URL (skippable after 3 s)URL of the opening video shown at start. Skippable after 3 s.
File+ Intro video file (pack in instead of a URL)Packs the opening video file (mp4 · webm) into the game.
File+ Intro slide images (instead of video)Opening as several images, with text on each.
ToggleContinue musicKeeps the track playing into the next screen after this sequence ends.
FieldEnding video URL (not skippable)Video shown after clearing the last stage.
File+ Ending video file (pack in instead of a URL)Packs the ending video file in.
File+ Ending slide imagesEnding as several images.
FieldMusicGroup of track fields. Each track is a URL or file; the number beside it is the volume.
FieldDefault BGMTrack used when a stage has none.
File+ Default BGM filePacks the track file in.
FieldBoss trackShared boss-wave track (when a stage has no boss track).
File+ Boss track filePacks the track file in.
FieldTitle trackTitle screen track.
File+ Title track filePacks the track file in.
FieldOpening trackTrack during the opening (intro).
File+ Opening track filePacks the track file in.
FieldMid-slide trackTrack for cutscenes between stages.
File+ Mid-slide track filePacks the track file in.
FieldEnding trackTrack during the ending.
File+ Ending track filePacks the track file in.
FieldCredits trackTrack during the credits.
File+ Credits track filePacks the track file in.
FieldCredits (one per line; start with # for large text)Text that scrolls after the ending. One per line; start with # for a large heading; divider lines like ── title ── work too.

7 Controls · screen · hit feel

Default PC keys · screen scale · grabs · hit feel. See the “Control keys” table for keys and the “Hit feel” table for hit feel.

ItemMeaning · unit · default
ButtonDefault (arrow keys + QWER)Resets the key layout to default (arrow keys to move + Q W E R). It can also be changed in-game under “Key settings”; these are the starting values.
FieldPC max scaleMaximum scale for enlarging the game on PC. Without a limit, pixels grow too big on large screens (about 3 recommended).
FieldInteger scaling only (1 = yes)1 scales only by whole numbers (2×, 3×) so pixels look even. 0 fills more of the screen but is slightly blurrier.
ButtonMobile fullscreen onShows a fullscreen button on phones.
ButtonGrab onTurns on grabs (walk into an enemy up close; after grabbing, attack = knee strike, back direction + attack = throw).

Control keys

ActionName
lLeft
rRight
uUp
dDown
handHand
footFoot
jmpJump
spcSpecial
startStart

Hit feel

Tune it in-game in “◎ Hit studio”, press “Copy settings” and paste into step 7. Blank uses the defaults below.

ValueMeaningDefault
freezeMulHitstop multiplier — pauses longer at the moment of impact1.30
shakeMulScreen shake multiplier1.25
shakeTimeShake duration (frames)15
shakeAxisShake direction x · y · xy · radialxy
jitterJitter amplitude during hitstop (px)3
flashWhite flash on hit (frames)7
flashColorFlash color#ffffff
knockMulKnockback distance multiplier1.15
liftMulLaunch height multiplier1.10
glanceEffect ratio for glancing hits0.5
glanceBandBeyond this depth difference, a hit counts as glancing9
comboShakeShake increase per combo hit0.12
comboFreezeHitstop increase per combo hit (frames)0.9
comboCapMax hits the increase applies to8
ghostNNumber of dash afterimages4
ghostAAfterimage opacity0.34
ghostSil1 draws afterimages as silhouettes0

8 Screen display (HUD)

Position · size · color · art of on-screen displays such as the HP bar · name · score · lives. See the “HUD elements” table below.

ItemMeaning · unit · default
File+ Back panelPanel art laid behind the HUD.
File✓ Fill imageHP bar fill art (✓ when added).
ButtonClearRemoves the added art.
File✓ Danger imageFill art that switches in when HP is low.
File✓ FrameFrame art around the HP bar.
File✓ Life iconIcon showing the number of lives.
File✓ Super iconIcon for super gauge slots.
ButtonReset to defaultResets this section to defaults.

HUD elements

Per element: on (on) · x · y (half-size screen basis) · size (size or w · h) · color (color) · image (img).

ElementNameDefault
panelBack panelon True · x 0 · y 0 · w 0 · h 0
nameCharacter nameon True · x 12 · y 16 · size 9 · color #f2ecdd
hpHP baron True · x 12 · y 20 · w 124 · h 7 · color #3fe3ff · low #ff2f7e · back #2e2140 · edge #150d1e · fill Fill image · fillLow Danger image · frame Frame · frameX 0 · frameY 0 · frameW 0 · frameH 0
livesLives lefton True · x 12 · y 40 · size 9 · color #f2ecdd · text LIVES · icon Life icon · iw 9 · ih 9 · gap 11
specialSuper slotson True · x 66 · y 33 · w 5 · h 7 · gap 8 · color #3fe3ff · icon Super icon
feverPower-up gaugeon True · x 150 · y 16 · w 80 · h 5 · size 9 · color #ff9c3f
scoreScoreon True · x 12 · y 18 · size 11 · color #ff9c3f
stageStage nameon True · x 12 · y 32 · size 9 · color #f2ecdd
leftEnemies lefton True · x 10 · y 52 · size 10 · color rgba(242,236,221,.5) · text ENEMIES LEFT
bannerWave banneron True · y 94 · size 20 · color #ff2f7e
hintWave hinton True · y 116 · size 12 · color #ffd24a
hitsCombo counton True · x 13 · y 62 · size 18 · color #ffd24a

◇ Translation sheet

Exports game text (title · subtitles · credits · names) as CSV, then imports the translation back into the game.

ItemMeaning · unit · default
ButtonExport translation sheetDownloads the list of text to translate as CSV.
FileImport translation sheetAdds the CSV with translations filled in. The game shows text in the player's language.

9 Check

Shows problems such as missing characters · items · obstacles or settings that don't match the modes. If there are problems, you're asked once when saving · building.

10 Build as a single file

Choose the engine file once (remembered) and the whole game comes out as a single HTML file.

ItemMeaning · unit · default
File+ Choose neon-precinct.htmlChoose engine/neon-precinct.html from the bundle. It's remembered from then on.

OpenBOR Importer

1 Load

Choose the folder with the text files and sprites of a character you made yourself for OpenBOR. Every time you choose, a rights notice appears, and nothing loads until you press “OK — continue” (there is no “don't show again”). Image paths in the text files (data/chars/…) are found in the folder; projectile characters (type none · projectile) are left out of the list and used along with the character.

ItemMeaning · unit · default
File+ Choose OpenBOR folderChoose the whole OpenBOR game folder (or data folder). Image paths in the text files (data/chars/…) are found inside it. Images with the same name in several characters are told apart by path.
File+ Choose multiple filesWhen you can't choose a folder — choose a character text file and its images together. Files are matched by name without paths, so choose one character's files at a time.

2 Animation mapping

Maps OpenBOR animations to our slots — idle · walk · run → dash · jump · jumpattack → jump hand attack · pain → hurt · fall → down · grab · throw · block → guard · runattack → dash attack, attack1 ~ N → hand attacks, freespecial · special → command combos (for enemies, throwing moves become hand attacks). You can change them in the table. Reads both the official syntax (image top-left coordinates · one-line attack) and the anchor-relative format (negative coordinates · abox), and shows scripts (@script · @cmd) · missing images · anchor mismatches as notices.

ItemMeaning · unit · default
ToggleSnap the anchor to the feet in the imageUses the lowest opaque row in each image (the feet) as the anchor instead of offset. Turn on when offset doesn't match the feet and characters look sunk or floating (the notice shows how many px it's off).

3 Enemy AI · role

For enemies (type enemy), sets the behavior style (humanoid · tank · flyer) from aimove · gravity · projectile, nograb → grab immune, and builds suggested spawn options from aggression · nopain (cool · stagger · band). It reminds you to set the role in Game Forge (enemy → grunt or boss, player → hero).

ItemMeaning · unit · default
ButtonCopyCopies the spawn options JSON to the clipboard.

4 Make character JSON

Converts per the table above and downloads one character JSON — sheet (one row aligned on the anchor), delay 1/100 s → 1/60 s frames, bbox → half-width, attack boxes → startup · active · recovery · reach, damage, health, speed (10 → 1.45), com → command combos, custknife → projectile · shot image. 480 base is the default. Open the result in Character Forge to refine it.

ItemMeaning · unit · default
ButtonMake character JSONConverts per the table above and downloads the character JSON. Animations set to “Don't import” are left out. Open it in Character Forge to refine the anchor · hitboxes · moves.

Asset Forge

Handles characters · items · obstacles · effects. Items · obstacles are created here and their properties set, and every asset is matched in position · size frame by frame while comparing against the hero. Edits are baked into the art when saved.

ItemMeaning
+ Load JSONOpen several character · item · obstacle · effect JSONs together. Choose from the list on the left.
+ New item · + New obstacleCreates a new item · obstacle. Add the image (horizontal PNG strip) and set values under “Properties” on the right. When you add an image, the frame count is guessed assuming square cells.
Propertiesid · name · kind · values · image · frames · fps of the selected item · obstacle. Only the fields needed for the kind appear. See the “Obstacle definition fields” · “Obstacle kinds” · “Item kinds” tables below.
Save this only · group by kind · save allDownloads just the selected one · one file per kind (items.json · obstacles.json) · everything in one (only clickable when there is something to save). Load them in Stage Forge steps 8 · 9.
Play · fpsPlays the selected item. fps = cells per second.
Compare with hero · load heroStands the hero character beside it to compare size.
Frame adjust — overlay previous frame · opacityOverlays the previous cell semi-transparently to check for jitter.
Below floorExtends the area below the floor line. For crates drawn at an angle, the bent line at the bottom corner must touch the floor line to look grounded.
Move · eraser · flip horizontallyMoves · erases · flips the art in this cell. 1px at a time with ◀ ▶ ▲ ▼.
Size · target height · fitArt scale. Enter a target height (px) and press “Fit” to size it to that height.
Revert this frame · revert allReverts edits for one cell · all cells.
Bake into imageApplies the edited position · size to the art.
Details — anchor · hitbox · actual sizeShows the point under the feet, the hitbox, and the actual in-game size.
Overlay effect · fixOverlays an effect on a character move to line it up.

Obstacle definition fields

FieldMeaning
id · nameThe name referred to by placements · drops, and the display name.
KindSeven behaviors — table below.
hw · depth · heightHitbox half-width · depth · height (px, 960 basis). Can be smaller than the art.
Image · frames · fpsSheet PNG, cell count, playback speed.
Base widthWhich screen size the art was drawn for. 960 is the default (art as-is). If you drew it small for a 480 × 270 screen, choose 480 — the engine draws it at 2×.
Hits hero onlyFire · rolling barrels — if off, enemies get hurt too.
DropItem dropped when it breaks.

Obstacle kinds

KindActionKind-specific fields
solidUnbreakable (blocks)—
breakableBreakableHP (hp)
explosiveExplosiveHP · blast radius (blastR) · blast damage (blastDmg)
hazardDamage over time (passable)Damage (dmg) · interval (tick, frames)
fallingFalls from the skyHP · fall speed (fall) · landing impact (impact)
moverRolls side to sideSpeed (vx) · contact damage (dmg)
platformPlatform (can stand on)— (can stand on it; its height is the platform height)

Item kinds

Fields — id · name · kind · amount (amount) · duration (duration, frames) · text (text) · color · image · frames · fps.

KindNameMeaning
healHP recoveryHP recovery — by amount (e.g. 35), shows text
feverFever (power-up)Fever (power-up) — stronger attacks for duration frames (e.g. 900)
specialSuper gaugeSuper gauge — fills amount slots
lifeExtra lifeExtra life

Engine dev screen

The authoring screen you see when opening engine/neon-precinct.html directly, or in a game built without “for release”.

ItemMeaning
Load game / character / stage JSONLoad several JSONs and play right away. If hero · stage are empty, the first ones are used.
Roster — hero · grunts · boss · stageTap the chips to choose the characters · starting stage for this run.
STARTStarts the game.
AUTOAuto play — runs to the end hands-free.
SandbagPuts up a target that never fights back or dies (for testing moves).
◎ Hit studioAdjusts hit feel · sound. Paste into Game Forge step 7 with “Copy settings”.
⚙ Key settingsPC key layout.
Language (top left)Screen language (한국어 · English · 日本語). Opens in the browser language; any other language opens in English.
PauseEsc · P or the “Ⅱ” in the screen corner. While paused, T returns to the title. Move list · sound settings.

Glossary

ItemMeaning
AnchorThe point under a character's feet — where it touches the floor.
Floor bandThe strip characters can walk up and down in.
GateThe end of the area where a wave ends — where the camera stops.
WaveThe unit enemies come in. Defeat them all to move on.
TierGrunt · elite · boss · final. HP · size · moves · score.
Behavior styleHow an enemy behaves (humanoid · tank · flyer · grappler).
Spawn optionsBehavior · special skill settings (JSON) attached to a wave's enemy group.
Special skillsGrab · collapsing floor · mortar · super mode · forbidden spell · clone · invincible counter.
Hit frameThe pose cell shown timed to the start of the attack hitbox (hitFrame).
Startup · active · recoveryThe three phases of an attack (frames).
HitstopThe brief pause of the screen at the moment of impact (freeze).
LaunchThe hit opponent is lifted into the air (launch · lift).
ArmorA state where hits don't interrupt.
Variant setCells for another look during power-up · rage.
ParallaxHow much slower a background layer scrolls than the camera.
Procedural backgroundThe default background the engine draws without art.
Part battleFighting a boss split into several parts.
Slash modeA mode that widens the hero's attack range and narrows the hurtbox.
For releaseA build setting that hides authoring items and builds the player-facing screens.
Frame1/60 s.

Troubleshooting

ItemMeaning
A character looks like it floats or sinks into the floorAdjust “Foot Y” in Character Forge step 3. If it differs per cell, fix it cell by cell in Asset Forge.
The background is pushed down, or the floor image doesn't showEnter the floor lines in Stage Forge step 2 first, then “Align background · floor vertically” in step 4.
⚠ at the top of a wave cardThe reason is written there — gate spacing (700 or more), enemies appearing beyond the next gate, obstacles out of range, and so on.
Enemies don't appearCheck the character list · roles (grunt · boss). Missing characters show up in Game Forge step 9 Check.
“Play in engine” doesn't openAllow pop-ups in the browser. The engine must be in the engine/ folder of the same bundle as the tools.
Authoring buttons show in the built gameTurn on “Build for release” in Game Forge step 5 and build again.
Obstacles look like dotted boxes · items like diamondsThat obstacle · item has no art. Add art in Stage Forge steps 8 · 9.
Can't jump over rolling barrelsShrink the hitbox (half-width · height). The art can stay as it is. You have to run at it and jump.
Part of the art is cut off after pose editingParts moved outside the cell are cropped (a warning appears). Reduce the move · size, or widen the cell in step 2.
The game file is too largeMostly video · music. Shorten the video or use slides, and use ogg for music.
A warning appears when closingThere are unsaved edits. Save, then close.

Usage scope · license

The engine · tools · scripts are under a free license (LICENSE at the top of the bundle — this English version is authoritative) — The engine · tools are free to use when downloaded from the official distribution channel (neonprecinct.com), and games you make can be sold freely with no royalty. Reselling or redistributing the software (even unmodified or free of charge), distributing modified versions, and distributing it under another name are not allowed — engine files included in your games are the exception. Sharing a link to the official channel is fine. For how far you can reuse the sample's (Hyakki Yako) art · sound, see “Usage scope” in samples/hyakki-yako/README.md.

ItemMeaning
Use of generative AIPortions of the artwork, sound, and English/Japanese translations in this product were created with the assistance of generative AI tools. See “How this sample was made” in the sample README.