@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,7 @@
|
|
|
1
|
+
# Asset licences
|
|
2
|
+
|
|
3
|
+
| File | Licence | Origin |
|
|
4
|
+
|---|---|---|
|
|
5
|
+
| `assets/sprites/*` | CC0 1.0 | self-made: the gem flipbook, the panel, the backdrop, the frame and the checker tileset and map, drawn from vector shapes by `tools/make-assets.py` (standard library only, deterministic) |
|
|
6
|
+
| `assets/audio/*.wav` | CC0 1.0 | self-made: synthesised tones and noise, same script |
|
|
7
|
+
| `assets/fonts/ui.ttf` | SIL Open Font License 1.1 (`assets/fonts/OFL.txt`) | Noto Sans SC Regular, subset to Latin-1 and the HUD's characters by the same script from the project template's `assets/fonts/NotoSansSC-Regular-subset.ttf` |
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
# Tile Swap — the match3 archetype
|
|
2
|
+
|
|
3
|
+
Swap two neighbouring gems to make a line of three or more of one colour.
|
|
4
|
+
Lines clear, the gems above fall, new gems drop in, and any line the fall
|
|
5
|
+
makes clears again as a cascade worth more. Reach the target score before
|
|
6
|
+
the moves run out.
|
|
7
|
+
|
|
8
|
+
三消:交换相邻的两块方块,连成三个或更多同色即可消除;上方方块落下、新方块补入,下落时连成的线会再次消除(连锁得分更高)。在步数用完前达到目标分数即胜利。
|
|
9
|
+
|
|
10
|
+
A complete Origin Engine project: `og run .`, `og test .`, `og build .`.
|
|
11
|
+
It replaces the platform's Godot Discover match3 (Lantern Swap) and keeps
|
|
12
|
+
its feel (one thumb, a swap that makes nothing is free, cascades as the
|
|
13
|
+
reward, a move budget instead of a clock), not its code, art or lanterns.
|
|
14
|
+
|
|
15
|
+
It is also the engine's 2D and game-feel showcase for a puzzle game:
|
|
16
|
+
|
|
17
|
+
- **Sprites and flipbooks.** Every gem is an `og.Sprite` playing an
|
|
18
|
+
`og.Flipbook` clip from one sheet (`assets/sprites/gems.ogt`): an idle
|
|
19
|
+
loop that holds 2.4 s and then glints, each gem seeked to its own moment,
|
|
20
|
+
and a `once` burst when it clears.
|
|
21
|
+
- **Nine-slice and a tilemap.** The board's backing is a nine-sliced
|
|
22
|
+
`og.Sprite` panel; the checker under the gems is a hand-written 7 × 7
|
|
23
|
+
tilemap (`assets/sprites/board.ogt` over the `cells.ogt` tileset).
|
|
24
|
+
- **Tweens drive the phases.** A swap slides with `cubicInOut` (a refused
|
|
25
|
+
one goes there and back as one yoyo), cleared gems squash to nothing and
|
|
26
|
+
fade, gems fall with `bounceOut`, column by column, and squash as they
|
|
27
|
+
land; new rounds pop in with `backOut`. Each phase waits for its tween
|
|
28
|
+
group's `og.TweenCompleted` (by tag), not for a tick count.
|
|
29
|
+
- **Feel.** Every cleared group's score floats up from it
|
|
30
|
+
(`og.render.floatingText`, a gold crit on a cascade), the gems flash
|
|
31
|
+
before they burst, four or more in a group punch the camera in, a cascade
|
|
32
|
+
shakes it by its depth, a third cascade holds time for 3 ticks
|
|
33
|
+
(`og.time.hitStop`), and the selection frame breathes on a looping tween.
|
|
34
|
+
|
|
35
|
+
```sh
|
|
36
|
+
og run . --headless --commands "0.5:touch_move:640,700;0.5:touch_start;0.55:touch_end;1:screenshot:board.png;1.1:quit"
|
|
37
|
+
og test .
|
|
38
|
+
og build .
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## What it demonstrates, and the skills it exercises
|
|
42
|
+
|
|
43
|
+
A grid puzzle made of tweens: swaps, falls and refills as `og.tween` moves
|
|
44
|
+
and sequences, squash on landing, a flash and floating score on a clear,
|
|
45
|
+
hit stop, shake and punch growing with a cascade (og-feel §3–§7), taps and
|
|
46
|
+
drags read on the tick they land (og-feel §1; og-game §7), a sound for every
|
|
47
|
+
press, swap, clear, cascade, win and loss (og-audio §1), the board as data
|
|
48
|
+
with a deterministic deal from og.Rng (og-core §2), and playtests that drive
|
|
49
|
+
a known board through commands (og-build §1, §3). `og polish .`
|
|
50
|
+
(2026-10-19): feel 100 (taste n/a: the HUD is screen-space text).
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
## Rules
|
|
54
|
+
|
|
55
|
+
- **Title.** The first tap (or Space/Enter) deals a round: `Tuning.moves`
|
|
56
|
+
moves, score 0. That tap does not also select.
|
|
57
|
+
- **Swapping.** Tap a tile, then a neighbour; or press a tile and drag at
|
|
58
|
+
least 0.45 of a cell towards a neighbour. Tapping the selected tile again
|
|
59
|
+
deselects it; tapping a tile that is not a neighbour selects it instead.
|
|
60
|
+
- **Lines.** After a swap, every horizontal or vertical run of three or more
|
|
61
|
+
of one colour is marked. No line: the tiles swap back and no move is
|
|
62
|
+
spent. Lines: one move is spent and the marked tiles fold away over
|
|
63
|
+
`Tuning.clearTicks`.
|
|
64
|
+
- **Score.** Each cleared tile scores `Tuning.tileScore × chain`, where the
|
|
65
|
+
chain is 1 for the swap's own lines and rises by one for every cascade.
|
|
66
|
+
- **Fall and refill.** Survivors fall to the bottom of their columns at
|
|
67
|
+
`Tuning.fallSpeed` cells/s; the cleared tiles come back above the board
|
|
68
|
+
with colours from the dice and fall in. Lines the fall makes clear again.
|
|
69
|
+
- **End.** When the board settles: score ≥ `Tuning.target` wins; no moves
|
|
70
|
+
left loses; a board where no swap makes a line is dealt again (colours
|
|
71
|
+
only, `Match.shuffles` counts it). The end card holds 40 ticks, then a tap
|
|
72
|
+
deals the next round.
|
|
73
|
+
|
|
74
|
+
Deals never contain a ready line and always contain a move. Every colour
|
|
75
|
+
draw comes from `og.Rng`, so a seed (`project.ogt`, `og run --seed`) gives
|
|
76
|
+
the same deals, refills and reshuffles on every host.
|
|
77
|
+
|
|
78
|
+
## The world
|
|
79
|
+
|
|
80
|
+
| Row | Count | Name | Drawn as |
|
|
81
|
+
|---|---|---|---|
|
|
82
|
+
| backdrop | 1 | `backdrop` | a soft lift of light behind the board (layer −30); around it the camera's background is the brand ink `#14161b` |
|
|
83
|
+
| board | 1 | `board` (from `assets/scenes/main.ogt`) | the nine-sliced panel (layer −20) |
|
|
84
|
+
| tiles | 49 | `tile-0` … `tile-48` (pool rows: a tile's cell is `Piece.col/row`, not its name) | gems: `og.Sprite` + `og.Flipbook` on the gem sheet (layer 0) |
|
|
85
|
+
| selection frame | 1 | `cursor` | a rounded frame (layer 1) |
|
|
86
|
+
|
|
87
|
+
Those 52 rows have `og.Transform`, `og.Sprite`, `og.Flipbook` (sheet 0, so
|
|
88
|
+
unused, except on the gems) and:
|
|
89
|
+
|
|
90
|
+
| Component | On | What it holds |
|
|
91
|
+
|---|---|---|
|
|
92
|
+
| `Piece` | every row | `kind`, a tile's `col`/`row` (0,0 is the bottom left), `colour` (−1 empty), `marked` |
|
|
93
|
+
| `Match` | every row; **the board's is the authority** | `phase` (title, idle, swap, swapBack, clear, fall, won, lost), `phaseTicks`, `score`, `best`, `movesLeft`, `chain`, `maxChain`, `cleared`, `lastCleared`, `rounds`, `shuffles`, `selected`, `swapA`/`swapB`, the drag (`dragFrom`, `pressX/Y`), the view (`viewHeight`, `viewCentreY`), the pointer mapping Pick works out each tick (`pxPerM`, `screenX0/Y0`), `wait` (the tag of the tween group the phase waits for) and `font` (for the floating scores) |
|
|
94
|
+
| `Tuning` | every row; **the board's is the authority** | the tunables below |
|
|
95
|
+
| `Hud` | the board only | the font handle and the view's top |
|
|
96
|
+
|
|
97
|
+
One more entity, `cells`, carries only the `og.Tilemap` of the checker
|
|
98
|
+
(layer −10), placed by its top-left corner at the board's; no system sees
|
|
99
|
+
it.
|
|
100
|
+
|
|
101
|
+
`Match` and `Tuning` ride on every row for the same reason as in the
|
|
102
|
+
runner: a system sees one query and cannot reach another entity or a game
|
|
103
|
+
resource yet, and the swap, clear and fall need the round's state together
|
|
104
|
+
with the tiles.
|
|
105
|
+
|
|
106
|
+
`src/board.ts` is pure logic over a colour grid (lines, "is there a move",
|
|
107
|
+
the deal, the board text format); `src/layout.ts` is the geometry. Neither
|
|
108
|
+
touches the world, so systems, commands and playtests share them.
|
|
109
|
+
|
|
110
|
+
## Systems (in tick order)
|
|
111
|
+
|
|
112
|
+
| System | Reads | Writes | Job |
|
|
113
|
+
|---|---|---|---|
|
|
114
|
+
| `Flow` | `og.Input`, `Tuning` | `og.Rng`, `Match`, `Piece`, `og.Transform` | the title and end cards; a tap deals a round, the gems popping in on staggered tweens |
|
|
115
|
+
| `Pick` | `og.Input`, `Piece` | `Match` | pointer → cell; tap-tap and drag start a swap; a `swap` command's request |
|
|
116
|
+
| `Resolve` | `Tuning`, `og.TweenCompleted` | `og.Rng`, `Match`, `Piece`, `og.Transform` | starts the swap (or the refused yoyo), clear and fall tween groups and waits for each; marks, scores, collapses and refills; floating scores, flash, punch, shake and hit stop; cascade, win, lose, reshuffle |
|
|
117
|
+
| `Animate` | `Match`, `Piece`, `Tuning` | `og.Sprite`, `og.Flipbook`, `og.Transform` | each gem's clip (idle or burst), visibility and fade-in at the top edge, the selected gem's pulse, the frame's cell; gems hidden on the title and dimmed under the end cards |
|
|
118
|
+
| `Hud` | `Match`, `Hud`, `Tuning` | — | score, moves, target, best; cascade callout; title, win and lose cards |
|
|
119
|
+
|
|
120
|
+
## Tunables (`Tuning`, on the board)
|
|
121
|
+
|
|
122
|
+
| Field | Default | Range | Unit | What it changes |
|
|
123
|
+
|---|---|---|---|---|
|
|
124
|
+
| `moves` | 20 | 1–60 | moves | the budget of a round |
|
|
125
|
+
| `target` | 1500 | 10–10000 | points | the score that wins |
|
|
126
|
+
| `colours` | 5 | 3–6 | colours | fewer colours, more lines and cascades |
|
|
127
|
+
| `tileScore` | 10 | 1–100 | points | per cleared tile, times the chain |
|
|
128
|
+
| `swapTicks` | 8 | 1–30 | ticks | the swap tween's length (a refused swap takes it twice) |
|
|
129
|
+
| `clearTicks` | 12 | 1–40 | ticks | the clear tween's length (squash and fade) |
|
|
130
|
+
| `fallSpeed` | 14 | 2–60 | cells/s | a fall tween lasts 0.12 s plus its drop at this speed |
|
|
131
|
+
|
|
132
|
+
Written in `assets/scenes/main.ogt` (the board's `Tuning` block), live with
|
|
133
|
+
`set:board.Tuning.<field>=<value>` or Tune.
|
|
134
|
+
|
|
135
|
+
## What a Maker changes first
|
|
136
|
+
|
|
137
|
+
1. **Difficulty**: `moves`, `target` and `colours` in the scene's `Tuning`.
|
|
138
|
+
2. **Scoring**: the score line in `Resolve`'s clear step (a bonus for lines
|
|
139
|
+
of four or five, for example).
|
|
140
|
+
3. **The opening**: deal an authored first board with the `deal` command's
|
|
141
|
+
text format from `start`, so the first move teaches.
|
|
142
|
+
4. **Look**: the gem cuts and colours, the glint and the burst frames in
|
|
143
|
+
`tools/make-assets.py` (six cuts, so colour is never the only cue), the
|
|
144
|
+
idle hold in the sheet it writes, then
|
|
145
|
+
`python3 tools/make-assets.py && og cook .`.
|
|
146
|
+
5. **Feel**: the eases, durations and staggers in `Resolve` (`startClear`,
|
|
147
|
+
`collapse`), the punch, shake and hit-stop thresholds in `startClear`.
|
|
148
|
+
6. **Size**: `SIZE` in `src/layout.ts` (the pools follow; regenerate the
|
|
149
|
+
tilemap in `tools/make-assets.py`'s `board_map`).
|
|
150
|
+
|
|
151
|
+
## Commands (for scripts and agents)
|
|
152
|
+
|
|
153
|
+
| Action | Does |
|
|
154
|
+
|---|---|
|
|
155
|
+
| `deal:<rows>` | lays out the board: 7 lines of 7 colour digits joined by `/`, the top row first; needs an idle board |
|
|
156
|
+
| `swap:<col>,<row>:<col>,<row>` | swaps two neighbouring cells on the next tick, as two taps would |
|
|
157
|
+
| `viewport:<desktop\|2x>` | reports the play surface as 640×360 CSS px at 2× (a high-DPR screen; the render target stays 1280×720), or the host's again |
|
|
158
|
+
|
|
159
|
+
`facts` reports `phase`, `score`, `movesLeft`, `cleared`, `maxChain`,
|
|
160
|
+
`best`, `rounds` and the pointer mapping. A cell's CSS pixel is
|
|
161
|
+
`(x0 + x·pxPerM, y0 − y·pxPerM)` with `(x, y)` from `cellCentre` in
|
|
162
|
+
`src/layout.ts`; at 1280×720 that is 60 px per metre around (640, 390).
|
|
163
|
+
|
|
164
|
+
## Playtests (`og test .`)
|
|
165
|
+
|
|
166
|
+
| File | Proves |
|
|
167
|
+
|---|---|
|
|
168
|
+
| `tests/swap.og.ts` | on an authored board, real taps: a swap that makes nothing goes back for free; the swap that makes a line clears it, spends a move, scores, and the fall cascades (chain 2, both lines scored); every system matches its rows |
|
|
169
|
+
| `tests/hidpi.og.ts` | on a 2× surface (640×360 CSS px over the 1280×720 target) the pointer mapping is in CSS pixels and a tap lands on its cell |
|
|
170
|
+
| `tests/drag.og.ts` | a drag shorter than half a cell does nothing; past it, the swap happens and clears |
|
|
171
|
+
| `tests/endings.og.ts` | target 30: the first line wins; one move and an unreachable target: that move loses; a tap after the card deals the next round with the tuned moves; best kept |
|
|
172
|
+
| `tests/frames.og.ts` | at 1280×720 the dealt board, the swap's line mid-clear (burst, squash, `+30`) and the cascade mid-clear (gold crit `+60`, shake) match `references/<tier>/` (og-tests' tolerance, `tests/frames.ts`); away from the board the frame is the brand ink |
|
|
173
|
+
| `tests/replay.og.ts` | `runs: 2`: a refused swap and a cascading swap, stopped mid-fall, end on the same world hash in two fresh processes |
|
|
174
|
+
|
|
175
|
+
Each one fails when its behaviour is broken (checked by charging refused
|
|
176
|
+
swaps, removing cascades, dropping the drag threshold, shrinking the gems
|
|
177
|
+
for the frames and a wall-clock fall delay for the replay). Record a tier's
|
|
178
|
+
reference frames with `OG_FX_CAPTURE=1 og test .` (`references/metal/` is
|
|
179
|
+
recorded; other tiers compare with it until they have their own).
|
|
180
|
+
|
|
181
|
+
## Assets
|
|
182
|
+
|
|
183
|
+
`python3 tools/make-assets.py` writes them all, byte for byte
|
|
184
|
+
(`LICENSES.md`): `assets/sprites/gems.png` + `gems.ogt` (six rows of eight
|
|
185
|
+
80 px frames: idle, three glint frames, four burst frames; clip `2c` is
|
|
186
|
+
colour `c`'s idle loop, `2c + 1` its burst), `panel.png` (96 px, 32 px
|
|
187
|
+
nine-slice insets), `backdrop.png`, `ring.png`, `cells.png` +
|
|
188
|
+
`cells.ogt` + `board.ogt` (the tileset and the map, `kind pixel`), the
|
|
189
|
+
sounds and the font subset. Then `og cook .`.
|
|
190
|
+
|
|
191
|
+
The sounds play through one `og.AudioSource` voice each: Pick (a
|
|
192
|
+
selection) and Resolve (a swap, a refused swap, a clear, a cascade, the win
|
|
193
|
+
and the loss) set bits of the `Sounds` resource and Voices plays each once
|
|
194
|
+
(`og polish` found the archetype silent; tests/sounds.og.ts holds it).
|
|
195
|
+
|
|
196
|
+
## Known limits (engine gaps, not design)
|
|
197
|
+
|
|
198
|
+
- Systems cannot read other entities or the camera (a game resource they
|
|
199
|
+
declare, `Sounds`, they can), so
|
|
200
|
+
`Match` and `Tuning` ride on every row, and `Pick` maps the pointer from
|
|
201
|
+
the view it set in `start` over `og.ui.viewport` (the play surface in
|
|
202
|
+
CSS pixels, as the pointer is).
|
|
203
|
+
- The camera is set once in `start`; on the web the renderer is not
|
|
204
|
+
attached then, so the view assumes 16:9 and a portrait phone clips the
|
|
205
|
+
board's sides.
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
Copyright 2014-2021 Adobe (http://www.adobe.com/), with Reserved Font Name 'Source'
|
|
2
|
+
|
|
3
|
+
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
|
4
|
+
This license is copied below, and is also available with a FAQ at:
|
|
5
|
+
https://scripts.sil.org/OFL
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
-----------------------------------------------------------
|
|
9
|
+
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
|
10
|
+
-----------------------------------------------------------
|
|
11
|
+
|
|
12
|
+
PREAMBLE
|
|
13
|
+
The goals of the Open Font License (OFL) are to stimulate worldwide
|
|
14
|
+
development of collaborative font projects, to support the font creation
|
|
15
|
+
efforts of academic and linguistic communities, and to provide a free and
|
|
16
|
+
open framework in which fonts may be shared and improved in partnership
|
|
17
|
+
with others.
|
|
18
|
+
|
|
19
|
+
The OFL allows the licensed fonts to be used, studied, modified and
|
|
20
|
+
redistributed freely as long as they are not sold by themselves. The
|
|
21
|
+
fonts, including any derivative works, can be bundled, embedded,
|
|
22
|
+
redistributed and/or sold with any software provided that any reserved
|
|
23
|
+
names are not used by derivative works. The fonts and derivatives,
|
|
24
|
+
however, cannot be released under any other type of license. The
|
|
25
|
+
requirement for fonts to remain under this license does not apply
|
|
26
|
+
to any document created using the fonts or their derivatives.
|
|
27
|
+
|
|
28
|
+
DEFINITIONS
|
|
29
|
+
"Font Software" refers to the set of files released by the Copyright
|
|
30
|
+
Holder(s) under this license and clearly marked as such. This may
|
|
31
|
+
include source files, build scripts and documentation.
|
|
32
|
+
|
|
33
|
+
"Reserved Font Name" refers to any names specified as such after the
|
|
34
|
+
copyright statement(s).
|
|
35
|
+
|
|
36
|
+
"Original Version" refers to the collection of Font Software components as
|
|
37
|
+
distributed by the Copyright Holder(s).
|
|
38
|
+
|
|
39
|
+
"Modified Version" refers to any derivative made by adding to, deleting,
|
|
40
|
+
or substituting -- in part or in whole -- any of the components of the
|
|
41
|
+
Original Version, by changing formats or by porting the Font Software to a
|
|
42
|
+
new environment.
|
|
43
|
+
|
|
44
|
+
"Author" refers to any designer, engineer, programmer, technical
|
|
45
|
+
writer or other person who contributed to the Font Software.
|
|
46
|
+
|
|
47
|
+
PERMISSION & CONDITIONS
|
|
48
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
49
|
+
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
|
50
|
+
redistribute, and sell modified and unmodified copies of the Font
|
|
51
|
+
Software, subject to the following conditions:
|
|
52
|
+
|
|
53
|
+
1) Neither the Font Software nor any of its individual components,
|
|
54
|
+
in Original or Modified Versions, may be sold by itself.
|
|
55
|
+
|
|
56
|
+
2) Original or Modified Versions of the Font Software may be bundled,
|
|
57
|
+
redistributed and/or sold with any software, provided that each copy
|
|
58
|
+
contains the above copyright notice and this license. These can be
|
|
59
|
+
included either as stand-alone text files, human-readable headers or
|
|
60
|
+
in the appropriate machine-readable metadata fields within text or
|
|
61
|
+
binary files as long as those fields can be easily viewed by the user.
|
|
62
|
+
|
|
63
|
+
3) No Modified Version of the Font Software may use the Reserved Font
|
|
64
|
+
Name(s) unless explicit written permission is granted by the corresponding
|
|
65
|
+
Copyright Holder. This restriction only applies to the primary font name as
|
|
66
|
+
presented to the users.
|
|
67
|
+
|
|
68
|
+
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
|
69
|
+
Software shall not be used to promote, endorse or advertise any
|
|
70
|
+
Modified Version, except to acknowledge the contribution(s) of the
|
|
71
|
+
Copyright Holder(s) and the Author(s) or with their explicit written
|
|
72
|
+
permission.
|
|
73
|
+
|
|
74
|
+
5) The Font Software, modified or unmodified, in part or in whole,
|
|
75
|
+
must be distributed entirely under this license, and must not be
|
|
76
|
+
distributed under any other license. The requirement for fonts to
|
|
77
|
+
remain under this license does not apply to any document created
|
|
78
|
+
using the Font Software.
|
|
79
|
+
|
|
80
|
+
TERMINATION
|
|
81
|
+
This license becomes null and void if any of the above conditions are
|
|
82
|
+
not met.
|
|
83
|
+
|
|
84
|
+
DISCLAIMER
|
|
85
|
+
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
86
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
|
87
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
|
88
|
+
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
|
89
|
+
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
90
|
+
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
|
91
|
+
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
92
|
+
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
|
93
|
+
OTHER DEALINGS IN THE FONT SOFTWARE.
|
|
Binary file
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
type import
|
|
2
|
+
version 1
|
|
3
|
+
---
|
|
4
|
+
# Written by tools/make-assets.py: the atlas holds Latin-1 and the HUD's own
|
|
5
|
+
# CJK characters (CHARS there); add a character to CHARS before showing it.
|
|
6
|
+
font {
|
|
7
|
+
charset latin
|
|
8
|
+
chars "三消开始游戏点击或拖动交换相邻方块连成同色分数步数目标胜利失败再来一次剩余最高"
|
|
9
|
+
em_px 48
|
|
10
|
+
px_range 6
|
|
11
|
+
}
|