@origingame/create-game 0.0.0-stage → 0.1.0

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.
Files changed (581) hide show
  1. package/README.md +57 -2
  2. package/archetypes/README.md +99 -0
  3. package/archetypes/idle/.origin/setup +14 -0
  4. package/archetypes/idle/LICENSES.md +12 -0
  5. package/archetypes/idle/README.md +234 -0
  6. package/archetypes/idle/assets/audio/buy.wav +0 -0
  7. package/archetypes/idle/assets/audio/milestone.wav +0 -0
  8. package/archetypes/idle/assets/audio/nova.wav +0 -0
  9. package/archetypes/idle/assets/audio/orbit.wav +0 -0
  10. package/archetypes/idle/assets/audio/tap.wav +0 -0
  11. package/archetypes/idle/assets/audio/ui-close.ogt +9 -0
  12. package/archetypes/idle/assets/audio/ui-error.ogt +9 -0
  13. package/archetypes/idle/assets/audio/ui-open.ogt +9 -0
  14. package/archetypes/idle/assets/audio/ui-press.ogt +9 -0
  15. package/archetypes/idle/assets/audio/ui-success.ogt +9 -0
  16. package/archetypes/idle/assets/fonts/NotoSansSC-subset.ttf +0 -0
  17. package/archetypes/idle/assets/fonts/NotoSansSC-subset.ttf.ogt +10 -0
  18. package/archetypes/idle/assets/fonts/OFL.txt +93 -0
  19. package/archetypes/idle/assets/fx/drift.ogt +21 -0
  20. package/archetypes/idle/assets/fx/milestone.ogt +21 -0
  21. package/archetypes/idle/assets/fx/nova.ogt +22 -0
  22. package/archetypes/idle/assets/fx/stars.ogt +20 -0
  23. package/archetypes/idle/assets/fx/tap.ogt +23 -0
  24. package/archetypes/idle/assets/looks/idle.ogt +17 -0
  25. package/archetypes/idle/assets/skins/sparkorb/ChakraPetch-BoldItalic.ttf +0 -0
  26. package/archetypes/idle/assets/skins/sparkorb/ChakraPetch-BoldItalic.ttf.ogt +9 -0
  27. package/archetypes/idle/assets/skins/sparkorb/LICENSES.md +19 -0
  28. package/archetypes/idle/assets/skins/sparkorb/OFL.txt +95 -0
  29. package/archetypes/idle/assets/skins/sparkorb/Orbitron-Medium.ttf +0 -0
  30. package/archetypes/idle/assets/skins/sparkorb/Orbitron-Medium.ttf.ogt +9 -0
  31. package/archetypes/idle/assets/skins/sparkorb/Rajdhani-Bold.ttf +0 -0
  32. package/archetypes/idle/assets/skins/sparkorb/Rajdhani-Bold.ttf.ogt +9 -0
  33. package/archetypes/idle/assets/skins/sparkorb/atlas.png +0 -0
  34. package/archetypes/idle/assets/skins/sparkorb/atlas.png.ogt +7 -0
  35. package/archetypes/idle/assets/skins/sparkorb/icons.png +0 -0
  36. package/archetypes/idle/assets/skins/sparkorb/icons.png.ogt +7 -0
  37. package/archetypes/idle/assets/skins/sparkorb/skin.ogt +113 -0
  38. package/archetypes/idle/assets/sprites/glow.png +0 -0
  39. package/archetypes/idle/assets/sprites/glow.png.ogt +8 -0
  40. package/archetypes/idle/assets/sprites/mote-crystal.png +0 -0
  41. package/archetypes/idle/assets/sprites/mote-crystal.png.ogt +7 -0
  42. package/archetypes/idle/assets/sprites/mote-ember.png +0 -0
  43. package/archetypes/idle/assets/sprites/mote-ember.png.ogt +7 -0
  44. package/archetypes/idle/assets/sprites/mote-star.png +0 -0
  45. package/archetypes/idle/assets/sprites/mote-star.png.ogt +7 -0
  46. package/archetypes/idle/assets/sprites/mote-storm.png +0 -0
  47. package/archetypes/idle/assets/sprites/mote-storm.png.ogt +7 -0
  48. package/archetypes/idle/assets/sprites/orb.png +0 -0
  49. package/archetypes/idle/assets/sprites/orb.png.ogt +7 -0
  50. package/archetypes/idle/assets/sprites/spark.png +0 -0
  51. package/archetypes/idle/assets/sprites/spark.png.ogt +7 -0
  52. package/archetypes/idle/assets/strings/en.ogt +62 -0
  53. package/archetypes/idle/assets/strings/zh-CN.ogt +62 -0
  54. package/archetypes/idle/gitattributes +22 -0
  55. package/archetypes/idle/host.d.ts +46 -0
  56. package/archetypes/idle/package.json +18 -0
  57. package/archetypes/idle/project.ogt +14 -0
  58. package/archetypes/idle/references/metal/card.png +0 -0
  59. package/archetypes/idle/references/metal/orbit.png +0 -0
  60. package/archetypes/idle/references/metal/title.png +0 -0
  61. package/archetypes/idle/src/components.ts +139 -0
  62. package/archetypes/idle/src/main.ts +247 -0
  63. package/archetypes/idle/src/numbers.ts +126 -0
  64. package/archetypes/idle/src/systems.ts +340 -0
  65. package/archetypes/idle/src/ui.ts +412 -0
  66. package/archetypes/idle/tests/away.og.ts +42 -0
  67. package/archetypes/idle/tests/flow.og.ts +57 -0
  68. package/archetypes/idle/tests/frames.og.ts +33 -0
  69. package/archetypes/idle/tests/frames.ts +134 -0
  70. package/archetypes/idle/tests/lib.ts +74 -0
  71. package/archetypes/idle/tests/milestone.og.ts +32 -0
  72. package/archetypes/idle/tests/nova.og.ts +52 -0
  73. package/archetypes/idle/tests/offline.og.ts +60 -0
  74. package/archetypes/idle/tests/pad.og.ts +55 -0
  75. package/archetypes/idle/tests/pause.og.ts +68 -0
  76. package/archetypes/idle/tests/phone.og.ts +50 -0
  77. package/archetypes/idle/tests/replay.og.ts +28 -0
  78. package/archetypes/idle/tools/make-assets.py +448 -0
  79. package/archetypes/idle/tools/oglite.py +285 -0
  80. package/archetypes/idle/tsconfig.json +17 -0
  81. package/archetypes/match3/.origin/setup +14 -0
  82. package/archetypes/match3/LICENSES.md +7 -0
  83. package/archetypes/match3/README.md +205 -0
  84. package/archetypes/match3/assets/audio/cascade.wav +0 -0
  85. package/archetypes/match3/assets/audio/clear.wav +0 -0
  86. package/archetypes/match3/assets/audio/lost.wav +0 -0
  87. package/archetypes/match3/assets/audio/refused.wav +0 -0
  88. package/archetypes/match3/assets/audio/select.wav +0 -0
  89. package/archetypes/match3/assets/audio/swap.wav +0 -0
  90. package/archetypes/match3/assets/audio/won.wav +0 -0
  91. package/archetypes/match3/assets/fonts/OFL.txt +93 -0
  92. package/archetypes/match3/assets/fonts/ui.ttf +0 -0
  93. package/archetypes/match3/assets/fonts/ui.ttf.ogt +11 -0
  94. package/archetypes/match3/assets/scenes/main.ogt +24 -0
  95. package/archetypes/match3/assets/sprites/backdrop.png +0 -0
  96. package/archetypes/match3/assets/sprites/board.ogt +21 -0
  97. package/archetypes/match3/assets/sprites/cells.ogt +7 -0
  98. package/archetypes/match3/assets/sprites/cells.png +0 -0
  99. package/archetypes/match3/assets/sprites/cells.png.ogt +7 -0
  100. package/archetypes/match3/assets/sprites/gems.ogt +75 -0
  101. package/archetypes/match3/assets/sprites/gems.png +0 -0
  102. package/archetypes/match3/assets/sprites/panel.png +0 -0
  103. package/archetypes/match3/assets/sprites/ring.png +0 -0
  104. package/archetypes/match3/gitattributes +22 -0
  105. package/archetypes/match3/host.d.ts +46 -0
  106. package/archetypes/match3/package.json +18 -0
  107. package/archetypes/match3/project.ogt +18 -0
  108. package/archetypes/match3/references/metal/cascade.png +0 -0
  109. package/archetypes/match3/references/metal/clearing.png +0 -0
  110. package/archetypes/match3/references/metal/dealt.png +0 -0
  111. package/archetypes/match3/src/art.ts +54 -0
  112. package/archetypes/match3/src/board.ts +112 -0
  113. package/archetypes/match3/src/components.ts +95 -0
  114. package/archetypes/match3/src/layout.ts +25 -0
  115. package/archetypes/match3/src/main.ts +199 -0
  116. package/archetypes/match3/src/systems.ts +631 -0
  117. package/archetypes/match3/tests/drag.og.ts +31 -0
  118. package/archetypes/match3/tests/endings.og.ts +40 -0
  119. package/archetypes/match3/tests/frames.og.ts +49 -0
  120. package/archetypes/match3/tests/frames.ts +134 -0
  121. package/archetypes/match3/tests/hidpi.og.ts +41 -0
  122. package/archetypes/match3/tests/lib.ts +64 -0
  123. package/archetypes/match3/tests/replay.og.ts +28 -0
  124. package/archetypes/match3/tests/sounds.og.ts +50 -0
  125. package/archetypes/match3/tests/swap.og.ts +67 -0
  126. package/archetypes/match3/tools/make-assets.py +404 -0
  127. package/archetypes/match3/tools/oglite.py +285 -0
  128. package/archetypes/match3/tsconfig.json +17 -0
  129. package/archetypes/rhythm/.origin/setup +14 -0
  130. package/archetypes/rhythm/LICENSES.md +13 -0
  131. package/archetypes/rhythm/README.md +235 -0
  132. package/archetypes/rhythm/assets/audio/bass0.wav +0 -0
  133. package/archetypes/rhythm/assets/audio/bass1.wav +0 -0
  134. package/archetypes/rhythm/assets/audio/bass2.wav +0 -0
  135. package/archetypes/rhythm/assets/audio/bass3.wav +0 -0
  136. package/archetypes/rhythm/assets/audio/chords0.wav +0 -0
  137. package/archetypes/rhythm/assets/audio/chords1.wav +0 -0
  138. package/archetypes/rhythm/assets/audio/chords2.wav +0 -0
  139. package/archetypes/rhythm/assets/audio/chords3.wav +0 -0
  140. package/archetypes/rhythm/assets/audio/clear.wav +0 -0
  141. package/archetypes/rhythm/assets/audio/click.wav +0 -0
  142. package/archetypes/rhythm/assets/audio/drums.wav +0 -0
  143. package/archetypes/rhythm/assets/audio/fail.wav +0 -0
  144. package/archetypes/rhythm/assets/audio/leadA.wav +0 -0
  145. package/archetypes/rhythm/assets/audio/leadB.wav +0 -0
  146. package/archetypes/rhythm/assets/audio/miss.wav +0 -0
  147. package/archetypes/rhythm/assets/audio/tap0.wav +0 -0
  148. package/archetypes/rhythm/assets/audio/tap1.wav +0 -0
  149. package/archetypes/rhythm/assets/audio/tap2.wav +0 -0
  150. package/archetypes/rhythm/assets/audio/ui-close.ogt +9 -0
  151. package/archetypes/rhythm/assets/audio/ui-error.ogt +9 -0
  152. package/archetypes/rhythm/assets/audio/ui-open.ogt +9 -0
  153. package/archetypes/rhythm/assets/audio/ui-press.ogt +9 -0
  154. package/archetypes/rhythm/assets/audio/ui-success.ogt +9 -0
  155. package/archetypes/rhythm/assets/charts/neon-pulse.ogt +919 -0
  156. package/archetypes/rhythm/assets/fonts/NotoSansSC-subset.ttf +0 -0
  157. package/archetypes/rhythm/assets/fonts/NotoSansSC-subset.ttf.ogt +10 -0
  158. package/archetypes/rhythm/assets/fonts/OFL.txt +93 -0
  159. package/archetypes/rhythm/assets/fx/hit.ogt +22 -0
  160. package/archetypes/rhythm/assets/skins/lanebeat/ChakraPetch-Medium.ttf +0 -0
  161. package/archetypes/rhythm/assets/skins/lanebeat/ChakraPetch-Medium.ttf.ogt +9 -0
  162. package/archetypes/rhythm/assets/skins/lanebeat/JetBrainsMono-Regular.ttf +0 -0
  163. package/archetypes/rhythm/assets/skins/lanebeat/JetBrainsMono-Regular.ttf.ogt +9 -0
  164. package/archetypes/rhythm/assets/skins/lanebeat/LICENSES.md +17 -0
  165. package/archetypes/rhythm/assets/skins/lanebeat/OFL.txt +95 -0
  166. package/archetypes/rhythm/assets/skins/lanebeat/Orbitron-Bold.ttf +0 -0
  167. package/archetypes/rhythm/assets/skins/lanebeat/Orbitron-Bold.ttf.ogt +9 -0
  168. package/archetypes/rhythm/assets/skins/lanebeat/atlas.png +0 -0
  169. package/archetypes/rhythm/assets/skins/lanebeat/atlas.png.ogt +7 -0
  170. package/archetypes/rhythm/assets/skins/lanebeat/icons.png +0 -0
  171. package/archetypes/rhythm/assets/skins/lanebeat/icons.png.ogt +7 -0
  172. package/archetypes/rhythm/assets/skins/lanebeat/skin.ogt +110 -0
  173. package/archetypes/rhythm/assets/sprites/lane.png +0 -0
  174. package/archetypes/rhythm/assets/sprites/lane.png.ogt +7 -0
  175. package/archetypes/rhythm/assets/sprites/note.png +0 -0
  176. package/archetypes/rhythm/assets/sprites/note.png.ogt +7 -0
  177. package/archetypes/rhythm/assets/sprites/ring.png +0 -0
  178. package/archetypes/rhythm/assets/sprites/ring.png.ogt +7 -0
  179. package/archetypes/rhythm/assets/sprites/spark.png +0 -0
  180. package/archetypes/rhythm/assets/sprites/spark.png.ogt +7 -0
  181. package/archetypes/rhythm/assets/strings/en.ogt +61 -0
  182. package/archetypes/rhythm/assets/strings/zh-CN.ogt +61 -0
  183. package/archetypes/rhythm/gitattributes +22 -0
  184. package/archetypes/rhythm/host.d.ts +46 -0
  185. package/archetypes/rhythm/package.json +18 -0
  186. package/archetypes/rhythm/project.ogt +14 -0
  187. package/archetypes/rhythm/references/metal/highway.png +0 -0
  188. package/archetypes/rhythm/references/metal/results.png +0 -0
  189. package/archetypes/rhythm/references/metal/title.png +0 -0
  190. package/archetypes/rhythm/src/components.ts +147 -0
  191. package/archetypes/rhythm/src/main.ts +202 -0
  192. package/archetypes/rhythm/src/systems.ts +490 -0
  193. package/archetypes/rhythm/src/ui.ts +421 -0
  194. package/archetypes/rhythm/tests/band.og.ts +45 -0
  195. package/archetypes/rhythm/tests/calibrate.og.ts +49 -0
  196. package/archetypes/rhythm/tests/clear.og.ts +51 -0
  197. package/archetypes/rhythm/tests/fail.og.ts +40 -0
  198. package/archetypes/rhythm/tests/flow.og.ts +54 -0
  199. package/archetypes/rhythm/tests/frames.og.ts +35 -0
  200. package/archetypes/rhythm/tests/frames.ts +134 -0
  201. package/archetypes/rhythm/tests/lib.ts +123 -0
  202. package/archetypes/rhythm/tests/pad.og.ts +41 -0
  203. package/archetypes/rhythm/tests/pause.og.ts +77 -0
  204. package/archetypes/rhythm/tests/phone.og.ts +44 -0
  205. package/archetypes/rhythm/tests/replay.og.ts +27 -0
  206. package/archetypes/rhythm/tests/timing.og.ts +37 -0
  207. package/archetypes/rhythm/tools/make-assets.py +383 -0
  208. package/archetypes/rhythm/tools/oglite.py +285 -0
  209. package/archetypes/rhythm/tsconfig.json +17 -0
  210. package/archetypes/roguelike/.origin/setup +14 -0
  211. package/archetypes/roguelike/LICENSES.md +14 -0
  212. package/archetypes/roguelike/README.md +256 -0
  213. package/archetypes/roguelike/assets/ai/foe.ogt +28 -0
  214. package/archetypes/roguelike/assets/ai/guardian.ogt +26 -0
  215. package/archetypes/roguelike/assets/audio/bump.wav +0 -0
  216. package/archetypes/roguelike/assets/audio/drink.wav +0 -0
  217. package/archetypes/roguelike/assets/audio/fall.wav +0 -0
  218. package/archetypes/roguelike/assets/audio/hit.wav +0 -0
  219. package/archetypes/roguelike/assets/audio/hurt.wav +0 -0
  220. package/archetypes/roguelike/assets/audio/item.wav +0 -0
  221. package/archetypes/roguelike/assets/audio/kill.wav +0 -0
  222. package/archetypes/roguelike/assets/audio/pickup.wav +0 -0
  223. package/archetypes/roguelike/assets/audio/roar.wav +0 -0
  224. package/archetypes/roguelike/assets/audio/stairs.wav +0 -0
  225. package/archetypes/roguelike/assets/audio/step.ogt +9 -0
  226. package/archetypes/roguelike/assets/audio/telegraph.wav +0 -0
  227. package/archetypes/roguelike/assets/audio/tomb.wav +0 -0
  228. package/archetypes/roguelike/assets/audio/ui-close.ogt +9 -0
  229. package/archetypes/roguelike/assets/audio/ui-error.ogt +9 -0
  230. package/archetypes/roguelike/assets/audio/ui-open.ogt +9 -0
  231. package/archetypes/roguelike/assets/audio/ui-press.ogt +9 -0
  232. package/archetypes/roguelike/assets/audio/ui-success.ogt +9 -0
  233. package/archetypes/roguelike/assets/audio/won.wav +0 -0
  234. package/archetypes/roguelike/assets/fonts/NotoSansSC-subset.ttf +0 -0
  235. package/archetypes/roguelike/assets/fonts/NotoSansSC-subset.ttf.ogt +10 -0
  236. package/archetypes/roguelike/assets/fonts/OFL.txt +93 -0
  237. package/archetypes/roguelike/assets/maps/dive.ogt +106 -0
  238. package/archetypes/roguelike/assets/skins/lampdive/DotGothic16-Regular.ttf +0 -0
  239. package/archetypes/roguelike/assets/skins/lampdive/DotGothic16-Regular.ttf.ogt +9 -0
  240. package/archetypes/roguelike/assets/skins/lampdive/LICENSES.md +16 -0
  241. package/archetypes/roguelike/assets/skins/lampdive/OFL.txt +93 -0
  242. package/archetypes/roguelike/assets/skins/lampdive/atlas.png +0 -0
  243. package/archetypes/roguelike/assets/skins/lampdive/atlas.png.ogt +7 -0
  244. package/archetypes/roguelike/assets/skins/lampdive/icons.png +0 -0
  245. package/archetypes/roguelike/assets/skins/lampdive/icons.png.ogt +7 -0
  246. package/archetypes/roguelike/assets/skins/lampdive/skin.ogt +115 -0
  247. package/archetypes/roguelike/assets/sprites/dive.ogt +50 -0
  248. package/archetypes/roguelike/assets/sprites/dive.png +0 -0
  249. package/archetypes/roguelike/assets/sprites/dive.png.ogt +7 -0
  250. package/archetypes/roguelike/assets/sprites/glow.png +0 -0
  251. package/archetypes/roguelike/assets/sprites/glow.png.ogt +7 -0
  252. package/archetypes/roguelike/assets/strings/en.ogt +57 -0
  253. package/archetypes/roguelike/assets/strings/zh-CN.ogt +57 -0
  254. package/archetypes/roguelike/assets/tiles/tomb.ogt +31 -0
  255. package/archetypes/roguelike/assets/tiles/tomb.png +0 -0
  256. package/archetypes/roguelike/assets/tiles/tomb.png.ogt +7 -0
  257. package/archetypes/roguelike/gitattributes +22 -0
  258. package/archetypes/roguelike/host.d.ts +46 -0
  259. package/archetypes/roguelike/package.json +18 -0
  260. package/archetypes/roguelike/project.ogt +14 -0
  261. package/archetypes/roguelike/references/metal/dive.png +0 -0
  262. package/archetypes/roguelike/references/metal/over.png +0 -0
  263. package/archetypes/roguelike/references/metal/title.png +0 -0
  264. package/archetypes/roguelike/src/art.ts +23 -0
  265. package/archetypes/roguelike/src/components.ts +169 -0
  266. package/archetypes/roguelike/src/dive.ts +144 -0
  267. package/archetypes/roguelike/src/foes.ts +174 -0
  268. package/archetypes/roguelike/src/main.ts +258 -0
  269. package/archetypes/roguelike/src/systems.ts +620 -0
  270. package/archetypes/roguelike/src/ui.ts +350 -0
  271. package/archetypes/roguelike/tests/flow.og.ts +54 -0
  272. package/archetypes/roguelike/tests/foes.og.ts +45 -0
  273. package/archetypes/roguelike/tests/frames.og.ts +32 -0
  274. package/archetypes/roguelike/tests/frames.ts +134 -0
  275. package/archetypes/roguelike/tests/lib.ts +83 -0
  276. package/archetypes/roguelike/tests/lose.og.ts +44 -0
  277. package/archetypes/roguelike/tests/pad.og.ts +54 -0
  278. package/archetypes/roguelike/tests/pause.og.ts +59 -0
  279. package/archetypes/roguelike/tests/phone.og.ts +54 -0
  280. package/archetypes/roguelike/tests/replay.og.ts +24 -0
  281. package/archetypes/roguelike/tests/win.og.ts +60 -0
  282. package/archetypes/roguelike/tools/make-assets.py +518 -0
  283. package/archetypes/roguelike/tools/oglite.py +285 -0
  284. package/archetypes/roguelike/tsconfig.json +17 -0
  285. package/archetypes/runner/.origin/setup +14 -0
  286. package/archetypes/runner/LICENSES.md +10 -0
  287. package/archetypes/runner/README.md +225 -0
  288. package/archetypes/runner/assets/audio/coin.wav +0 -0
  289. package/archetypes/runner/assets/audio/crash.wav +0 -0
  290. package/archetypes/runner/assets/audio/hold.ogt +9 -0
  291. package/archetypes/runner/assets/audio/jump.wav +0 -0
  292. package/archetypes/runner/assets/audio/start.wav +0 -0
  293. package/archetypes/runner/assets/fonts/OFL.txt +93 -0
  294. package/archetypes/runner/assets/fonts/ui.ttf +0 -0
  295. package/archetypes/runner/assets/fonts/ui.ttf.ogt +11 -0
  296. package/archetypes/runner/assets/maps/far.ogt +25 -0
  297. package/archetypes/runner/assets/maps/near.ogt +25 -0
  298. package/archetypes/runner/assets/maps/roofs.ogt +19 -0
  299. package/archetypes/runner/assets/scenes/main.ogt +35 -0
  300. package/archetypes/runner/assets/sprites/coin.ogt +11 -0
  301. package/archetypes/runner/assets/sprites/coin.png +0 -0
  302. package/archetypes/runner/assets/sprites/coin.png.ogt +7 -0
  303. package/archetypes/runner/assets/sprites/courier.ogt +32 -0
  304. package/archetypes/runner/assets/sprites/courier.png +0 -0
  305. package/archetypes/runner/assets/sprites/courier.png.ogt +7 -0
  306. package/archetypes/runner/assets/sprites/props.ogt +21 -0
  307. package/archetypes/runner/assets/sprites/props.png +0 -0
  308. package/archetypes/runner/assets/sprites/props.png.ogt +7 -0
  309. package/archetypes/runner/assets/sprites/sky.png +0 -0
  310. package/archetypes/runner/assets/sprites/sky.png.ogt +7 -0
  311. package/archetypes/runner/assets/tiles/city.ogt +18 -0
  312. package/archetypes/runner/assets/tiles/city.png +0 -0
  313. package/archetypes/runner/assets/tiles/city.png.ogt +7 -0
  314. package/archetypes/runner/gitattributes +22 -0
  315. package/archetypes/runner/host.d.ts +46 -0
  316. package/archetypes/runner/package.json +18 -0
  317. package/archetypes/runner/project.ogt +18 -0
  318. package/archetypes/runner/references/metal/frames-coin.png +0 -0
  319. package/archetypes/runner/references/metal/frames-crash.png +0 -0
  320. package/archetypes/runner/references/metal/frames-title.png +0 -0
  321. package/archetypes/runner/src/art.ts +57 -0
  322. package/archetypes/runner/src/components.ts +94 -0
  323. package/archetypes/runner/src/main.ts +241 -0
  324. package/archetypes/runner/src/systems.ts +553 -0
  325. package/archetypes/runner/tests/coins.og.ts +30 -0
  326. package/archetypes/runner/tests/flow.og.ts +72 -0
  327. package/archetypes/runner/tests/frames.og.ts +37 -0
  328. package/archetypes/runner/tests/frames.ts +134 -0
  329. package/archetypes/runner/tests/jump.og.ts +44 -0
  330. package/archetypes/runner/tests/lib.ts +42 -0
  331. package/archetypes/runner/tests/records.og.ts +43 -0
  332. package/archetypes/runner/tests/replay.og.ts +36 -0
  333. package/archetypes/runner/tests/sounds.og.ts +43 -0
  334. package/archetypes/runner/tests/tune.og.ts +36 -0
  335. package/archetypes/runner/tools/make-assets.py +603 -0
  336. package/archetypes/runner/tools/oglite.py +285 -0
  337. package/archetypes/runner/tsconfig.json +17 -0
  338. package/archetypes/third-person/.origin/setup +14 -0
  339. package/archetypes/third-person/LICENSES.md +23 -0
  340. package/archetypes/third-person/README.md +249 -0
  341. package/archetypes/third-person/assets/ai/sentinel-east.ogt +69 -0
  342. package/archetypes/third-person/assets/ai/sentinel-north.ogt +69 -0
  343. package/archetypes/third-person/assets/ai/sentinel-west.ogt +69 -0
  344. package/archetypes/third-person/assets/anims/humanoid-clips.glb +0 -0
  345. package/archetypes/third-person/assets/audio/alarm.wav +0 -0
  346. package/archetypes/third-person/assets/audio/dawn.wav +0 -0
  347. package/archetypes/third-person/assets/audio/grab.wav +0 -0
  348. package/archetypes/third-person/assets/audio/ignite.wav +0 -0
  349. package/archetypes/third-person/assets/audio/jump.wav +0 -0
  350. package/archetypes/third-person/assets/audio/night.wav +0 -0
  351. package/archetypes/third-person/assets/audio/splash.wav +0 -0
  352. package/archetypes/third-person/assets/audio/step.ogt +9 -0
  353. package/archetypes/third-person/assets/audio/ui-close.ogt +9 -0
  354. package/archetypes/third-person/assets/audio/ui-error.ogt +9 -0
  355. package/archetypes/third-person/assets/audio/ui-open.ogt +9 -0
  356. package/archetypes/third-person/assets/audio/ui-press.ogt +9 -0
  357. package/archetypes/third-person/assets/audio/ui-success.ogt +9 -0
  358. package/archetypes/third-person/assets/audio/vale.wav +0 -0
  359. package/archetypes/third-person/assets/fonts/NotoSansSC-subset.ttf +0 -0
  360. package/archetypes/third-person/assets/fonts/NotoSansSC-subset.ttf.ogt +10 -0
  361. package/archetypes/third-person/assets/fonts/OFL.txt +93 -0
  362. package/archetypes/third-person/assets/fx/burst.ogt +25 -0
  363. package/archetypes/third-person/assets/fx/fire.ogt +24 -0
  364. package/archetypes/third-person/assets/fx/smoke.ogt +24 -0
  365. package/archetypes/third-person/assets/fx/splash.ogt +24 -0
  366. package/archetypes/third-person/assets/luts/teal-orange.cube +4917 -0
  367. package/archetypes/third-person/assets/models/stout.glb +0 -0
  368. package/archetypes/third-person/assets/models/strider.glb +0 -0
  369. package/archetypes/third-person/assets/models/strider.glb.ogt +9 -0
  370. package/archetypes/third-person/assets/nav/vale.ogt +43 -0
  371. package/archetypes/third-person/assets/rigs/strider.ogt +6 -0
  372. package/archetypes/third-person/assets/skins/ember/Cinzel-Bold.ttf +0 -0
  373. package/archetypes/third-person/assets/skins/ember/Cinzel-Bold.ttf.ogt +9 -0
  374. package/archetypes/third-person/assets/skins/ember/LICENSES.md +13 -0
  375. package/archetypes/third-person/assets/skins/ember/Newsreader-Medium.ttf +0 -0
  376. package/archetypes/third-person/assets/skins/ember/Newsreader-Medium.ttf.ogt +9 -0
  377. package/archetypes/third-person/assets/skins/ember/OFL.txt +94 -0
  378. package/archetypes/third-person/assets/skins/ember/atlas.png +0 -0
  379. package/archetypes/third-person/assets/skins/ember/atlas.png.ogt +7 -0
  380. package/archetypes/third-person/assets/skins/ember/icons.png +0 -0
  381. package/archetypes/third-person/assets/skins/ember/icons.png.ogt +7 -0
  382. package/archetypes/third-person/assets/skins/ember/skin.ogt +109 -0
  383. package/archetypes/third-person/assets/strings/en.ogt +47 -0
  384. package/archetypes/third-person/assets/strings/zh-CN.ogt +47 -0
  385. package/archetypes/third-person/assets/terrain/vale-control.png +0 -0
  386. package/archetypes/third-person/assets/terrain/vale.ogt +42 -0
  387. package/archetypes/third-person/assets/terrain/vale.png +0 -0
  388. package/archetypes/third-person/assets/textures/decals.png +0 -0
  389. package/archetypes/third-person/assets/textures/flame.png +0 -0
  390. package/archetypes/third-person/assets/textures/smoke.png +0 -0
  391. package/archetypes/third-person/assets/textures/spark.png +0 -0
  392. package/archetypes/third-person/assets/textures/terrain-grass.png +0 -0
  393. package/archetypes/third-person/assets/textures/terrain-path.png +0 -0
  394. package/archetypes/third-person/assets/textures/terrain-rock.png +0 -0
  395. package/archetypes/third-person/assets/textures/terrain-sand.png +0 -0
  396. package/archetypes/third-person/gitattributes +22 -0
  397. package/archetypes/third-person/host.d.ts +46 -0
  398. package/archetypes/third-person/package.json +18 -0
  399. package/archetypes/third-person/project.ogt +14 -0
  400. package/archetypes/third-person/references/metal/beacon.png +0 -0
  401. package/archetypes/third-person/references/metal/dawn.png +0 -0
  402. package/archetypes/third-person/references/metal/title.png +0 -0
  403. package/archetypes/third-person/references/webgl2/beacon.png +0 -0
  404. package/archetypes/third-person/src/anim.ts +87 -0
  405. package/archetypes/third-person/src/beacons.ts +80 -0
  406. package/archetypes/third-person/src/components.ts +148 -0
  407. package/archetypes/third-person/src/hero.ts +293 -0
  408. package/archetypes/third-person/src/main.ts +164 -0
  409. package/archetypes/third-person/src/sentinels.ts +159 -0
  410. package/archetypes/third-person/src/sound.ts +66 -0
  411. package/archetypes/third-person/src/ui.ts +451 -0
  412. package/archetypes/third-person/src/world.ts +212 -0
  413. package/archetypes/third-person/tests/flow.og.ts +70 -0
  414. package/archetypes/third-person/tests/frames.og.ts +35 -0
  415. package/archetypes/third-person/tests/frames.ts +134 -0
  416. package/archetypes/third-person/tests/hitstop.og.ts +26 -0
  417. package/archetypes/third-person/tests/lib.ts +87 -0
  418. package/archetypes/third-person/tests/lose.og.ts +44 -0
  419. package/archetypes/third-person/tests/pause.og.ts +64 -0
  420. package/archetypes/third-person/tests/phone.og.ts +65 -0
  421. package/archetypes/third-person/tests/replay.og.ts +32 -0
  422. package/archetypes/third-person/tests/restart.og.ts +28 -0
  423. package/archetypes/third-person/tests/sentinels.og.ts +48 -0
  424. package/archetypes/third-person/tests/win.og.ts +62 -0
  425. package/archetypes/third-person/tools/make-assets.py +353 -0
  426. package/archetypes/third-person/tools/oglite.py +285 -0
  427. package/archetypes/third-person/tsconfig.json +17 -0
  428. package/archetypes/topdown/.origin/setup +14 -0
  429. package/archetypes/topdown/LICENSES.md +10 -0
  430. package/archetypes/topdown/README.md +235 -0
  431. package/archetypes/topdown/assets/ai/slime.ogt +49 -0
  432. package/archetypes/topdown/assets/audio/coin.wav +0 -0
  433. package/archetypes/topdown/assets/audio/door.wav +0 -0
  434. package/archetypes/topdown/assets/audio/hit.wav +0 -0
  435. package/archetypes/topdown/assets/audio/hurt.wav +0 -0
  436. package/archetypes/topdown/assets/audio/key.wav +0 -0
  437. package/archetypes/topdown/assets/audio/step.ogt +9 -0
  438. package/archetypes/topdown/assets/fonts/OFL.txt +93 -0
  439. package/archetypes/topdown/assets/fonts/ui.ttf +0 -0
  440. package/archetypes/topdown/assets/fonts/ui.ttf.ogt +9 -0
  441. package/archetypes/topdown/assets/maps/tomb.tmj +2183 -0
  442. package/archetypes/topdown/assets/sprites/hero.ogt +58 -0
  443. package/archetypes/topdown/assets/sprites/hero.png +0 -0
  444. package/archetypes/topdown/assets/sprites/hero.png.ogt +7 -0
  445. package/archetypes/topdown/assets/sprites/items.ogt +15 -0
  446. package/archetypes/topdown/assets/sprites/items.png +0 -0
  447. package/archetypes/topdown/assets/sprites/items.png.ogt +7 -0
  448. package/archetypes/topdown/assets/sprites/slime.ogt +17 -0
  449. package/archetypes/topdown/assets/sprites/slime.png +0 -0
  450. package/archetypes/topdown/assets/sprites/slime.png.ogt +7 -0
  451. package/archetypes/topdown/assets/tiles/dungeon.ogt +65 -0
  452. package/archetypes/topdown/assets/tiles/dungeon.png +0 -0
  453. package/archetypes/topdown/assets/tiles/dungeon.png.ogt +7 -0
  454. package/archetypes/topdown/gitattributes +22 -0
  455. package/archetypes/topdown/host.d.ts +46 -0
  456. package/archetypes/topdown/package.json +18 -0
  457. package/archetypes/topdown/project.ogt +14 -0
  458. package/archetypes/topdown/references/metal/crit.png +0 -0
  459. package/archetypes/topdown/references/metal/dash.png +0 -0
  460. package/archetypes/topdown/references/metal/east.png +0 -0
  461. package/archetypes/topdown/references/metal/start.png +0 -0
  462. package/archetypes/topdown/src/art.ts +48 -0
  463. package/archetypes/topdown/src/components.ts +128 -0
  464. package/archetypes/topdown/src/main.ts +275 -0
  465. package/archetypes/topdown/src/systems.ts +503 -0
  466. package/archetypes/topdown/tests/ai.og.ts +64 -0
  467. package/archetypes/topdown/tests/combat.og.ts +72 -0
  468. package/archetypes/topdown/tests/door.og.ts +62 -0
  469. package/archetypes/topdown/tests/flee.og.ts +49 -0
  470. package/archetypes/topdown/tests/frames.og.ts +45 -0
  471. package/archetypes/topdown/tests/frames.ts +134 -0
  472. package/archetypes/topdown/tests/lib.ts +71 -0
  473. package/archetypes/topdown/tests/replay.og.ts +40 -0
  474. package/archetypes/topdown/tests/walk.og.ts +46 -0
  475. package/archetypes/topdown/tools/make-assets.py +623 -0
  476. package/archetypes/topdown/tools/oglite.py +285 -0
  477. package/archetypes/topdown/tsconfig.json +17 -0
  478. package/archetypes/tower-defense/.origin/setup +14 -0
  479. package/archetypes/tower-defense/LICENSES.md +15 -0
  480. package/archetypes/tower-defense/README.md +240 -0
  481. package/archetypes/tower-defense/assets/ai/plant.ogt +16 -0
  482. package/archetypes/tower-defense/assets/audio/clear.wav +0 -0
  483. package/archetypes/tower-defense/assets/audio/frost.wav +0 -0
  484. package/archetypes/tower-defense/assets/audio/leak.wav +0 -0
  485. package/archetypes/tower-defense/assets/audio/lost.wav +0 -0
  486. package/archetypes/tower-defense/assets/audio/night.wav +0 -0
  487. package/archetypes/tower-defense/assets/audio/plant.wav +0 -0
  488. package/archetypes/tower-defense/assets/audio/pop.wav +0 -0
  489. package/archetypes/tower-defense/assets/audio/thorn.wav +0 -0
  490. package/archetypes/tower-defense/assets/audio/ui-close.ogt +9 -0
  491. package/archetypes/tower-defense/assets/audio/ui-error.ogt +9 -0
  492. package/archetypes/tower-defense/assets/audio/ui-open.ogt +9 -0
  493. package/archetypes/tower-defense/assets/audio/ui-press.ogt +9 -0
  494. package/archetypes/tower-defense/assets/audio/ui-success.ogt +9 -0
  495. package/archetypes/tower-defense/assets/audio/wave.wav +0 -0
  496. package/archetypes/tower-defense/assets/audio/won.wav +0 -0
  497. package/archetypes/tower-defense/assets/fonts/NotoSansSC-subset.ttf +0 -0
  498. package/archetypes/tower-defense/assets/fonts/NotoSansSC-subset.ttf.ogt +10 -0
  499. package/archetypes/tower-defense/assets/fonts/OFL.txt +93 -0
  500. package/archetypes/tower-defense/assets/fx/fireflies.ogt +21 -0
  501. package/archetypes/tower-defense/assets/fx/pop.ogt +21 -0
  502. package/archetypes/tower-defense/assets/maps/garden.ogt +91 -0
  503. package/archetypes/tower-defense/assets/skins/pathguard/Fredoka-SemiBold.ttf +0 -0
  504. package/archetypes/tower-defense/assets/skins/pathguard/Fredoka-SemiBold.ttf.ogt +9 -0
  505. package/archetypes/tower-defense/assets/skins/pathguard/LICENSES.md +13 -0
  506. package/archetypes/tower-defense/assets/skins/pathguard/LilitaOne-Regular.ttf +0 -0
  507. package/archetypes/tower-defense/assets/skins/pathguard/LilitaOne-Regular.ttf.ogt +9 -0
  508. package/archetypes/tower-defense/assets/skins/pathguard/OFL.txt +94 -0
  509. package/archetypes/tower-defense/assets/skins/pathguard/atlas.png +0 -0
  510. package/archetypes/tower-defense/assets/skins/pathguard/atlas.png.ogt +7 -0
  511. package/archetypes/tower-defense/assets/skins/pathguard/icons.png +0 -0
  512. package/archetypes/tower-defense/assets/skins/pathguard/icons.png.ogt +7 -0
  513. package/archetypes/tower-defense/assets/skins/pathguard/skin.ogt +111 -0
  514. package/archetypes/tower-defense/assets/sprites/garden.ogt +66 -0
  515. package/archetypes/tower-defense/assets/sprites/garden.png +0 -0
  516. package/archetypes/tower-defense/assets/sprites/garden.png.ogt +7 -0
  517. package/archetypes/tower-defense/assets/sprites/glow.png +0 -0
  518. package/archetypes/tower-defense/assets/sprites/glow.png.ogt +7 -0
  519. package/archetypes/tower-defense/assets/sprites/ring.png +0 -0
  520. package/archetypes/tower-defense/assets/sprites/ring.png.ogt +7 -0
  521. package/archetypes/tower-defense/assets/sprites/spark.png +0 -0
  522. package/archetypes/tower-defense/assets/sprites/spark.png.ogt +7 -0
  523. package/archetypes/tower-defense/assets/strings/en.ogt +47 -0
  524. package/archetypes/tower-defense/assets/strings/zh-CN.ogt +47 -0
  525. package/archetypes/tower-defense/assets/tiles/garden.ogt +10 -0
  526. package/archetypes/tower-defense/assets/tiles/garden.png +0 -0
  527. package/archetypes/tower-defense/assets/tiles/garden.png.ogt +7 -0
  528. package/archetypes/tower-defense/gitattributes +22 -0
  529. package/archetypes/tower-defense/host.d.ts +46 -0
  530. package/archetypes/tower-defense/package.json +18 -0
  531. package/archetypes/tower-defense/project.ogt +14 -0
  532. package/archetypes/tower-defense/references/metal/end.png +0 -0
  533. package/archetypes/tower-defense/references/metal/title.png +0 -0
  534. package/archetypes/tower-defense/references/metal/wave.png +0 -0
  535. package/archetypes/tower-defense/src/art.ts +24 -0
  536. package/archetypes/tower-defense/src/components.ts +156 -0
  537. package/archetypes/tower-defense/src/main.ts +253 -0
  538. package/archetypes/tower-defense/src/systems.ts +658 -0
  539. package/archetypes/tower-defense/src/ui.ts +382 -0
  540. package/archetypes/tower-defense/tests/flow.og.ts +56 -0
  541. package/archetypes/tower-defense/tests/frames.og.ts +31 -0
  542. package/archetypes/tower-defense/tests/frames.ts +134 -0
  543. package/archetypes/tower-defense/tests/lib.ts +81 -0
  544. package/archetypes/tower-defense/tests/lose.og.ts +40 -0
  545. package/archetypes/tower-defense/tests/maze.og.ts +53 -0
  546. package/archetypes/tower-defense/tests/pad.og.ts +41 -0
  547. package/archetypes/tower-defense/tests/pause.og.ts +59 -0
  548. package/archetypes/tower-defense/tests/phone.og.ts +49 -0
  549. package/archetypes/tower-defense/tests/replay.og.ts +28 -0
  550. package/archetypes/tower-defense/tests/win.og.ts +58 -0
  551. package/archetypes/tower-defense/tools/make-assets.py +640 -0
  552. package/archetypes/tower-defense/tools/oglite.py +285 -0
  553. package/archetypes/tower-defense/tsconfig.json +17 -0
  554. package/bin/create.ts +496 -0
  555. package/looks/catalogue.json +1871 -0
  556. package/package.json +31 -4
  557. package/template/.origin/setup +14 -0
  558. package/template/LICENSES.md +23 -0
  559. package/template/README.md +37 -0
  560. package/template/assets/ai/guard.ogt +48 -0
  561. package/template/assets/audio/blip.wav +0 -0
  562. package/template/assets/audio/click.ogt +9 -0
  563. package/template/assets/fonts/NotoSansSC-Regular-subset.ttf +0 -0
  564. package/template/assets/fonts/NotoSansSC-Regular-subset.ttf.ogt +12 -0
  565. package/template/assets/fonts/OFL.txt +93 -0
  566. package/template/assets/looks/origin-game.ogt +12 -0
  567. package/template/assets/models/dropship.glb +0 -0
  568. package/template/assets/models/walker.glb +0 -0
  569. package/template/assets/nav/yard.ogt +27 -0
  570. package/template/assets/scenes/main.ogt +34 -0
  571. package/template/assets/strings/en.ogt +14 -0
  572. package/template/assets/textures/stone.png +0 -0
  573. package/template/assets/textures/stone_n.png +0 -0
  574. package/template/assets/textures/stone_n.png.ogt +7 -0
  575. package/template/gitattributes +22 -0
  576. package/template/package.json +18 -0
  577. package/template/project.ogt +25 -0
  578. package/template/src/main.ts +246 -0
  579. package/template/tests/guard.og.ts +67 -0
  580. package/template/tests/smoke.og.ts +43 -0
  581. 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
+ }