@origingame/create-game 0.0.0-stage → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +57 -2
- package/archetypes/README.md +99 -0
- package/archetypes/idle/.origin/setup +14 -0
- package/archetypes/idle/LICENSES.md +12 -0
- package/archetypes/idle/README.md +234 -0
- package/archetypes/idle/assets/audio/buy.wav +0 -0
- package/archetypes/idle/assets/audio/milestone.wav +0 -0
- package/archetypes/idle/assets/audio/nova.wav +0 -0
- package/archetypes/idle/assets/audio/orbit.wav +0 -0
- package/archetypes/idle/assets/audio/tap.wav +0 -0
- package/archetypes/idle/assets/audio/ui-close.ogt +9 -0
- package/archetypes/idle/assets/audio/ui-error.ogt +9 -0
- package/archetypes/idle/assets/audio/ui-open.ogt +9 -0
- package/archetypes/idle/assets/audio/ui-press.ogt +9 -0
- package/archetypes/idle/assets/audio/ui-success.ogt +9 -0
- package/archetypes/idle/assets/fonts/NotoSansSC-subset.ttf +0 -0
- package/archetypes/idle/assets/fonts/NotoSansSC-subset.ttf.ogt +10 -0
- package/archetypes/idle/assets/fonts/OFL.txt +93 -0
- package/archetypes/idle/assets/fx/drift.ogt +21 -0
- package/archetypes/idle/assets/fx/milestone.ogt +21 -0
- package/archetypes/idle/assets/fx/nova.ogt +22 -0
- package/archetypes/idle/assets/fx/stars.ogt +20 -0
- package/archetypes/idle/assets/fx/tap.ogt +23 -0
- package/archetypes/idle/assets/looks/idle.ogt +17 -0
- package/archetypes/idle/assets/skins/sparkorb/ChakraPetch-BoldItalic.ttf +0 -0
- package/archetypes/idle/assets/skins/sparkorb/ChakraPetch-BoldItalic.ttf.ogt +9 -0
- package/archetypes/idle/assets/skins/sparkorb/LICENSES.md +19 -0
- package/archetypes/idle/assets/skins/sparkorb/OFL.txt +95 -0
- package/archetypes/idle/assets/skins/sparkorb/Orbitron-Medium.ttf +0 -0
- package/archetypes/idle/assets/skins/sparkorb/Orbitron-Medium.ttf.ogt +9 -0
- package/archetypes/idle/assets/skins/sparkorb/Rajdhani-Bold.ttf +0 -0
- package/archetypes/idle/assets/skins/sparkorb/Rajdhani-Bold.ttf.ogt +9 -0
- package/archetypes/idle/assets/skins/sparkorb/atlas.png +0 -0
- package/archetypes/idle/assets/skins/sparkorb/atlas.png.ogt +7 -0
- package/archetypes/idle/assets/skins/sparkorb/icons.png +0 -0
- package/archetypes/idle/assets/skins/sparkorb/icons.png.ogt +7 -0
- package/archetypes/idle/assets/skins/sparkorb/skin.ogt +113 -0
- package/archetypes/idle/assets/sprites/glow.png +0 -0
- package/archetypes/idle/assets/sprites/glow.png.ogt +8 -0
- package/archetypes/idle/assets/sprites/mote-crystal.png +0 -0
- package/archetypes/idle/assets/sprites/mote-crystal.png.ogt +7 -0
- package/archetypes/idle/assets/sprites/mote-ember.png +0 -0
- package/archetypes/idle/assets/sprites/mote-ember.png.ogt +7 -0
- package/archetypes/idle/assets/sprites/mote-star.png +0 -0
- package/archetypes/idle/assets/sprites/mote-star.png.ogt +7 -0
- package/archetypes/idle/assets/sprites/mote-storm.png +0 -0
- package/archetypes/idle/assets/sprites/mote-storm.png.ogt +7 -0
- package/archetypes/idle/assets/sprites/orb.png +0 -0
- package/archetypes/idle/assets/sprites/orb.png.ogt +7 -0
- package/archetypes/idle/assets/sprites/spark.png +0 -0
- package/archetypes/idle/assets/sprites/spark.png.ogt +7 -0
- package/archetypes/idle/assets/strings/en.ogt +62 -0
- package/archetypes/idle/assets/strings/zh-CN.ogt +62 -0
- package/archetypes/idle/gitattributes +22 -0
- package/archetypes/idle/gitignore +8 -0
- package/archetypes/idle/host.d.ts +46 -0
- package/archetypes/idle/package.json +18 -0
- package/archetypes/idle/project.ogt +14 -0
- package/archetypes/idle/references/metal/card.png +0 -0
- package/archetypes/idle/references/metal/orbit.png +0 -0
- package/archetypes/idle/references/metal/title.png +0 -0
- package/archetypes/idle/src/components.ts +139 -0
- package/archetypes/idle/src/main.ts +247 -0
- package/archetypes/idle/src/numbers.ts +126 -0
- package/archetypes/idle/src/systems.ts +340 -0
- package/archetypes/idle/src/ui.ts +412 -0
- package/archetypes/idle/tests/away.og.ts +42 -0
- package/archetypes/idle/tests/flow.og.ts +57 -0
- package/archetypes/idle/tests/frames.og.ts +33 -0
- package/archetypes/idle/tests/frames.ts +134 -0
- package/archetypes/idle/tests/lib.ts +74 -0
- package/archetypes/idle/tests/milestone.og.ts +32 -0
- package/archetypes/idle/tests/nova.og.ts +52 -0
- package/archetypes/idle/tests/offline.og.ts +60 -0
- package/archetypes/idle/tests/pad.og.ts +55 -0
- package/archetypes/idle/tests/pause.og.ts +68 -0
- package/archetypes/idle/tests/phone.og.ts +50 -0
- package/archetypes/idle/tests/replay.og.ts +28 -0
- package/archetypes/idle/tools/make-assets.py +448 -0
- package/archetypes/idle/tools/oglite.py +285 -0
- package/archetypes/idle/tsconfig.json +17 -0
- package/archetypes/match3/.origin/setup +14 -0
- package/archetypes/match3/LICENSES.md +7 -0
- package/archetypes/match3/README.md +205 -0
- package/archetypes/match3/assets/audio/cascade.wav +0 -0
- package/archetypes/match3/assets/audio/clear.wav +0 -0
- package/archetypes/match3/assets/audio/lost.wav +0 -0
- package/archetypes/match3/assets/audio/refused.wav +0 -0
- package/archetypes/match3/assets/audio/select.wav +0 -0
- package/archetypes/match3/assets/audio/swap.wav +0 -0
- package/archetypes/match3/assets/audio/won.wav +0 -0
- package/archetypes/match3/assets/fonts/OFL.txt +93 -0
- package/archetypes/match3/assets/fonts/ui.ttf +0 -0
- package/archetypes/match3/assets/fonts/ui.ttf.ogt +11 -0
- package/archetypes/match3/assets/scenes/main.ogt +24 -0
- package/archetypes/match3/assets/sprites/backdrop.png +0 -0
- package/archetypes/match3/assets/sprites/board.ogt +21 -0
- package/archetypes/match3/assets/sprites/cells.ogt +7 -0
- package/archetypes/match3/assets/sprites/cells.png +0 -0
- package/archetypes/match3/assets/sprites/cells.png.ogt +7 -0
- package/archetypes/match3/assets/sprites/gems.ogt +75 -0
- package/archetypes/match3/assets/sprites/gems.png +0 -0
- package/archetypes/match3/assets/sprites/panel.png +0 -0
- package/archetypes/match3/assets/sprites/ring.png +0 -0
- package/archetypes/match3/gitattributes +22 -0
- package/archetypes/match3/gitignore +8 -0
- package/archetypes/match3/host.d.ts +46 -0
- package/archetypes/match3/package.json +18 -0
- package/archetypes/match3/project.ogt +18 -0
- package/archetypes/match3/references/metal/cascade.png +0 -0
- package/archetypes/match3/references/metal/clearing.png +0 -0
- package/archetypes/match3/references/metal/dealt.png +0 -0
- package/archetypes/match3/src/art.ts +54 -0
- package/archetypes/match3/src/board.ts +112 -0
- package/archetypes/match3/src/components.ts +95 -0
- package/archetypes/match3/src/layout.ts +25 -0
- package/archetypes/match3/src/main.ts +199 -0
- package/archetypes/match3/src/systems.ts +631 -0
- package/archetypes/match3/tests/drag.og.ts +31 -0
- package/archetypes/match3/tests/endings.og.ts +40 -0
- package/archetypes/match3/tests/frames.og.ts +49 -0
- package/archetypes/match3/tests/frames.ts +134 -0
- package/archetypes/match3/tests/hidpi.og.ts +41 -0
- package/archetypes/match3/tests/lib.ts +64 -0
- package/archetypes/match3/tests/replay.og.ts +28 -0
- package/archetypes/match3/tests/sounds.og.ts +50 -0
- package/archetypes/match3/tests/swap.og.ts +67 -0
- package/archetypes/match3/tools/make-assets.py +404 -0
- package/archetypes/match3/tools/oglite.py +285 -0
- package/archetypes/match3/tsconfig.json +17 -0
- package/archetypes/rhythm/.origin/setup +14 -0
- package/archetypes/rhythm/LICENSES.md +13 -0
- package/archetypes/rhythm/README.md +235 -0
- package/archetypes/rhythm/assets/audio/bass0.wav +0 -0
- package/archetypes/rhythm/assets/audio/bass1.wav +0 -0
- package/archetypes/rhythm/assets/audio/bass2.wav +0 -0
- package/archetypes/rhythm/assets/audio/bass3.wav +0 -0
- package/archetypes/rhythm/assets/audio/chords0.wav +0 -0
- package/archetypes/rhythm/assets/audio/chords1.wav +0 -0
- package/archetypes/rhythm/assets/audio/chords2.wav +0 -0
- package/archetypes/rhythm/assets/audio/chords3.wav +0 -0
- package/archetypes/rhythm/assets/audio/clear.wav +0 -0
- package/archetypes/rhythm/assets/audio/click.wav +0 -0
- package/archetypes/rhythm/assets/audio/drums.wav +0 -0
- package/archetypes/rhythm/assets/audio/fail.wav +0 -0
- package/archetypes/rhythm/assets/audio/leadA.wav +0 -0
- package/archetypes/rhythm/assets/audio/leadB.wav +0 -0
- package/archetypes/rhythm/assets/audio/miss.wav +0 -0
- package/archetypes/rhythm/assets/audio/tap0.wav +0 -0
- package/archetypes/rhythm/assets/audio/tap1.wav +0 -0
- package/archetypes/rhythm/assets/audio/tap2.wav +0 -0
- package/archetypes/rhythm/assets/audio/ui-close.ogt +9 -0
- package/archetypes/rhythm/assets/audio/ui-error.ogt +9 -0
- package/archetypes/rhythm/assets/audio/ui-open.ogt +9 -0
- package/archetypes/rhythm/assets/audio/ui-press.ogt +9 -0
- package/archetypes/rhythm/assets/audio/ui-success.ogt +9 -0
- package/archetypes/rhythm/assets/charts/neon-pulse.ogt +919 -0
- package/archetypes/rhythm/assets/fonts/NotoSansSC-subset.ttf +0 -0
- package/archetypes/rhythm/assets/fonts/NotoSansSC-subset.ttf.ogt +10 -0
- package/archetypes/rhythm/assets/fonts/OFL.txt +93 -0
- package/archetypes/rhythm/assets/fx/hit.ogt +22 -0
- package/archetypes/rhythm/assets/skins/lanebeat/ChakraPetch-Medium.ttf +0 -0
- package/archetypes/rhythm/assets/skins/lanebeat/ChakraPetch-Medium.ttf.ogt +9 -0
- package/archetypes/rhythm/assets/skins/lanebeat/JetBrainsMono-Regular.ttf +0 -0
- package/archetypes/rhythm/assets/skins/lanebeat/JetBrainsMono-Regular.ttf.ogt +9 -0
- package/archetypes/rhythm/assets/skins/lanebeat/LICENSES.md +17 -0
- package/archetypes/rhythm/assets/skins/lanebeat/OFL.txt +95 -0
- package/archetypes/rhythm/assets/skins/lanebeat/Orbitron-Bold.ttf +0 -0
- package/archetypes/rhythm/assets/skins/lanebeat/Orbitron-Bold.ttf.ogt +9 -0
- package/archetypes/rhythm/assets/skins/lanebeat/atlas.png +0 -0
- package/archetypes/rhythm/assets/skins/lanebeat/atlas.png.ogt +7 -0
- package/archetypes/rhythm/assets/skins/lanebeat/icons.png +0 -0
- package/archetypes/rhythm/assets/skins/lanebeat/icons.png.ogt +7 -0
- package/archetypes/rhythm/assets/skins/lanebeat/skin.ogt +110 -0
- package/archetypes/rhythm/assets/sprites/lane.png +0 -0
- package/archetypes/rhythm/assets/sprites/lane.png.ogt +7 -0
- package/archetypes/rhythm/assets/sprites/note.png +0 -0
- package/archetypes/rhythm/assets/sprites/note.png.ogt +7 -0
- package/archetypes/rhythm/assets/sprites/ring.png +0 -0
- package/archetypes/rhythm/assets/sprites/ring.png.ogt +7 -0
- package/archetypes/rhythm/assets/sprites/spark.png +0 -0
- package/archetypes/rhythm/assets/sprites/spark.png.ogt +7 -0
- package/archetypes/rhythm/assets/strings/en.ogt +61 -0
- package/archetypes/rhythm/assets/strings/zh-CN.ogt +61 -0
- package/archetypes/rhythm/gitattributes +22 -0
- package/archetypes/rhythm/gitignore +8 -0
- package/archetypes/rhythm/host.d.ts +46 -0
- package/archetypes/rhythm/package.json +18 -0
- package/archetypes/rhythm/project.ogt +14 -0
- package/archetypes/rhythm/references/metal/highway.png +0 -0
- package/archetypes/rhythm/references/metal/results.png +0 -0
- package/archetypes/rhythm/references/metal/title.png +0 -0
- package/archetypes/rhythm/src/components.ts +147 -0
- package/archetypes/rhythm/src/main.ts +202 -0
- package/archetypes/rhythm/src/systems.ts +490 -0
- package/archetypes/rhythm/src/ui.ts +421 -0
- package/archetypes/rhythm/tests/band.og.ts +45 -0
- package/archetypes/rhythm/tests/calibrate.og.ts +49 -0
- package/archetypes/rhythm/tests/clear.og.ts +51 -0
- package/archetypes/rhythm/tests/fail.og.ts +40 -0
- package/archetypes/rhythm/tests/flow.og.ts +54 -0
- package/archetypes/rhythm/tests/frames.og.ts +35 -0
- package/archetypes/rhythm/tests/frames.ts +134 -0
- package/archetypes/rhythm/tests/lib.ts +123 -0
- package/archetypes/rhythm/tests/pad.og.ts +41 -0
- package/archetypes/rhythm/tests/pause.og.ts +77 -0
- package/archetypes/rhythm/tests/phone.og.ts +44 -0
- package/archetypes/rhythm/tests/replay.og.ts +27 -0
- package/archetypes/rhythm/tests/timing.og.ts +37 -0
- package/archetypes/rhythm/tools/make-assets.py +383 -0
- package/archetypes/rhythm/tools/oglite.py +285 -0
- package/archetypes/rhythm/tsconfig.json +17 -0
- package/archetypes/roguelike/.origin/setup +14 -0
- package/archetypes/roguelike/LICENSES.md +14 -0
- package/archetypes/roguelike/README.md +256 -0
- package/archetypes/roguelike/assets/ai/foe.ogt +28 -0
- package/archetypes/roguelike/assets/ai/guardian.ogt +26 -0
- package/archetypes/roguelike/assets/audio/bump.wav +0 -0
- package/archetypes/roguelike/assets/audio/drink.wav +0 -0
- package/archetypes/roguelike/assets/audio/fall.wav +0 -0
- package/archetypes/roguelike/assets/audio/hit.wav +0 -0
- package/archetypes/roguelike/assets/audio/hurt.wav +0 -0
- package/archetypes/roguelike/assets/audio/item.wav +0 -0
- package/archetypes/roguelike/assets/audio/kill.wav +0 -0
- package/archetypes/roguelike/assets/audio/pickup.wav +0 -0
- package/archetypes/roguelike/assets/audio/roar.wav +0 -0
- package/archetypes/roguelike/assets/audio/stairs.wav +0 -0
- package/archetypes/roguelike/assets/audio/step.ogt +9 -0
- package/archetypes/roguelike/assets/audio/telegraph.wav +0 -0
- package/archetypes/roguelike/assets/audio/tomb.wav +0 -0
- package/archetypes/roguelike/assets/audio/ui-close.ogt +9 -0
- package/archetypes/roguelike/assets/audio/ui-error.ogt +9 -0
- package/archetypes/roguelike/assets/audio/ui-open.ogt +9 -0
- package/archetypes/roguelike/assets/audio/ui-press.ogt +9 -0
- package/archetypes/roguelike/assets/audio/ui-success.ogt +9 -0
- package/archetypes/roguelike/assets/audio/won.wav +0 -0
- package/archetypes/roguelike/assets/fonts/NotoSansSC-subset.ttf +0 -0
- package/archetypes/roguelike/assets/fonts/NotoSansSC-subset.ttf.ogt +10 -0
- package/archetypes/roguelike/assets/fonts/OFL.txt +93 -0
- package/archetypes/roguelike/assets/maps/dive.ogt +106 -0
- package/archetypes/roguelike/assets/skins/lampdive/DotGothic16-Regular.ttf +0 -0
- package/archetypes/roguelike/assets/skins/lampdive/DotGothic16-Regular.ttf.ogt +9 -0
- package/archetypes/roguelike/assets/skins/lampdive/LICENSES.md +16 -0
- package/archetypes/roguelike/assets/skins/lampdive/OFL.txt +93 -0
- package/archetypes/roguelike/assets/skins/lampdive/atlas.png +0 -0
- package/archetypes/roguelike/assets/skins/lampdive/atlas.png.ogt +7 -0
- package/archetypes/roguelike/assets/skins/lampdive/icons.png +0 -0
- package/archetypes/roguelike/assets/skins/lampdive/icons.png.ogt +7 -0
- package/archetypes/roguelike/assets/skins/lampdive/skin.ogt +115 -0
- package/archetypes/roguelike/assets/sprites/dive.ogt +50 -0
- package/archetypes/roguelike/assets/sprites/dive.png +0 -0
- package/archetypes/roguelike/assets/sprites/dive.png.ogt +7 -0
- package/archetypes/roguelike/assets/sprites/glow.png +0 -0
- package/archetypes/roguelike/assets/sprites/glow.png.ogt +7 -0
- package/archetypes/roguelike/assets/strings/en.ogt +57 -0
- package/archetypes/roguelike/assets/strings/zh-CN.ogt +57 -0
- package/archetypes/roguelike/assets/tiles/tomb.ogt +31 -0
- package/archetypes/roguelike/assets/tiles/tomb.png +0 -0
- package/archetypes/roguelike/assets/tiles/tomb.png.ogt +7 -0
- package/archetypes/roguelike/gitattributes +22 -0
- package/archetypes/roguelike/gitignore +8 -0
- package/archetypes/roguelike/host.d.ts +46 -0
- package/archetypes/roguelike/package.json +18 -0
- package/archetypes/roguelike/project.ogt +14 -0
- package/archetypes/roguelike/references/metal/dive.png +0 -0
- package/archetypes/roguelike/references/metal/over.png +0 -0
- package/archetypes/roguelike/references/metal/title.png +0 -0
- package/archetypes/roguelike/src/art.ts +23 -0
- package/archetypes/roguelike/src/components.ts +169 -0
- package/archetypes/roguelike/src/dive.ts +144 -0
- package/archetypes/roguelike/src/foes.ts +174 -0
- package/archetypes/roguelike/src/main.ts +258 -0
- package/archetypes/roguelike/src/systems.ts +620 -0
- package/archetypes/roguelike/src/ui.ts +350 -0
- package/archetypes/roguelike/tests/flow.og.ts +54 -0
- package/archetypes/roguelike/tests/foes.og.ts +45 -0
- package/archetypes/roguelike/tests/frames.og.ts +32 -0
- package/archetypes/roguelike/tests/frames.ts +134 -0
- package/archetypes/roguelike/tests/lib.ts +83 -0
- package/archetypes/roguelike/tests/lose.og.ts +44 -0
- package/archetypes/roguelike/tests/pad.og.ts +54 -0
- package/archetypes/roguelike/tests/pause.og.ts +59 -0
- package/archetypes/roguelike/tests/phone.og.ts +54 -0
- package/archetypes/roguelike/tests/replay.og.ts +24 -0
- package/archetypes/roguelike/tests/win.og.ts +60 -0
- package/archetypes/roguelike/tools/make-assets.py +518 -0
- package/archetypes/roguelike/tools/oglite.py +285 -0
- package/archetypes/roguelike/tsconfig.json +17 -0
- package/archetypes/runner/.origin/setup +14 -0
- package/archetypes/runner/LICENSES.md +10 -0
- package/archetypes/runner/README.md +225 -0
- package/archetypes/runner/assets/audio/coin.wav +0 -0
- package/archetypes/runner/assets/audio/crash.wav +0 -0
- package/archetypes/runner/assets/audio/hold.ogt +9 -0
- package/archetypes/runner/assets/audio/jump.wav +0 -0
- package/archetypes/runner/assets/audio/start.wav +0 -0
- package/archetypes/runner/assets/fonts/OFL.txt +93 -0
- package/archetypes/runner/assets/fonts/ui.ttf +0 -0
- package/archetypes/runner/assets/fonts/ui.ttf.ogt +11 -0
- package/archetypes/runner/assets/maps/far.ogt +25 -0
- package/archetypes/runner/assets/maps/near.ogt +25 -0
- package/archetypes/runner/assets/maps/roofs.ogt +19 -0
- package/archetypes/runner/assets/scenes/main.ogt +35 -0
- package/archetypes/runner/assets/sprites/coin.ogt +11 -0
- package/archetypes/runner/assets/sprites/coin.png +0 -0
- package/archetypes/runner/assets/sprites/coin.png.ogt +7 -0
- package/archetypes/runner/assets/sprites/courier.ogt +32 -0
- package/archetypes/runner/assets/sprites/courier.png +0 -0
- package/archetypes/runner/assets/sprites/courier.png.ogt +7 -0
- package/archetypes/runner/assets/sprites/props.ogt +21 -0
- package/archetypes/runner/assets/sprites/props.png +0 -0
- package/archetypes/runner/assets/sprites/props.png.ogt +7 -0
- package/archetypes/runner/assets/sprites/sky.png +0 -0
- package/archetypes/runner/assets/sprites/sky.png.ogt +7 -0
- package/archetypes/runner/assets/tiles/city.ogt +18 -0
- package/archetypes/runner/assets/tiles/city.png +0 -0
- package/archetypes/runner/assets/tiles/city.png.ogt +7 -0
- package/archetypes/runner/gitattributes +22 -0
- package/archetypes/runner/gitignore +8 -0
- package/archetypes/runner/host.d.ts +46 -0
- package/archetypes/runner/package.json +18 -0
- package/archetypes/runner/project.ogt +18 -0
- package/archetypes/runner/references/metal/frames-coin.png +0 -0
- package/archetypes/runner/references/metal/frames-crash.png +0 -0
- package/archetypes/runner/references/metal/frames-title.png +0 -0
- package/archetypes/runner/src/art.ts +57 -0
- package/archetypes/runner/src/components.ts +94 -0
- package/archetypes/runner/src/main.ts +241 -0
- package/archetypes/runner/src/systems.ts +553 -0
- package/archetypes/runner/tests/coins.og.ts +30 -0
- package/archetypes/runner/tests/flow.og.ts +72 -0
- package/archetypes/runner/tests/frames.og.ts +37 -0
- package/archetypes/runner/tests/frames.ts +134 -0
- package/archetypes/runner/tests/jump.og.ts +44 -0
- package/archetypes/runner/tests/lib.ts +42 -0
- package/archetypes/runner/tests/records.og.ts +43 -0
- package/archetypes/runner/tests/replay.og.ts +36 -0
- package/archetypes/runner/tests/sounds.og.ts +43 -0
- package/archetypes/runner/tests/tune.og.ts +36 -0
- package/archetypes/runner/tools/make-assets.py +603 -0
- package/archetypes/runner/tools/oglite.py +285 -0
- package/archetypes/runner/tsconfig.json +17 -0
- package/archetypes/third-person/.origin/setup +14 -0
- package/archetypes/third-person/LICENSES.md +23 -0
- package/archetypes/third-person/README.md +249 -0
- package/archetypes/third-person/assets/ai/sentinel-east.ogt +69 -0
- package/archetypes/third-person/assets/ai/sentinel-north.ogt +69 -0
- package/archetypes/third-person/assets/ai/sentinel-west.ogt +69 -0
- package/archetypes/third-person/assets/anims/humanoid-clips.glb +0 -0
- package/archetypes/third-person/assets/audio/alarm.wav +0 -0
- package/archetypes/third-person/assets/audio/dawn.wav +0 -0
- package/archetypes/third-person/assets/audio/grab.wav +0 -0
- package/archetypes/third-person/assets/audio/ignite.wav +0 -0
- package/archetypes/third-person/assets/audio/jump.wav +0 -0
- package/archetypes/third-person/assets/audio/night.wav +0 -0
- package/archetypes/third-person/assets/audio/splash.wav +0 -0
- package/archetypes/third-person/assets/audio/step.ogt +9 -0
- package/archetypes/third-person/assets/audio/ui-close.ogt +9 -0
- package/archetypes/third-person/assets/audio/ui-error.ogt +9 -0
- package/archetypes/third-person/assets/audio/ui-open.ogt +9 -0
- package/archetypes/third-person/assets/audio/ui-press.ogt +9 -0
- package/archetypes/third-person/assets/audio/ui-success.ogt +9 -0
- package/archetypes/third-person/assets/audio/vale.wav +0 -0
- package/archetypes/third-person/assets/fonts/NotoSansSC-subset.ttf +0 -0
- package/archetypes/third-person/assets/fonts/NotoSansSC-subset.ttf.ogt +10 -0
- package/archetypes/third-person/assets/fonts/OFL.txt +93 -0
- package/archetypes/third-person/assets/fx/burst.ogt +25 -0
- package/archetypes/third-person/assets/fx/fire.ogt +24 -0
- package/archetypes/third-person/assets/fx/smoke.ogt +24 -0
- package/archetypes/third-person/assets/fx/splash.ogt +24 -0
- package/archetypes/third-person/assets/luts/teal-orange.cube +4917 -0
- package/archetypes/third-person/assets/models/stout.glb +0 -0
- package/archetypes/third-person/assets/models/strider.glb +0 -0
- package/archetypes/third-person/assets/models/strider.glb.ogt +9 -0
- package/archetypes/third-person/assets/nav/vale.ogt +43 -0
- package/archetypes/third-person/assets/rigs/strider.ogt +6 -0
- package/archetypes/third-person/assets/skins/ember/Cinzel-Bold.ttf +0 -0
- package/archetypes/third-person/assets/skins/ember/Cinzel-Bold.ttf.ogt +9 -0
- package/archetypes/third-person/assets/skins/ember/LICENSES.md +13 -0
- package/archetypes/third-person/assets/skins/ember/Newsreader-Medium.ttf +0 -0
- package/archetypes/third-person/assets/skins/ember/Newsreader-Medium.ttf.ogt +9 -0
- package/archetypes/third-person/assets/skins/ember/OFL.txt +94 -0
- package/archetypes/third-person/assets/skins/ember/atlas.png +0 -0
- package/archetypes/third-person/assets/skins/ember/atlas.png.ogt +7 -0
- package/archetypes/third-person/assets/skins/ember/icons.png +0 -0
- package/archetypes/third-person/assets/skins/ember/icons.png.ogt +7 -0
- package/archetypes/third-person/assets/skins/ember/skin.ogt +109 -0
- package/archetypes/third-person/assets/strings/en.ogt +47 -0
- package/archetypes/third-person/assets/strings/zh-CN.ogt +47 -0
- package/archetypes/third-person/assets/terrain/vale-control.png +0 -0
- package/archetypes/third-person/assets/terrain/vale.ogt +42 -0
- package/archetypes/third-person/assets/terrain/vale.png +0 -0
- package/archetypes/third-person/assets/textures/decals.png +0 -0
- package/archetypes/third-person/assets/textures/flame.png +0 -0
- package/archetypes/third-person/assets/textures/smoke.png +0 -0
- package/archetypes/third-person/assets/textures/spark.png +0 -0
- package/archetypes/third-person/assets/textures/terrain-grass.png +0 -0
- package/archetypes/third-person/assets/textures/terrain-path.png +0 -0
- package/archetypes/third-person/assets/textures/terrain-rock.png +0 -0
- package/archetypes/third-person/assets/textures/terrain-sand.png +0 -0
- package/archetypes/third-person/gitattributes +22 -0
- package/archetypes/third-person/gitignore +8 -0
- package/archetypes/third-person/host.d.ts +46 -0
- package/archetypes/third-person/package.json +18 -0
- package/archetypes/third-person/project.ogt +14 -0
- package/archetypes/third-person/references/metal/beacon.png +0 -0
- package/archetypes/third-person/references/metal/dawn.png +0 -0
- package/archetypes/third-person/references/metal/title.png +0 -0
- package/archetypes/third-person/references/webgl2/beacon.png +0 -0
- package/archetypes/third-person/src/anim.ts +87 -0
- package/archetypes/third-person/src/beacons.ts +80 -0
- package/archetypes/third-person/src/components.ts +148 -0
- package/archetypes/third-person/src/hero.ts +293 -0
- package/archetypes/third-person/src/main.ts +164 -0
- package/archetypes/third-person/src/sentinels.ts +159 -0
- package/archetypes/third-person/src/sound.ts +66 -0
- package/archetypes/third-person/src/ui.ts +451 -0
- package/archetypes/third-person/src/world.ts +212 -0
- package/archetypes/third-person/tests/flow.og.ts +70 -0
- package/archetypes/third-person/tests/frames.og.ts +35 -0
- package/archetypes/third-person/tests/frames.ts +134 -0
- package/archetypes/third-person/tests/hitstop.og.ts +26 -0
- package/archetypes/third-person/tests/lib.ts +87 -0
- package/archetypes/third-person/tests/lose.og.ts +44 -0
- package/archetypes/third-person/tests/pause.og.ts +64 -0
- package/archetypes/third-person/tests/phone.og.ts +65 -0
- package/archetypes/third-person/tests/replay.og.ts +32 -0
- package/archetypes/third-person/tests/restart.og.ts +28 -0
- package/archetypes/third-person/tests/sentinels.og.ts +48 -0
- package/archetypes/third-person/tests/win.og.ts +62 -0
- package/archetypes/third-person/tools/make-assets.py +353 -0
- package/archetypes/third-person/tools/oglite.py +285 -0
- package/archetypes/third-person/tsconfig.json +17 -0
- package/archetypes/topdown/.origin/setup +14 -0
- package/archetypes/topdown/LICENSES.md +10 -0
- package/archetypes/topdown/README.md +235 -0
- package/archetypes/topdown/assets/ai/slime.ogt +49 -0
- package/archetypes/topdown/assets/audio/coin.wav +0 -0
- package/archetypes/topdown/assets/audio/door.wav +0 -0
- package/archetypes/topdown/assets/audio/hit.wav +0 -0
- package/archetypes/topdown/assets/audio/hurt.wav +0 -0
- package/archetypes/topdown/assets/audio/key.wav +0 -0
- package/archetypes/topdown/assets/audio/step.ogt +9 -0
- package/archetypes/topdown/assets/fonts/OFL.txt +93 -0
- package/archetypes/topdown/assets/fonts/ui.ttf +0 -0
- package/archetypes/topdown/assets/fonts/ui.ttf.ogt +9 -0
- package/archetypes/topdown/assets/maps/tomb.tmj +2183 -0
- package/archetypes/topdown/assets/sprites/hero.ogt +58 -0
- package/archetypes/topdown/assets/sprites/hero.png +0 -0
- package/archetypes/topdown/assets/sprites/hero.png.ogt +7 -0
- package/archetypes/topdown/assets/sprites/items.ogt +15 -0
- package/archetypes/topdown/assets/sprites/items.png +0 -0
- package/archetypes/topdown/assets/sprites/items.png.ogt +7 -0
- package/archetypes/topdown/assets/sprites/slime.ogt +17 -0
- package/archetypes/topdown/assets/sprites/slime.png +0 -0
- package/archetypes/topdown/assets/sprites/slime.png.ogt +7 -0
- package/archetypes/topdown/assets/tiles/dungeon.ogt +65 -0
- package/archetypes/topdown/assets/tiles/dungeon.png +0 -0
- package/archetypes/topdown/assets/tiles/dungeon.png.ogt +7 -0
- package/archetypes/topdown/gitattributes +22 -0
- package/archetypes/topdown/gitignore +8 -0
- package/archetypes/topdown/host.d.ts +46 -0
- package/archetypes/topdown/package.json +18 -0
- package/archetypes/topdown/project.ogt +14 -0
- package/archetypes/topdown/references/metal/crit.png +0 -0
- package/archetypes/topdown/references/metal/dash.png +0 -0
- package/archetypes/topdown/references/metal/east.png +0 -0
- package/archetypes/topdown/references/metal/start.png +0 -0
- package/archetypes/topdown/src/art.ts +48 -0
- package/archetypes/topdown/src/components.ts +128 -0
- package/archetypes/topdown/src/main.ts +275 -0
- package/archetypes/topdown/src/systems.ts +503 -0
- package/archetypes/topdown/tests/ai.og.ts +64 -0
- package/archetypes/topdown/tests/combat.og.ts +72 -0
- package/archetypes/topdown/tests/door.og.ts +62 -0
- package/archetypes/topdown/tests/flee.og.ts +49 -0
- package/archetypes/topdown/tests/frames.og.ts +45 -0
- package/archetypes/topdown/tests/frames.ts +134 -0
- package/archetypes/topdown/tests/lib.ts +71 -0
- package/archetypes/topdown/tests/replay.og.ts +40 -0
- package/archetypes/topdown/tests/walk.og.ts +46 -0
- package/archetypes/topdown/tools/make-assets.py +623 -0
- package/archetypes/topdown/tools/oglite.py +285 -0
- package/archetypes/topdown/tsconfig.json +17 -0
- package/archetypes/tower-defense/.origin/setup +14 -0
- package/archetypes/tower-defense/LICENSES.md +15 -0
- package/archetypes/tower-defense/README.md +240 -0
- package/archetypes/tower-defense/assets/ai/plant.ogt +16 -0
- package/archetypes/tower-defense/assets/audio/clear.wav +0 -0
- package/archetypes/tower-defense/assets/audio/frost.wav +0 -0
- package/archetypes/tower-defense/assets/audio/leak.wav +0 -0
- package/archetypes/tower-defense/assets/audio/lost.wav +0 -0
- package/archetypes/tower-defense/assets/audio/night.wav +0 -0
- package/archetypes/tower-defense/assets/audio/plant.wav +0 -0
- package/archetypes/tower-defense/assets/audio/pop.wav +0 -0
- package/archetypes/tower-defense/assets/audio/thorn.wav +0 -0
- package/archetypes/tower-defense/assets/audio/ui-close.ogt +9 -0
- package/archetypes/tower-defense/assets/audio/ui-error.ogt +9 -0
- package/archetypes/tower-defense/assets/audio/ui-open.ogt +9 -0
- package/archetypes/tower-defense/assets/audio/ui-press.ogt +9 -0
- package/archetypes/tower-defense/assets/audio/ui-success.ogt +9 -0
- package/archetypes/tower-defense/assets/audio/wave.wav +0 -0
- package/archetypes/tower-defense/assets/audio/won.wav +0 -0
- package/archetypes/tower-defense/assets/fonts/NotoSansSC-subset.ttf +0 -0
- package/archetypes/tower-defense/assets/fonts/NotoSansSC-subset.ttf.ogt +10 -0
- package/archetypes/tower-defense/assets/fonts/OFL.txt +93 -0
- package/archetypes/tower-defense/assets/fx/fireflies.ogt +21 -0
- package/archetypes/tower-defense/assets/fx/pop.ogt +21 -0
- package/archetypes/tower-defense/assets/maps/garden.ogt +91 -0
- package/archetypes/tower-defense/assets/skins/pathguard/Fredoka-SemiBold.ttf +0 -0
- package/archetypes/tower-defense/assets/skins/pathguard/Fredoka-SemiBold.ttf.ogt +9 -0
- package/archetypes/tower-defense/assets/skins/pathguard/LICENSES.md +13 -0
- package/archetypes/tower-defense/assets/skins/pathguard/LilitaOne-Regular.ttf +0 -0
- package/archetypes/tower-defense/assets/skins/pathguard/LilitaOne-Regular.ttf.ogt +9 -0
- package/archetypes/tower-defense/assets/skins/pathguard/OFL.txt +94 -0
- package/archetypes/tower-defense/assets/skins/pathguard/atlas.png +0 -0
- package/archetypes/tower-defense/assets/skins/pathguard/atlas.png.ogt +7 -0
- package/archetypes/tower-defense/assets/skins/pathguard/icons.png +0 -0
- package/archetypes/tower-defense/assets/skins/pathguard/icons.png.ogt +7 -0
- package/archetypes/tower-defense/assets/skins/pathguard/skin.ogt +111 -0
- package/archetypes/tower-defense/assets/sprites/garden.ogt +66 -0
- package/archetypes/tower-defense/assets/sprites/garden.png +0 -0
- package/archetypes/tower-defense/assets/sprites/garden.png.ogt +7 -0
- package/archetypes/tower-defense/assets/sprites/glow.png +0 -0
- package/archetypes/tower-defense/assets/sprites/glow.png.ogt +7 -0
- package/archetypes/tower-defense/assets/sprites/ring.png +0 -0
- package/archetypes/tower-defense/assets/sprites/ring.png.ogt +7 -0
- package/archetypes/tower-defense/assets/sprites/spark.png +0 -0
- package/archetypes/tower-defense/assets/sprites/spark.png.ogt +7 -0
- package/archetypes/tower-defense/assets/strings/en.ogt +47 -0
- package/archetypes/tower-defense/assets/strings/zh-CN.ogt +47 -0
- package/archetypes/tower-defense/assets/tiles/garden.ogt +10 -0
- package/archetypes/tower-defense/assets/tiles/garden.png +0 -0
- package/archetypes/tower-defense/assets/tiles/garden.png.ogt +7 -0
- package/archetypes/tower-defense/gitattributes +22 -0
- package/archetypes/tower-defense/gitignore +8 -0
- package/archetypes/tower-defense/host.d.ts +46 -0
- package/archetypes/tower-defense/package.json +18 -0
- package/archetypes/tower-defense/project.ogt +14 -0
- package/archetypes/tower-defense/references/metal/end.png +0 -0
- package/archetypes/tower-defense/references/metal/title.png +0 -0
- package/archetypes/tower-defense/references/metal/wave.png +0 -0
- package/archetypes/tower-defense/src/art.ts +24 -0
- package/archetypes/tower-defense/src/components.ts +156 -0
- package/archetypes/tower-defense/src/main.ts +253 -0
- package/archetypes/tower-defense/src/systems.ts +658 -0
- package/archetypes/tower-defense/src/ui.ts +382 -0
- package/archetypes/tower-defense/tests/flow.og.ts +56 -0
- package/archetypes/tower-defense/tests/frames.og.ts +31 -0
- package/archetypes/tower-defense/tests/frames.ts +134 -0
- package/archetypes/tower-defense/tests/lib.ts +81 -0
- package/archetypes/tower-defense/tests/lose.og.ts +40 -0
- package/archetypes/tower-defense/tests/maze.og.ts +53 -0
- package/archetypes/tower-defense/tests/pad.og.ts +41 -0
- package/archetypes/tower-defense/tests/pause.og.ts +59 -0
- package/archetypes/tower-defense/tests/phone.og.ts +49 -0
- package/archetypes/tower-defense/tests/replay.og.ts +28 -0
- package/archetypes/tower-defense/tests/win.og.ts +58 -0
- package/archetypes/tower-defense/tools/make-assets.py +640 -0
- package/archetypes/tower-defense/tools/oglite.py +285 -0
- package/archetypes/tower-defense/tsconfig.json +17 -0
- package/bin/create.ts +503 -0
- package/looks/catalogue.json +1871 -0
- package/package.json +31 -4
- package/template/.origin/setup +14 -0
- package/template/LICENSES.md +23 -0
- package/template/README.md +37 -0
- package/template/assets/ai/guard.ogt +48 -0
- package/template/assets/audio/blip.wav +0 -0
- package/template/assets/audio/click.ogt +9 -0
- package/template/assets/fonts/NotoSansSC-Regular-subset.ttf +0 -0
- package/template/assets/fonts/NotoSansSC-Regular-subset.ttf.ogt +12 -0
- package/template/assets/fonts/OFL.txt +93 -0
- package/template/assets/looks/origin-game.ogt +12 -0
- package/template/assets/models/dropship.glb +0 -0
- package/template/assets/models/walker.glb +0 -0
- package/template/assets/nav/yard.ogt +27 -0
- package/template/assets/scenes/main.ogt +34 -0
- package/template/assets/strings/en.ogt +14 -0
- package/template/assets/textures/stone.png +0 -0
- package/template/assets/textures/stone_n.png +0 -0
- package/template/assets/textures/stone_n.png.ogt +7 -0
- package/template/gitattributes +22 -0
- package/template/gitignore +8 -0
- package/template/package.json +18 -0
- package/template/project.ogt +25 -0
- package/template/src/main.ts +246 -0
- package/template/tests/guard.og.ts +67 -0
- package/template/tests/smoke.og.ts +43 -0
- package/template/tsconfig.json +17 -0
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
"""A tiny, standard-library-only sprite kit for Origin Engine archetypes.
|
|
2
|
+
|
|
3
|
+
It draws antialiased vector shapes into RGBA images (4x4 supersampling),
|
|
4
|
+
writes PNGs, packs sprites into one glTF binary (.glb) of unit quads, one
|
|
5
|
+
mesh and one emissive, alpha-masked material per sprite, and writes 16-bit
|
|
6
|
+
WAV sounds. Everything is a pure function of its inputs, so the assets it
|
|
7
|
+
makes are byte-for-byte reproducible.
|
|
8
|
+
|
|
9
|
+
A sprite quad lies in the xy plane facing +z, 1 x 1 units, centred on the
|
|
10
|
+
origin, with uv (0,0) at the image's top left. Its material is black base
|
|
11
|
+
colour (alpha from the image, for the mask), roughness 1, and the image as
|
|
12
|
+
the emissive texture: with no light, no environment and tone mapping off,
|
|
13
|
+
the frame shows the image's colours exactly.
|
|
14
|
+
"""
|
|
15
|
+
import json, math, struct, wave, zlib
|
|
16
|
+
|
|
17
|
+
SS = 4 # supersamples per axis
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def hex_rgb(h):
|
|
21
|
+
h = h.lstrip("#")
|
|
22
|
+
return tuple(int(h[i:i + 2], 16) for i in (0, 2, 4))
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class Canvas:
|
|
26
|
+
"""An RGBA canvas; shapes are painted in order with coverage antialiasing.
|
|
27
|
+
Coordinates are in pixels, origin top left, y down."""
|
|
28
|
+
|
|
29
|
+
def __init__(self, w, h):
|
|
30
|
+
self.w, self.h = w, h
|
|
31
|
+
self.px = [[0.0, 0.0, 0.0, 0.0] for _ in range(w * h)] # premultiplied
|
|
32
|
+
|
|
33
|
+
def _paint(self, inside, bbox, colour, alpha=1.0):
|
|
34
|
+
r, g, b = (c / 255.0 for c in hex_rgb(colour))
|
|
35
|
+
x0, y0, x1, y1 = bbox
|
|
36
|
+
x0 = max(0, int(math.floor(x0))); y0 = max(0, int(math.floor(y0)))
|
|
37
|
+
x1 = min(self.w, int(math.ceil(x1))); y1 = min(self.h, int(math.ceil(y1)))
|
|
38
|
+
n = SS * SS
|
|
39
|
+
for y in range(y0, y1):
|
|
40
|
+
for x in range(x0, x1):
|
|
41
|
+
hits = 0
|
|
42
|
+
for sy in range(SS):
|
|
43
|
+
py = y + (sy + 0.5) / SS
|
|
44
|
+
for sx in range(SS):
|
|
45
|
+
if inside(x + (sx + 0.5) / SS, py):
|
|
46
|
+
hits += 1
|
|
47
|
+
if hits == 0:
|
|
48
|
+
continue
|
|
49
|
+
a = alpha * hits / n
|
|
50
|
+
p = self.px[y * self.w + x]
|
|
51
|
+
p[0] = r * a + p[0] * (1 - a)
|
|
52
|
+
p[1] = g * a + p[1] * (1 - a)
|
|
53
|
+
p[2] = b * a + p[2] * (1 - a)
|
|
54
|
+
p[3] = a + p[3] * (1 - a)
|
|
55
|
+
|
|
56
|
+
def rect(self, x, y, w, h, colour, radius=0.0, alpha=1.0):
|
|
57
|
+
rad = min(radius, w / 2, h / 2)
|
|
58
|
+
|
|
59
|
+
def inside(px, py):
|
|
60
|
+
if px < x or px > x + w or py < y or py > y + h:
|
|
61
|
+
return False
|
|
62
|
+
if rad <= 0:
|
|
63
|
+
return True
|
|
64
|
+
cx = min(max(px, x + rad), x + w - rad)
|
|
65
|
+
cy = min(max(py, y + rad), y + h - rad)
|
|
66
|
+
return (px - cx) ** 2 + (py - cy) ** 2 <= rad * rad
|
|
67
|
+
|
|
68
|
+
self._paint(inside, (x, y, x + w, y + h), colour, alpha)
|
|
69
|
+
|
|
70
|
+
def circle(self, cx, cy, r, colour, alpha=1.0):
|
|
71
|
+
self.ellipse(cx, cy, r, r, colour, alpha)
|
|
72
|
+
|
|
73
|
+
def ellipse(self, cx, cy, rx, ry, colour, alpha=1.0):
|
|
74
|
+
def inside(px, py):
|
|
75
|
+
return ((px - cx) / rx) ** 2 + ((py - cy) / ry) ** 2 <= 1.0
|
|
76
|
+
|
|
77
|
+
self._paint(inside, (cx - rx, cy - ry, cx + rx, cy + ry), colour, alpha)
|
|
78
|
+
|
|
79
|
+
def ring(self, cx, cy, r, width, colour, alpha=1.0):
|
|
80
|
+
def inside(px, py):
|
|
81
|
+
d = math.hypot(px - cx, py - cy)
|
|
82
|
+
return r - width <= d <= r
|
|
83
|
+
|
|
84
|
+
self._paint(inside, (cx - r, cy - r, cx + r, cy + r), colour, alpha)
|
|
85
|
+
|
|
86
|
+
def poly(self, pts, colour, alpha=1.0):
|
|
87
|
+
xs = [p[0] for p in pts]; ys = [p[1] for p in pts]
|
|
88
|
+
|
|
89
|
+
def inside(px, py):
|
|
90
|
+
c = False
|
|
91
|
+
j = len(pts) - 1
|
|
92
|
+
for i in range(len(pts)):
|
|
93
|
+
xi, yi = pts[i]; xj, yj = pts[j]
|
|
94
|
+
if (yi > py) != (yj > py) and px < (xj - xi) * (py - yi) / (yj - yi) + xi:
|
|
95
|
+
c = not c
|
|
96
|
+
j = i
|
|
97
|
+
return c
|
|
98
|
+
|
|
99
|
+
self._paint(inside, (min(xs), min(ys), max(xs), max(ys)), colour, alpha)
|
|
100
|
+
|
|
101
|
+
def line(self, x0, y0, x1, y1, width, colour, alpha=1.0):
|
|
102
|
+
dx, dy = x1 - x0, y1 - y0
|
|
103
|
+
ln = math.hypot(dx, dy) or 1.0
|
|
104
|
+
nx, ny = -dy / ln * width / 2, dx / ln * width / 2
|
|
105
|
+
self.poly([(x0 + nx, y0 + ny), (x1 + nx, y1 + ny), (x1 - nx, y1 - ny), (x0 - nx, y0 - ny)], colour, alpha)
|
|
106
|
+
self.circle(x0, y0, width / 2, colour, alpha)
|
|
107
|
+
self.circle(x1, y1, width / 2, colour, alpha)
|
|
108
|
+
|
|
109
|
+
def rgba(self):
|
|
110
|
+
"""Straight-alpha RGBA8 rows. Transparent pixels take the colour of
|
|
111
|
+
the nearest painted pixel (a few dilation passes), so filtering and
|
|
112
|
+
mips never pull a dark fringe into the edge."""
|
|
113
|
+
w, h = self.w, self.h
|
|
114
|
+
col = [None] * (w * h)
|
|
115
|
+
for i, p in enumerate(self.px):
|
|
116
|
+
if p[3] > 0:
|
|
117
|
+
col[i] = (p[0] / p[3], p[1] / p[3], p[2] / p[3])
|
|
118
|
+
for _ in range(8):
|
|
119
|
+
nxt = list(col)
|
|
120
|
+
changed = False
|
|
121
|
+
for y in range(h):
|
|
122
|
+
for x in range(w):
|
|
123
|
+
i = y * w + x
|
|
124
|
+
if col[i] is not None:
|
|
125
|
+
continue
|
|
126
|
+
for dx, dy in ((1, 0), (-1, 0), (0, 1), (0, -1)):
|
|
127
|
+
xx, yy = x + dx, y + dy
|
|
128
|
+
if 0 <= xx < w and 0 <= yy < h and col[yy * w + xx] is not None:
|
|
129
|
+
nxt[i] = col[yy * w + xx]
|
|
130
|
+
changed = True
|
|
131
|
+
break
|
|
132
|
+
col = nxt
|
|
133
|
+
if not changed:
|
|
134
|
+
break
|
|
135
|
+
rows = []
|
|
136
|
+
for y in range(h):
|
|
137
|
+
row = bytearray()
|
|
138
|
+
for x in range(w):
|
|
139
|
+
i = y * w + x
|
|
140
|
+
c = col[i] or (0.0, 0.0, 0.0)
|
|
141
|
+
a = self.px[i][3]
|
|
142
|
+
row += bytes([round(min(1, max(0, c[0])) * 255), round(min(1, max(0, c[1])) * 255),
|
|
143
|
+
round(min(1, max(0, c[2])) * 255), round(min(1, max(0, a)) * 255)])
|
|
144
|
+
rows.append(bytes(row))
|
|
145
|
+
return rows
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def png_bytes(w, h, rows):
|
|
149
|
+
raw = b"".join(b"\x00" + r for r in rows)
|
|
150
|
+
|
|
151
|
+
def chunk(t, d):
|
|
152
|
+
return struct.pack(">I", len(d)) + t + d + struct.pack(">I", zlib.crc32(t + d) & 0xFFFFFFFF)
|
|
153
|
+
|
|
154
|
+
return (b"\x89PNG\r\n\x1a\n" + chunk(b"IHDR", struct.pack(">IIBBBBB", w, h, 8, 6, 0, 0, 0))
|
|
155
|
+
+ chunk(b"IDAT", zlib.compress(raw, 9)) + chunk(b"IEND", b""))
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def write_glb(path, sprites):
|
|
159
|
+
"""sprites: list of (name, png bytes, masked). One quad mesh per sprite,
|
|
160
|
+
in list order: GltfInfo.geometries[i] and materials[i] are sprite i."""
|
|
161
|
+
bin_ = bytearray()
|
|
162
|
+
|
|
163
|
+
def add(data, align=4):
|
|
164
|
+
while len(bin_) % align:
|
|
165
|
+
bin_.append(0)
|
|
166
|
+
off = len(bin_)
|
|
167
|
+
bin_.extend(data)
|
|
168
|
+
return off, len(data)
|
|
169
|
+
|
|
170
|
+
pos = struct.pack("<12f", -0.5, -0.5, 0, 0.5, -0.5, 0, 0.5, 0.5, 0, -0.5, 0.5, 0)
|
|
171
|
+
nrm = struct.pack("<12f", *([0, 0, 1] * 4))
|
|
172
|
+
uv = struct.pack("<8f", 0, 1, 1, 1, 1, 0, 0, 0)
|
|
173
|
+
idx = struct.pack("<6H", 0, 1, 2, 0, 2, 3)
|
|
174
|
+
views, accessors = [], []
|
|
175
|
+
for data, target in ((pos, 34962), (nrm, 34962), (uv, 34962), (idx, 34963)):
|
|
176
|
+
o, n = add(data)
|
|
177
|
+
views.append({"buffer": 0, "byteOffset": o, "byteLength": n, "target": target})
|
|
178
|
+
accessors = [
|
|
179
|
+
{"bufferView": 0, "componentType": 5126, "count": 4, "type": "VEC3", "min": [-0.5, -0.5, 0], "max": [0.5, 0.5, 0]},
|
|
180
|
+
{"bufferView": 1, "componentType": 5126, "count": 4, "type": "VEC3"},
|
|
181
|
+
{"bufferView": 2, "componentType": 5126, "count": 4, "type": "VEC2"},
|
|
182
|
+
{"bufferView": 3, "componentType": 5123, "count": 6, "type": "SCALAR"},
|
|
183
|
+
]
|
|
184
|
+
images, textures, materials, meshes, nodes = [], [], [], [], []
|
|
185
|
+
for i, (name, data, masked) in enumerate(sprites):
|
|
186
|
+
o, n = add(data)
|
|
187
|
+
views.append({"buffer": 0, "byteOffset": o, "byteLength": n})
|
|
188
|
+
images.append({"bufferView": len(views) - 1, "mimeType": "image/png", "name": name})
|
|
189
|
+
textures.append({"source": i, "sampler": 0})
|
|
190
|
+
m = {
|
|
191
|
+
"name": name,
|
|
192
|
+
"pbrMetallicRoughness": {"baseColorFactor": [0, 0, 0, 1], "baseColorTexture": {"index": i},
|
|
193
|
+
"metallicFactor": 0, "roughnessFactor": 1},
|
|
194
|
+
"emissiveTexture": {"index": i},
|
|
195
|
+
"emissiveFactor": [1, 1, 1],
|
|
196
|
+
}
|
|
197
|
+
if masked:
|
|
198
|
+
m["alphaMode"] = "MASK"
|
|
199
|
+
m["alphaCutoff"] = 0.5
|
|
200
|
+
materials.append(m)
|
|
201
|
+
meshes.append({"name": name, "primitives": [{"attributes": {"POSITION": 0, "NORMAL": 1, "TEXCOORD_0": 2},
|
|
202
|
+
"indices": 3, "material": i}]})
|
|
203
|
+
nodes.append({"name": name, "mesh": i, "translation": [i * 1.2, 0, 0]})
|
|
204
|
+
while len(bin_) % 4:
|
|
205
|
+
bin_.append(0)
|
|
206
|
+
doc = {
|
|
207
|
+
"asset": {"version": "2.0", "generator": "oglite.py"},
|
|
208
|
+
"scene": 0, "scenes": [{"nodes": list(range(len(nodes)))}], "nodes": nodes, "meshes": meshes,
|
|
209
|
+
"materials": materials, "textures": textures, "images": images,
|
|
210
|
+
"samplers": [{"magFilter": 9729, "minFilter": 9987, "wrapS": 33071, "wrapT": 33071}],
|
|
211
|
+
"accessors": accessors, "bufferViews": views, "buffers": [{"byteLength": len(bin_)}],
|
|
212
|
+
}
|
|
213
|
+
js = json.dumps(doc, separators=(",", ":")).encode()
|
|
214
|
+
while len(js) % 4:
|
|
215
|
+
js += b" "
|
|
216
|
+
out = struct.pack("<III", 0x46546C67, 2, 12 + 8 + len(js) + 8 + len(bin_))
|
|
217
|
+
out += struct.pack("<II", len(js), 0x4E4F534A) + js + struct.pack("<II", len(bin_), 0x004E4942) + bytes(bin_)
|
|
218
|
+
with open(path, "wb") as f:
|
|
219
|
+
f.write(out)
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
def write_wav(path, samples, rate=22050):
|
|
223
|
+
"""samples: floats in [-1, 1], mono."""
|
|
224
|
+
with wave.open(path, "wb") as w:
|
|
225
|
+
w.setnchannels(1)
|
|
226
|
+
w.setsampwidth(2)
|
|
227
|
+
w.setframerate(rate)
|
|
228
|
+
w.writeframes(b"".join(struct.pack("<h", int(max(-1, min(1, s)) * 32000)) for s in samples))
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
def tone(seconds, f0, f1=None, rate=22050, shape="sine", attack=0.005, decay=None, gain=0.6):
|
|
232
|
+
"""A sweep from f0 to f1 Hz with a short attack and an exponential decay."""
|
|
233
|
+
f1 = f0 if f1 is None else f1
|
|
234
|
+
n = int(seconds * rate)
|
|
235
|
+
out, phase = [], 0.0
|
|
236
|
+
decay = decay or seconds / 4
|
|
237
|
+
for i in range(n):
|
|
238
|
+
t = i / rate
|
|
239
|
+
f = f0 + (f1 - f0) * (i / max(1, n - 1))
|
|
240
|
+
phase += 2 * math.pi * f / rate
|
|
241
|
+
if shape == "square":
|
|
242
|
+
s = 1.0 if math.sin(phase) >= 0 else -1.0
|
|
243
|
+
s *= 0.5
|
|
244
|
+
elif shape == "tri":
|
|
245
|
+
s = 2 / math.pi * math.asin(math.sin(phase))
|
|
246
|
+
else:
|
|
247
|
+
s = math.sin(phase)
|
|
248
|
+
env = min(1.0, t / attack) * math.exp(-t / decay)
|
|
249
|
+
out.append(s * env * gain)
|
|
250
|
+
return out
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
def noise(seconds, rate=22050, decay=0.08, gain=0.5, seed=1):
|
|
254
|
+
x = seed & 0xFFFFFFFF
|
|
255
|
+
out = []
|
|
256
|
+
for i in range(int(seconds * rate)):
|
|
257
|
+
x ^= (x << 13) & 0xFFFFFFFF; x ^= x >> 17; x ^= (x << 5) & 0xFFFFFFFF
|
|
258
|
+
out.append(((x / 0xFFFFFFFF) * 2 - 1) * math.exp(-(i / rate) / decay) * gain)
|
|
259
|
+
return out
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
def mix(*parts):
|
|
263
|
+
n = max(len(p) for p in parts)
|
|
264
|
+
return [sum(p[i] for p in parts if i < len(p)) for i in range(n)]
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
def concat(*parts):
|
|
268
|
+
out = []
|
|
269
|
+
for p in parts:
|
|
270
|
+
out.extend(p)
|
|
271
|
+
return out
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
def subset_font(src, dst, text):
|
|
275
|
+
"""Subset a TTF to Latin-1 plus `text` (needs fontTools)."""
|
|
276
|
+
from fontTools import subset
|
|
277
|
+
opts = subset.Options()
|
|
278
|
+
opts.name_IDs = ["*"]
|
|
279
|
+
opts.notdef_outline = True
|
|
280
|
+
opts.layout_features = []
|
|
281
|
+
font = subset.load_font(src, opts)
|
|
282
|
+
s = subset.Subsetter(opts)
|
|
283
|
+
s.populate(text="".join(chr(c) for c in range(0x20, 0x7F)) + "".join(chr(c) for c in range(0xA0, 0x100)) + text)
|
|
284
|
+
s.subset(font)
|
|
285
|
+
subset.save_font(font, dst, opts)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "Bundler",
|
|
6
|
+
"lib": ["ES2022"],
|
|
7
|
+
"types": [],
|
|
8
|
+
"strict": true,
|
|
9
|
+
"exactOptionalPropertyTypes": true,
|
|
10
|
+
"noFallthroughCasesInSwitch": true,
|
|
11
|
+
"isolatedModules": true,
|
|
12
|
+
"verbatimModuleSyntax": true,
|
|
13
|
+
"allowImportingTsExtensions": true,
|
|
14
|
+
"noEmit": true
|
|
15
|
+
},
|
|
16
|
+
"include": ["src/**/*.ts", "tests/**/*.ts", "host.d.ts"]
|
|
17
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# Prepares this Game's cloud sandbox snapshot: Origin runs it once per
|
|
3
|
+
# snapshot build, in the checkout, without a terminal, for at most 20 minutes,
|
|
4
|
+
# and saves the result for new sandboxes of the Game. Keep it idempotent; it
|
|
5
|
+
# never receives credentials. Only ignored output is kept: node_modules/ and
|
|
6
|
+
# cooked/ (og cook is incremental, so a new sandbox starts cooked).
|
|
7
|
+
set -eu
|
|
8
|
+
if [ -f bun.lock ]; then bun install --frozen-lockfile; else bun install; fi
|
|
9
|
+
og="${ORIGIN_OG_BIN:-og}"
|
|
10
|
+
if ! command -v "$og" >/dev/null 2>&1; then
|
|
11
|
+
echo "no og on this executor class; the first og run cooks instead"
|
|
12
|
+
exit 0
|
|
13
|
+
fi
|
|
14
|
+
"$og" cook .
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Asset licences
|
|
2
|
+
|
|
3
|
+
Nothing in this project is downloaded: every asset is self-made by the
|
|
4
|
+
Origin Engine authors or one of the engine's CC0 assets.
|
|
5
|
+
|
|
6
|
+
| File | Licence | Origin |
|
|
7
|
+
|---|---|---|
|
|
8
|
+
| `assets/terrain/vale.png`, `assets/terrain/vale-control.png` | CC0 1.0 | self-made: the vale's 16-bit heightmap and its splat control map, drawn by `tools/make-assets.py` (standard library only, deterministic) |
|
|
9
|
+
| `assets/terrain/vale.ogt` | CC0 1.0 | self-made: the terrain's layers and rules, written by hand |
|
|
10
|
+
| `assets/textures/terrain-*.png` | CC0 1.0 | the engine's: `templates/fx-showcase` (`tools/make-terrain.py`) |
|
|
11
|
+
| `assets/textures/flame.png`, `smoke.png`, `spark.png`, `decals.png`, `assets/luts/teal-orange.cube` | CC0 1.0 | the engine's: `templates/fx-showcase` (`tools/make-assets.py`) |
|
|
12
|
+
| `assets/fx/fire.ogt`, `smoke.ogt` | CC0 1.0 | the engine's: `templates/fx-showcase`, written by hand |
|
|
13
|
+
| `assets/fx/burst.ogt`, `splash.ogt` | CC0 1.0 | self-made: the beacon's embers and the lake's splash, written by hand |
|
|
14
|
+
| `assets/models/strider.glb`, `assets/models/stout.glb`, `assets/anims/humanoid-clips.glb` | CC0 1.0 | the engine's: generated by `crates/og-anim/tools/make_humanoids.py` (copied from `templates/fx-showcase`) |
|
|
15
|
+
| `assets/models/strider.glb.ogt`, `assets/rigs/strider.ogt` | CC0 1.0 | the engine's: `templates/fx-showcase`, written by hand |
|
|
16
|
+
| `assets/ai/*.ogt` | CC0 1.0 | self-made: the sentinels' behaviours and rounds, written by `tools/make-assets.py` |
|
|
17
|
+
| `assets/nav/vale.ogt` | CC0 1.0 | self-made: the navmesh's bake settings, written by hand |
|
|
18
|
+
| `assets/audio/*.wav` | CC0 1.0 | self-made: synthesised tones and noise (the ignition, alarm, grab, splash, jump, dawn and night) and the vale's music loop, `tools/make-assets.py` |
|
|
19
|
+
| `assets/audio/*.ogt` | CC0 1.0 | `og sfx` presets (click, select, back, error, levelup and a footstep) that `og cook` synthesises, written by the same script |
|
|
20
|
+
| `assets/strings/*.ogt` | CC0 1.0 | self-made: the English and Chinese string tables |
|
|
21
|
+
| `assets/fonts/NotoSansSC-subset.ttf` | SIL Open Font License 1.1 (`assets/fonts/OFL.txt`) | Noto Sans SC Regular, subset to Latin-1, CJK punctuation and the characters of `assets/strings/zh-CN.ogt` by the same script from the project template's `assets/fonts/NotoSansSC-Regular-subset.ttf` |
|
|
22
|
+
| `assets/skins/ember/*` | CC0 1.0 art, SIL OFL 1.1 fonts | the engine's fantasy style pack (`templates/ui-kit`), `assets/skins/ember/LICENSES.md` |
|
|
23
|
+
| `references/*/*.png` | CC0 1.0 | frames of this game recorded by `tests/frames.og.ts` |
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
# Ember Vale — the third-person archetype (3D)
|
|
2
|
+
|
|
3
|
+
Dusk is falling on a lake vale and four beacons stand dark on its knolls.
|
|
4
|
+
The lamplighter walks, runs, wades and jumps there; holding F by a beacon
|
|
5
|
+
it walks up to the plinth, reaches into the bowl and, a moment later, the
|
|
6
|
+
beacon catches. Three stone sentinels walk their rounds of the lake path:
|
|
7
|
+
one that sees the lamplighter calls the alarm and runs it down, and its
|
|
8
|
+
grab costs a heart. The lake is a refuge (the sentinels' navmesh stops at
|
|
9
|
+
the shore) but wading is slow. Every beacon lit before night wins the run;
|
|
10
|
+
three hearts gone, or night, loses it. Then the summary, and again.
|
|
11
|
+
|
|
12
|
+
余烬山谷:暮色正落在湖谷上,四座烽火台在小丘上黑着。点灯人可以走、跑、涉水、跳跃;在烽火台旁按住 F,它会走到台前,把手伸进火盆,片刻之后烽火燃起。三个石头哨兵沿湖边小路巡逻:看见点灯人的哨兵会发出警报并追上来,被抓住就失去一颗心。湖水是避难所(哨兵的导航网格止于岸边),但涉水很慢。入夜前点燃全部烽火即获胜;三颗心都失去或夜幕降临则失败。随后是总结,再来一次。
|
|
13
|
+
|
|
14
|
+
This is a complete Origin Engine project: `og run .` plays it headless,
|
|
15
|
+
`og build .` makes the play page, `og test .` runs its playtests and
|
|
16
|
+
`og polish .` scores them. It is the engine's mid-size 3D slice: one
|
|
17
|
+
third-person loop that uses the 3D systems together rather than a station
|
|
18
|
+
per feature (templates/fx-showcase has the stations).
|
|
19
|
+
|
|
20
|
+
```sh
|
|
21
|
+
og cook . # assets/ into cooked/ (og run and og build cook too)
|
|
22
|
+
og run . --headless --commands "0.6:run;0.8:warp:0;1:key_down:KeyF;3:screenshot:beacon.png;3.1:quit"
|
|
23
|
+
og test . # tests/*.og.ts through og run --headless --commands
|
|
24
|
+
og polish . # the playtests scored against og-taste and og-feel
|
|
25
|
+
og build . --publish # dist/: the play page as it ships (behind "tap to play")
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## What it demonstrates, and the skills it exercises
|
|
29
|
+
|
|
30
|
+
- **Terrain and water** (og-terrain, og-render §water): `assets/terrain/vale.ogt`
|
|
31
|
+
is a 128 m heightmap (a meadow, a lake basin, a knoll under each beacon,
|
|
32
|
+
a ring of cliffs) splatted from a control map with grass, path, rock and
|
|
33
|
+
sand (rock and sand by slope and height rules), with its heightfield
|
|
34
|
+
collider. `og.Water` fills the lake at y 1: waves, planar reflection,
|
|
35
|
+
shadows, caustics, a depth fade and foam where it meets the shore and
|
|
36
|
+
the lamplighter's legs.
|
|
37
|
+
- **A character on og.CharacterController** (og-physics): a capsule with a
|
|
38
|
+
slope limit, step height, ground snap and coyote time; the controls are
|
|
39
|
+
relative to the view (WASD or the arrows, the left stick, the touch
|
|
40
|
+
joystick); Shift or a full stick runs; Space, A or Jump jumps; wading
|
|
41
|
+
slows to `Tuning.wade`.
|
|
42
|
+
- **Skeletal animation with blend trees and IK** (og-anim): the hero is
|
|
43
|
+
the strider, its clips retargeted from the humanoid clip library at cook
|
|
44
|
+
time (`assets/models/strider.glb.ogt`); the sentinels are the stout, the
|
|
45
|
+
same library retargeted at run time (`og.anim.retarget`). Each plays an
|
|
46
|
+
`og.AnimationGraph` (`src/anim.ts`): a 1D blend of idle, walk and run by
|
|
47
|
+
speed, and for the hero a cross-fade to an air state. Kindling raises an
|
|
48
|
+
`og.IkChain` (FABRIK, three bones) on the right arm into the bowl; the
|
|
49
|
+
playtest reads it reached within 2 cm.
|
|
50
|
+
- **NPCs on a navmesh with behaviour trees** (og-nav, og-ai): `assets/nav/vale.ogt`
|
|
51
|
+
bakes the terrain above the waterline and the plinths at cook time; each
|
|
52
|
+
sentinel is an `og.NavAgent` thinking with `assets/ai/sentinel-<name>.ogt`
|
|
53
|
+
(patrol its round, alert and chase on sight, grab within reach, search
|
|
54
|
+
where it last saw the hero) and seeing through `og.Perception` (a 120°
|
|
55
|
+
cone, its sight from `Tuning`, the terrain and the plinths occlude).
|
|
56
|
+
- **Particles, decals and the post stack** (og-render): each beacon's fire,
|
|
57
|
+
smoke and a one-shot burst of embers (`assets/fx/*.ogt`), a splash at
|
|
58
|
+
every wading step and landing in the lake; a scorch decal on the knoll
|
|
59
|
+
and a rune on the plinth that glows once lit; bloom, AO, god rays, a
|
|
60
|
+
vignette, the teal-orange LUT and film grain, the sky, height fog and
|
|
61
|
+
`og.DayNight` running from late afternoon to night as the run's clock.
|
|
62
|
+
- **Screens on og.ui with tokens and MSDF text** (og-ui §2–§6, og-taste):
|
|
63
|
+
the engine's fantasy pack as `assets/skins/ember` (Cinzel and Newsreader,
|
|
64
|
+
Noto Sans SC as the fallback, every font an MSDF atlas at cook time); the
|
|
65
|
+
title over an orbit of the vale, the HUD (hearts and beacons top-left,
|
|
66
|
+
the dusk clock and Pause top-right, the kindling prompt and its progress
|
|
67
|
+
at the bottom; on a touch screen a joystick, Jump and Kindle), toasts,
|
|
68
|
+
`og.ui.pauseMenu`, a settings dialog and the summary built from widgets,
|
|
69
|
+
a dissolve between screens (a fade with reduced motion). Spacing comes
|
|
70
|
+
from the tokens' scale; colours are token references.
|
|
71
|
+
- **Feel** (og-feel): a camera punch when a beacon catches; a grab is a hit
|
|
72
|
+
stop, a red flash, a shake and a knock-back; a sentinel's eye burns red
|
|
73
|
+
while it chases, with "!" over it when it sees you.
|
|
74
|
+
- **Sound** (og-audio): a voice per event (pitch-varied steps and splashes,
|
|
75
|
+
the jump, the ignition, the alarm, the grab, the dawn and night
|
|
76
|
+
stingers), the UI's sounds from `og sfx` presets, the vale's loop on the
|
|
77
|
+
music bus ducked under the effects and a little reverb on the effects.
|
|
78
|
+
- **Tune**: every `Tuning` field is tunable (speeds, wading, kindling,
|
|
79
|
+
dusk, the sentinels' pace and sight, the hit stop, the camera).
|
|
80
|
+
- **Languages** (og-i18n): every string is a key of `assets/strings/en.ogt`
|
|
81
|
+
and `zh-CN.ogt`; the Chinese font is Noto Sans SC subset to exactly the
|
|
82
|
+
table's characters.
|
|
83
|
+
- **The platform** (og-platform-sdk): settings through
|
|
84
|
+
`loadSettings`/`saveSettings`; the record (`{runs, wins, best}`) read on
|
|
85
|
+
the first ticks and written at the revision read; one call at a time
|
|
86
|
+
(a newer record waits for the read or write in flight and goes out at
|
|
87
|
+
the revision its answer gives); a write refused as stale (another
|
|
88
|
+
device played meanwhile) is read again, merged (the stored counts plus
|
|
89
|
+
what this device added, the better best time) and written at the new
|
|
90
|
+
revision; a `run.over` telemetry event.
|
|
91
|
+
- **The tap gate**: `og build . --publish` ships behind the default
|
|
92
|
+
`gate: "tap"`, so audio starts on the player's first tap.
|
|
93
|
+
|
|
94
|
+
## Rules
|
|
95
|
+
|
|
96
|
+
- **Moving.** Walk 3 m/s, run 6 m/s, wade at 0.45 of either. The view
|
|
97
|
+
turns with Q and E (the right stick, or on a touch screen a finger
|
|
98
|
+
dragged sideways across the right half, between the clock and Jump)
|
|
99
|
+
and swings slowly behind a walking hero.
|
|
100
|
+
- **Kindling.** Within reach of a dark beacon the prompt shows; holding F
|
|
101
|
+
(X, Kindle) walks the hero to the plinth and reaches into the bowl;
|
|
102
|
+
1.6 s of reaching lights it. Letting go lets the kindling cool at twice
|
|
103
|
+
the rate.
|
|
104
|
+
- **Sentinels.** Each patrols its round at 1.6 m/s, sees 13 m in a 120°
|
|
105
|
+
cone (not through the terrain or the plinths), chases at 4.2 m/s and
|
|
106
|
+
grabs within 1.5 m: a heart, a knock-back and 1.6 s spared. It cannot
|
|
107
|
+
follow into the lake; out of sight it searches for 4 s, then goes back.
|
|
108
|
+
A new run puts each back at the start of its round, on patrol.
|
|
109
|
+
- **The end.** All four lit: dawn will find the vale lit (a win; the best
|
|
110
|
+
time is kept). The hearts gone: caught. 150 s of play (the hour reaching
|
|
111
|
+
19:30): night. 1.5 s later the summary; Again starts a run from nothing,
|
|
112
|
+
Title goes back. Only the record carries over.
|
|
113
|
+
|
|
114
|
+
Everything is deterministic: the clock is the fixed tick, og.ai, og.nav
|
|
115
|
+
and the character controller are deterministic and in snapshots, and
|
|
116
|
+
`tests/replay.og.ts` replays a run (moving, a jump, kindling, a grab) to
|
|
117
|
+
the same hash.
|
|
118
|
+
|
|
119
|
+
## How it feels
|
|
120
|
+
|
|
121
|
+
| Moment | What happens | Where |
|
|
122
|
+
|---|---|---|
|
|
123
|
+
| walking, running | the blend from idle through walk to run by speed, a footstep a stride (pitch-varied) | `Hero` in `src/hero.ts`, `src/anim.ts` |
|
|
124
|
+
| wading | slow, a splash at each stride, foam at the legs | `Hero` |
|
|
125
|
+
| a jump | the air state cross-fades in, a jump sound; a landing in the lake splashes | `Hero` |
|
|
126
|
+
| kindling | the hero walks up and the hand reaches into the bowl (IK), the progress bar fills | `Hero`, `Beacons`, `Ui` |
|
|
127
|
+
| a beacon catches | fire, smoke and a burst of embers, its light swelling in over 0.5 s and flickering, the scorch and the glowing rune, an ignition, a camera punch, a toast (not for the last) | `catchBeacon` in `src/beacons.ts`, `lightBeacon` in `src/world.ts` |
|
|
128
|
+
| seen | "!" over the sentinel, an alarm, its eye burning red, it runs | `alarm` in `src/sentinels.ts` |
|
|
129
|
+
| grabbed | a 5-tick hit stop, a red flash, a shake, the hero thrown back, a heart gone | `grab` in `src/sentinels.ts` |
|
|
130
|
+
| dusk | the sun lowers and the light warms, then cools, the clock's bar empties | `clock` in `src/ui.ts` |
|
|
131
|
+
| the end | the dawn or night stinger, the summary after a beat with its icon popping in | `clock`, `summary` in `src/ui.ts` |
|
|
132
|
+
|
|
133
|
+
## State
|
|
134
|
+
|
|
135
|
+
| Type | Kind | What it holds |
|
|
136
|
+
|---|---|---|
|
|
137
|
+
| `Game` | resource | the phase and ending, the record and its requests, hearts, lit beacons, the run's time and hour, kindling, wading, the counts (jumps, splashes, grabs, alarms), the knock-back, the view's yaw, the HUD's stick and buttons, sound requests, the terrain and navmesh handles |
|
|
138
|
+
| `Tuning` | resource | the knobs below |
|
|
139
|
+
| `Prefs` | resource | the volumes, the language, reduced motion |
|
|
140
|
+
| `Hero` | the hero's capsule | steps, air time |
|
|
141
|
+
| `Beacon` | the four plinths | index, lit, when it caught, the bowl's rim |
|
|
142
|
+
| `Sentinel` | the three sentinels | index, grabs, alarms, speed, alert |
|
|
143
|
+
| `Sfx` | one row per sound | its `Sound.*` bit, its plays |
|
|
144
|
+
|
|
145
|
+
## Systems (in tick order)
|
|
146
|
+
|
|
147
|
+
| System | Job |
|
|
148
|
+
|---|---|
|
|
149
|
+
| `og.systems.cameras` | the camera's punch and shake |
|
|
150
|
+
| `Ui` | the screens, starting and ending runs, the clock and the hour, pausing, the buses, the platform's answers |
|
|
151
|
+
| `Hero` | the controls, the character controller, the graph's parameters, the reach (IK), steps, splashes and jumps |
|
|
152
|
+
| `View` | the title's orbit, the follow camera kept above the ground and the water |
|
|
153
|
+
| `Sentinels` | their sight and pace from `Tuning`, the graph's speed, the feet on the terrain, the eye's light |
|
|
154
|
+
| `Beacons` | which beacon is in reach, kindling, catching, the lights' swell and flicker |
|
|
155
|
+
| `Voices` | plays each requested sound once |
|
|
156
|
+
|
|
157
|
+
og.nav, og.ai (the sentinels' decisions, whose commands `alarm` and `grab`
|
|
158
|
+
run before the next tick), physics and animation run in the engine's own
|
|
159
|
+
stages.
|
|
160
|
+
|
|
161
|
+
## Tunables (`Tuning`)
|
|
162
|
+
|
|
163
|
+
| Field | Default | What it changes |
|
|
164
|
+
|---|---|---|
|
|
165
|
+
| `walkSpeed`, `runSpeed` | 3, 6 m/s | the hero |
|
|
166
|
+
| `wade` | 0.45 | the speed in the lake, as a fraction |
|
|
167
|
+
| `jumpSpeed` | 5.2 m/s | the jump |
|
|
168
|
+
| `kindleSeconds`, `reach` | 1.6 s, 2.4 m | how long a beacon takes, how near the hero must be |
|
|
169
|
+
| `duskSeconds` | 150 s | the run's length before night |
|
|
170
|
+
| `patrolSpeed`, `chaseSpeed`, `sight` | 1.6, 4.2 m/s, 13 m | the sentinels |
|
|
171
|
+
| `hitStop` | 5 ticks | a grab's hit stop |
|
|
172
|
+
| `cameraDistance` | 6.2 m | the follow camera |
|
|
173
|
+
|
|
174
|
+
## What a Maker changes first
|
|
175
|
+
|
|
176
|
+
1. **The vale**: `tools/make-assets.py` (the knolls, the lake, the paths,
|
|
177
|
+
the sentinels' rounds), then `python3 tools/make-assets.py && og cook .`;
|
|
178
|
+
keep `BEACON_AT`, `LAKE` and `START` in `src/world.ts` and the plinths in
|
|
179
|
+
`assets/nav/vale.ogt` in step.
|
|
180
|
+
2. **The pressure**: `duskSeconds`, the sentinels' speeds and sight, their
|
|
181
|
+
minds in `assets/ai/`, `HEARTS` in `src/components.ts`.
|
|
182
|
+
3. **The look**: the post stack, fog and sky in `buildVale`, the water's
|
|
183
|
+
colours, the skin's palette in `assets/skins/ember/skin.ogt`.
|
|
184
|
+
4. **The characters**: another CC0 humanoid in `assets/models/` with the
|
|
185
|
+
clip library retargeted onto it (`src/anim.ts`), the graphs' thresholds.
|
|
186
|
+
5. **Words**: `assets/strings/*.ogt`; a new Chinese string needs the script
|
|
187
|
+
run again to subset the font (with fontTools and the project template's
|
|
188
|
+
Noto Sans SC; without them the script fails naming the characters the
|
|
189
|
+
committed font lacks).
|
|
190
|
+
|
|
191
|
+
## Commands (for scripts and agents)
|
|
192
|
+
|
|
193
|
+
| Action | Does |
|
|
194
|
+
|---|---|
|
|
195
|
+
| `run` | starts a run now, as Set out does |
|
|
196
|
+
| `warp:<beacon>` / `warp:<x>:<z>` | puts the hero where it kindles a beacon (0 to 3), or on the ground at x, z |
|
|
197
|
+
| `light:<beacon>` | the beacon catches now (the fourth wins) |
|
|
198
|
+
| `hearts:<n>` | sets the hearts left (0: caught) |
|
|
199
|
+
| `dusk:<seconds>` | jumps the run's clock (night at `Tuning.duskSeconds`) |
|
|
200
|
+
| `stale_record` | another device writes the record, so this one's next write is refused as stale and merged |
|
|
201
|
+
| `viewport:<desktop\|phone>` | lays the UI out for a phone in portrait (390 × 844 at 3×) |
|
|
202
|
+
| `language:<en\|zh-CN>` | switches the language |
|
|
203
|
+
| `alarm:<sentinel>`, `grab:<sentinel>` | the sentinels' behaviour commands: sentinel 0 to 2 (west, north, east) calls the alarm or grabs (og.ai sends them with the sentinel's entity) |
|
|
204
|
+
| core actions | `touch_move_to:play`, `Pause`, `Jump`, `Kindle`, `Stick`, `Again`, `Menu`; WASD, the arrows, Shift, Space, F, Q, E, Escape; `gamepad:a` … |
|
|
205
|
+
|
|
206
|
+
`facts` (the probe's `state()`) reports the phase, the ending, hearts, lit
|
|
207
|
+
beacons, the time and hour, the near beacon and kindling, wading,
|
|
208
|
+
grounded, speed, jumps, splashes, grabs, alarms, the record and the
|
|
209
|
+
language. The playtests read the same values from the `Game` resource with
|
|
210
|
+
`get:Game`.
|
|
211
|
+
|
|
212
|
+
## Playtests (`og test .`)
|
|
213
|
+
|
|
214
|
+
| File | Proves |
|
|
215
|
+
|---|---|
|
|
216
|
+
| `tests/flow.og.ts` | Set out by tap; walking 3 m/s and running 6 m/s north to the lake, wading at 2.7 m/s with splashes; at a beacon the prompt, F held: the IK chain reaches the bowl (error ≤ 2 cm), the beacon catches after kindleSeconds, the HUD and toast count it |
|
|
217
|
+
| `tests/sentinels.og.ts` | the west sentinel walks its round calm; the hero in its view: the alarm, its eye's light, a chase and a grab that costs a heart |
|
|
218
|
+
| `tests/win.og.ts` | four beacons lit: dawn, the record merged after a stale write (runs, wins, the best time) with a `run.over` event, the summary, then Again from nothing |
|
|
219
|
+
| `tests/lose.og.ts` | caught with no hearts left, Again, night at dusk's end, Title |
|
|
220
|
+
| `tests/hitstop.og.ts` | Escape pressed during a grab's hit-stop still pauses |
|
|
221
|
+
| `tests/restart.og.ts` | a sentinel chasing when the run restarts is back on patrol, its eye calm |
|
|
222
|
+
| `tests/pause.og.ts` | Escape holds the run (time scale 0, the clock stopped, keys move nothing); settings switch to 简体中文 and move the music; Done saves through og.platform; Resume |
|
|
223
|
+
| `tests/phone.og.ts` | 1170 × 2532 (390 × 844 at 3×): the HUD inside the safe area, touch-sized controls, the joystick walks, Jump jumps, Kindle held lights a beacon |
|
|
224
|
+
| `tests/frames.og.ts` | the title, a beacon catching and the dawn summary match `references/<tier>/` (`OG_FX_CAPTURE=1 og test .` records them) |
|
|
225
|
+
| `tests/replay.og.ts` | a run with movement, a jump, kindling and a grab, run twice, ends on one hash |
|
|
226
|
+
|
|
227
|
+
## Assets
|
|
228
|
+
|
|
229
|
+
Nothing here is downloaded. `tools/make-assets.py` regenerates the vale's
|
|
230
|
+
heightmap and control map, the sounds and music, the `og sfx` presets, the
|
|
231
|
+
sentinels' minds and the font subset byte for byte; the characters, the
|
|
232
|
+
clip library, the textures and the beacon's effects are the engine's own
|
|
233
|
+
CC0 assets. `LICENSES.md` lists every file; the skin's are in
|
|
234
|
+
`assets/skins/ember/LICENSES.md`.
|
|
235
|
+
|
|
236
|
+
## Known limits (engine gaps, not design)
|
|
237
|
+
|
|
238
|
+
- `og.IkChain`'s `space: "world"` is the frame of the skeleton entity's
|
|
239
|
+
parent (its og.Transform applies, the parent's does not), so a target
|
|
240
|
+
for a body parented to the capsule is relative to the capsule
|
|
241
|
+
(`src/hero.ts`); the API's doc says only "the skeleton entity's
|
|
242
|
+
og.Transform applies".
|
|
243
|
+
- `og.DayNight` advances on unscaled ticks, so a pause would not hold it;
|
|
244
|
+
the game holds it (speed 0) and sets the hour itself (`setHour` in
|
|
245
|
+
`src/world.ts`).
|
|
246
|
+
- og.ui's `settingsScreen` and `resultsScreen` carried English labels of
|
|
247
|
+
their own when this game was written, so the settings dialog and the
|
|
248
|
+
summary are built from widgets (both now take a field for each of their
|
|
249
|
+
words: og-i18n §2).
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
type behaviour
|
|
2
|
+
version 1
|
|
3
|
+
---
|
|
4
|
+
# The east sentinel (og.ai; generated by tools/make-assets.py, which keeps
|
|
5
|
+
# the route on the terrain). It walks its round of the lake's path; when it
|
|
6
|
+
# sees the hero (og.Perception: within its sight, in its cone, not
|
|
7
|
+
# behind the terrain) it calls the alarm and chases, grabs within reach
|
|
8
|
+
# (the game's `grab` costs a heart and throws the hero back), stands
|
|
9
|
+
# stunned a moment, and searches where it last saw the hero before going
|
|
10
|
+
# back to its round. The hero wading in the lake is out of its reach: the
|
|
11
|
+
# navmesh stops at the shore.
|
|
12
|
+
name "sentinel-east"
|
|
13
|
+
route post {
|
|
14
|
+
point 27 3.44 -22
|
|
15
|
+
point 31 3.15 -6
|
|
16
|
+
point 27 3.04 12
|
|
17
|
+
}
|
|
18
|
+
machine {
|
|
19
|
+
initial patrol
|
|
20
|
+
state patrol {
|
|
21
|
+
patrol post {
|
|
22
|
+
wait 1.5
|
|
23
|
+
speed Tuning.patrolSpeed
|
|
24
|
+
}
|
|
25
|
+
to alert {
|
|
26
|
+
check sees
|
|
27
|
+
check Game.phase is 1
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
state alert {
|
|
31
|
+
enter {
|
|
32
|
+
command alarm
|
|
33
|
+
}
|
|
34
|
+
chase {
|
|
35
|
+
speed Tuning.chaseSpeed
|
|
36
|
+
reach 1.1
|
|
37
|
+
}
|
|
38
|
+
to grab {
|
|
39
|
+
check targetDistance below 1.5
|
|
40
|
+
}
|
|
41
|
+
to search {
|
|
42
|
+
check sees is false
|
|
43
|
+
}
|
|
44
|
+
to patrol {
|
|
45
|
+
check Game.phase not 1
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
state grab {
|
|
49
|
+
enter {
|
|
50
|
+
command grab
|
|
51
|
+
}
|
|
52
|
+
stop
|
|
53
|
+
to search {
|
|
54
|
+
after 1.6
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
state search {
|
|
58
|
+
move_to lastSeen {
|
|
59
|
+
speed Tuning.patrolSpeed
|
|
60
|
+
}
|
|
61
|
+
to alert {
|
|
62
|
+
check sees
|
|
63
|
+
check Game.phase is 1
|
|
64
|
+
}
|
|
65
|
+
to patrol {
|
|
66
|
+
after 4
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|