@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.
Files changed (590) 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/gitignore +8 -0
  56. package/archetypes/idle/host.d.ts +46 -0
  57. package/archetypes/idle/package.json +18 -0
  58. package/archetypes/idle/project.ogt +14 -0
  59. package/archetypes/idle/references/metal/card.png +0 -0
  60. package/archetypes/idle/references/metal/orbit.png +0 -0
  61. package/archetypes/idle/references/metal/title.png +0 -0
  62. package/archetypes/idle/src/components.ts +139 -0
  63. package/archetypes/idle/src/main.ts +247 -0
  64. package/archetypes/idle/src/numbers.ts +126 -0
  65. package/archetypes/idle/src/systems.ts +340 -0
  66. package/archetypes/idle/src/ui.ts +412 -0
  67. package/archetypes/idle/tests/away.og.ts +42 -0
  68. package/archetypes/idle/tests/flow.og.ts +57 -0
  69. package/archetypes/idle/tests/frames.og.ts +33 -0
  70. package/archetypes/idle/tests/frames.ts +134 -0
  71. package/archetypes/idle/tests/lib.ts +74 -0
  72. package/archetypes/idle/tests/milestone.og.ts +32 -0
  73. package/archetypes/idle/tests/nova.og.ts +52 -0
  74. package/archetypes/idle/tests/offline.og.ts +60 -0
  75. package/archetypes/idle/tests/pad.og.ts +55 -0
  76. package/archetypes/idle/tests/pause.og.ts +68 -0
  77. package/archetypes/idle/tests/phone.og.ts +50 -0
  78. package/archetypes/idle/tests/replay.og.ts +28 -0
  79. package/archetypes/idle/tools/make-assets.py +448 -0
  80. package/archetypes/idle/tools/oglite.py +285 -0
  81. package/archetypes/idle/tsconfig.json +17 -0
  82. package/archetypes/match3/.origin/setup +14 -0
  83. package/archetypes/match3/LICENSES.md +7 -0
  84. package/archetypes/match3/README.md +205 -0
  85. package/archetypes/match3/assets/audio/cascade.wav +0 -0
  86. package/archetypes/match3/assets/audio/clear.wav +0 -0
  87. package/archetypes/match3/assets/audio/lost.wav +0 -0
  88. package/archetypes/match3/assets/audio/refused.wav +0 -0
  89. package/archetypes/match3/assets/audio/select.wav +0 -0
  90. package/archetypes/match3/assets/audio/swap.wav +0 -0
  91. package/archetypes/match3/assets/audio/won.wav +0 -0
  92. package/archetypes/match3/assets/fonts/OFL.txt +93 -0
  93. package/archetypes/match3/assets/fonts/ui.ttf +0 -0
  94. package/archetypes/match3/assets/fonts/ui.ttf.ogt +11 -0
  95. package/archetypes/match3/assets/scenes/main.ogt +24 -0
  96. package/archetypes/match3/assets/sprites/backdrop.png +0 -0
  97. package/archetypes/match3/assets/sprites/board.ogt +21 -0
  98. package/archetypes/match3/assets/sprites/cells.ogt +7 -0
  99. package/archetypes/match3/assets/sprites/cells.png +0 -0
  100. package/archetypes/match3/assets/sprites/cells.png.ogt +7 -0
  101. package/archetypes/match3/assets/sprites/gems.ogt +75 -0
  102. package/archetypes/match3/assets/sprites/gems.png +0 -0
  103. package/archetypes/match3/assets/sprites/panel.png +0 -0
  104. package/archetypes/match3/assets/sprites/ring.png +0 -0
  105. package/archetypes/match3/gitattributes +22 -0
  106. package/archetypes/match3/gitignore +8 -0
  107. package/archetypes/match3/host.d.ts +46 -0
  108. package/archetypes/match3/package.json +18 -0
  109. package/archetypes/match3/project.ogt +18 -0
  110. package/archetypes/match3/references/metal/cascade.png +0 -0
  111. package/archetypes/match3/references/metal/clearing.png +0 -0
  112. package/archetypes/match3/references/metal/dealt.png +0 -0
  113. package/archetypes/match3/src/art.ts +54 -0
  114. package/archetypes/match3/src/board.ts +112 -0
  115. package/archetypes/match3/src/components.ts +95 -0
  116. package/archetypes/match3/src/layout.ts +25 -0
  117. package/archetypes/match3/src/main.ts +199 -0
  118. package/archetypes/match3/src/systems.ts +631 -0
  119. package/archetypes/match3/tests/drag.og.ts +31 -0
  120. package/archetypes/match3/tests/endings.og.ts +40 -0
  121. package/archetypes/match3/tests/frames.og.ts +49 -0
  122. package/archetypes/match3/tests/frames.ts +134 -0
  123. package/archetypes/match3/tests/hidpi.og.ts +41 -0
  124. package/archetypes/match3/tests/lib.ts +64 -0
  125. package/archetypes/match3/tests/replay.og.ts +28 -0
  126. package/archetypes/match3/tests/sounds.og.ts +50 -0
  127. package/archetypes/match3/tests/swap.og.ts +67 -0
  128. package/archetypes/match3/tools/make-assets.py +404 -0
  129. package/archetypes/match3/tools/oglite.py +285 -0
  130. package/archetypes/match3/tsconfig.json +17 -0
  131. package/archetypes/rhythm/.origin/setup +14 -0
  132. package/archetypes/rhythm/LICENSES.md +13 -0
  133. package/archetypes/rhythm/README.md +235 -0
  134. package/archetypes/rhythm/assets/audio/bass0.wav +0 -0
  135. package/archetypes/rhythm/assets/audio/bass1.wav +0 -0
  136. package/archetypes/rhythm/assets/audio/bass2.wav +0 -0
  137. package/archetypes/rhythm/assets/audio/bass3.wav +0 -0
  138. package/archetypes/rhythm/assets/audio/chords0.wav +0 -0
  139. package/archetypes/rhythm/assets/audio/chords1.wav +0 -0
  140. package/archetypes/rhythm/assets/audio/chords2.wav +0 -0
  141. package/archetypes/rhythm/assets/audio/chords3.wav +0 -0
  142. package/archetypes/rhythm/assets/audio/clear.wav +0 -0
  143. package/archetypes/rhythm/assets/audio/click.wav +0 -0
  144. package/archetypes/rhythm/assets/audio/drums.wav +0 -0
  145. package/archetypes/rhythm/assets/audio/fail.wav +0 -0
  146. package/archetypes/rhythm/assets/audio/leadA.wav +0 -0
  147. package/archetypes/rhythm/assets/audio/leadB.wav +0 -0
  148. package/archetypes/rhythm/assets/audio/miss.wav +0 -0
  149. package/archetypes/rhythm/assets/audio/tap0.wav +0 -0
  150. package/archetypes/rhythm/assets/audio/tap1.wav +0 -0
  151. package/archetypes/rhythm/assets/audio/tap2.wav +0 -0
  152. package/archetypes/rhythm/assets/audio/ui-close.ogt +9 -0
  153. package/archetypes/rhythm/assets/audio/ui-error.ogt +9 -0
  154. package/archetypes/rhythm/assets/audio/ui-open.ogt +9 -0
  155. package/archetypes/rhythm/assets/audio/ui-press.ogt +9 -0
  156. package/archetypes/rhythm/assets/audio/ui-success.ogt +9 -0
  157. package/archetypes/rhythm/assets/charts/neon-pulse.ogt +919 -0
  158. package/archetypes/rhythm/assets/fonts/NotoSansSC-subset.ttf +0 -0
  159. package/archetypes/rhythm/assets/fonts/NotoSansSC-subset.ttf.ogt +10 -0
  160. package/archetypes/rhythm/assets/fonts/OFL.txt +93 -0
  161. package/archetypes/rhythm/assets/fx/hit.ogt +22 -0
  162. package/archetypes/rhythm/assets/skins/lanebeat/ChakraPetch-Medium.ttf +0 -0
  163. package/archetypes/rhythm/assets/skins/lanebeat/ChakraPetch-Medium.ttf.ogt +9 -0
  164. package/archetypes/rhythm/assets/skins/lanebeat/JetBrainsMono-Regular.ttf +0 -0
  165. package/archetypes/rhythm/assets/skins/lanebeat/JetBrainsMono-Regular.ttf.ogt +9 -0
  166. package/archetypes/rhythm/assets/skins/lanebeat/LICENSES.md +17 -0
  167. package/archetypes/rhythm/assets/skins/lanebeat/OFL.txt +95 -0
  168. package/archetypes/rhythm/assets/skins/lanebeat/Orbitron-Bold.ttf +0 -0
  169. package/archetypes/rhythm/assets/skins/lanebeat/Orbitron-Bold.ttf.ogt +9 -0
  170. package/archetypes/rhythm/assets/skins/lanebeat/atlas.png +0 -0
  171. package/archetypes/rhythm/assets/skins/lanebeat/atlas.png.ogt +7 -0
  172. package/archetypes/rhythm/assets/skins/lanebeat/icons.png +0 -0
  173. package/archetypes/rhythm/assets/skins/lanebeat/icons.png.ogt +7 -0
  174. package/archetypes/rhythm/assets/skins/lanebeat/skin.ogt +110 -0
  175. package/archetypes/rhythm/assets/sprites/lane.png +0 -0
  176. package/archetypes/rhythm/assets/sprites/lane.png.ogt +7 -0
  177. package/archetypes/rhythm/assets/sprites/note.png +0 -0
  178. package/archetypes/rhythm/assets/sprites/note.png.ogt +7 -0
  179. package/archetypes/rhythm/assets/sprites/ring.png +0 -0
  180. package/archetypes/rhythm/assets/sprites/ring.png.ogt +7 -0
  181. package/archetypes/rhythm/assets/sprites/spark.png +0 -0
  182. package/archetypes/rhythm/assets/sprites/spark.png.ogt +7 -0
  183. package/archetypes/rhythm/assets/strings/en.ogt +61 -0
  184. package/archetypes/rhythm/assets/strings/zh-CN.ogt +61 -0
  185. package/archetypes/rhythm/gitattributes +22 -0
  186. package/archetypes/rhythm/gitignore +8 -0
  187. package/archetypes/rhythm/host.d.ts +46 -0
  188. package/archetypes/rhythm/package.json +18 -0
  189. package/archetypes/rhythm/project.ogt +14 -0
  190. package/archetypes/rhythm/references/metal/highway.png +0 -0
  191. package/archetypes/rhythm/references/metal/results.png +0 -0
  192. package/archetypes/rhythm/references/metal/title.png +0 -0
  193. package/archetypes/rhythm/src/components.ts +147 -0
  194. package/archetypes/rhythm/src/main.ts +202 -0
  195. package/archetypes/rhythm/src/systems.ts +490 -0
  196. package/archetypes/rhythm/src/ui.ts +421 -0
  197. package/archetypes/rhythm/tests/band.og.ts +45 -0
  198. package/archetypes/rhythm/tests/calibrate.og.ts +49 -0
  199. package/archetypes/rhythm/tests/clear.og.ts +51 -0
  200. package/archetypes/rhythm/tests/fail.og.ts +40 -0
  201. package/archetypes/rhythm/tests/flow.og.ts +54 -0
  202. package/archetypes/rhythm/tests/frames.og.ts +35 -0
  203. package/archetypes/rhythm/tests/frames.ts +134 -0
  204. package/archetypes/rhythm/tests/lib.ts +123 -0
  205. package/archetypes/rhythm/tests/pad.og.ts +41 -0
  206. package/archetypes/rhythm/tests/pause.og.ts +77 -0
  207. package/archetypes/rhythm/tests/phone.og.ts +44 -0
  208. package/archetypes/rhythm/tests/replay.og.ts +27 -0
  209. package/archetypes/rhythm/tests/timing.og.ts +37 -0
  210. package/archetypes/rhythm/tools/make-assets.py +383 -0
  211. package/archetypes/rhythm/tools/oglite.py +285 -0
  212. package/archetypes/rhythm/tsconfig.json +17 -0
  213. package/archetypes/roguelike/.origin/setup +14 -0
  214. package/archetypes/roguelike/LICENSES.md +14 -0
  215. package/archetypes/roguelike/README.md +256 -0
  216. package/archetypes/roguelike/assets/ai/foe.ogt +28 -0
  217. package/archetypes/roguelike/assets/ai/guardian.ogt +26 -0
  218. package/archetypes/roguelike/assets/audio/bump.wav +0 -0
  219. package/archetypes/roguelike/assets/audio/drink.wav +0 -0
  220. package/archetypes/roguelike/assets/audio/fall.wav +0 -0
  221. package/archetypes/roguelike/assets/audio/hit.wav +0 -0
  222. package/archetypes/roguelike/assets/audio/hurt.wav +0 -0
  223. package/archetypes/roguelike/assets/audio/item.wav +0 -0
  224. package/archetypes/roguelike/assets/audio/kill.wav +0 -0
  225. package/archetypes/roguelike/assets/audio/pickup.wav +0 -0
  226. package/archetypes/roguelike/assets/audio/roar.wav +0 -0
  227. package/archetypes/roguelike/assets/audio/stairs.wav +0 -0
  228. package/archetypes/roguelike/assets/audio/step.ogt +9 -0
  229. package/archetypes/roguelike/assets/audio/telegraph.wav +0 -0
  230. package/archetypes/roguelike/assets/audio/tomb.wav +0 -0
  231. package/archetypes/roguelike/assets/audio/ui-close.ogt +9 -0
  232. package/archetypes/roguelike/assets/audio/ui-error.ogt +9 -0
  233. package/archetypes/roguelike/assets/audio/ui-open.ogt +9 -0
  234. package/archetypes/roguelike/assets/audio/ui-press.ogt +9 -0
  235. package/archetypes/roguelike/assets/audio/ui-success.ogt +9 -0
  236. package/archetypes/roguelike/assets/audio/won.wav +0 -0
  237. package/archetypes/roguelike/assets/fonts/NotoSansSC-subset.ttf +0 -0
  238. package/archetypes/roguelike/assets/fonts/NotoSansSC-subset.ttf.ogt +10 -0
  239. package/archetypes/roguelike/assets/fonts/OFL.txt +93 -0
  240. package/archetypes/roguelike/assets/maps/dive.ogt +106 -0
  241. package/archetypes/roguelike/assets/skins/lampdive/DotGothic16-Regular.ttf +0 -0
  242. package/archetypes/roguelike/assets/skins/lampdive/DotGothic16-Regular.ttf.ogt +9 -0
  243. package/archetypes/roguelike/assets/skins/lampdive/LICENSES.md +16 -0
  244. package/archetypes/roguelike/assets/skins/lampdive/OFL.txt +93 -0
  245. package/archetypes/roguelike/assets/skins/lampdive/atlas.png +0 -0
  246. package/archetypes/roguelike/assets/skins/lampdive/atlas.png.ogt +7 -0
  247. package/archetypes/roguelike/assets/skins/lampdive/icons.png +0 -0
  248. package/archetypes/roguelike/assets/skins/lampdive/icons.png.ogt +7 -0
  249. package/archetypes/roguelike/assets/skins/lampdive/skin.ogt +115 -0
  250. package/archetypes/roguelike/assets/sprites/dive.ogt +50 -0
  251. package/archetypes/roguelike/assets/sprites/dive.png +0 -0
  252. package/archetypes/roguelike/assets/sprites/dive.png.ogt +7 -0
  253. package/archetypes/roguelike/assets/sprites/glow.png +0 -0
  254. package/archetypes/roguelike/assets/sprites/glow.png.ogt +7 -0
  255. package/archetypes/roguelike/assets/strings/en.ogt +57 -0
  256. package/archetypes/roguelike/assets/strings/zh-CN.ogt +57 -0
  257. package/archetypes/roguelike/assets/tiles/tomb.ogt +31 -0
  258. package/archetypes/roguelike/assets/tiles/tomb.png +0 -0
  259. package/archetypes/roguelike/assets/tiles/tomb.png.ogt +7 -0
  260. package/archetypes/roguelike/gitattributes +22 -0
  261. package/archetypes/roguelike/gitignore +8 -0
  262. package/archetypes/roguelike/host.d.ts +46 -0
  263. package/archetypes/roguelike/package.json +18 -0
  264. package/archetypes/roguelike/project.ogt +14 -0
  265. package/archetypes/roguelike/references/metal/dive.png +0 -0
  266. package/archetypes/roguelike/references/metal/over.png +0 -0
  267. package/archetypes/roguelike/references/metal/title.png +0 -0
  268. package/archetypes/roguelike/src/art.ts +23 -0
  269. package/archetypes/roguelike/src/components.ts +169 -0
  270. package/archetypes/roguelike/src/dive.ts +144 -0
  271. package/archetypes/roguelike/src/foes.ts +174 -0
  272. package/archetypes/roguelike/src/main.ts +258 -0
  273. package/archetypes/roguelike/src/systems.ts +620 -0
  274. package/archetypes/roguelike/src/ui.ts +350 -0
  275. package/archetypes/roguelike/tests/flow.og.ts +54 -0
  276. package/archetypes/roguelike/tests/foes.og.ts +45 -0
  277. package/archetypes/roguelike/tests/frames.og.ts +32 -0
  278. package/archetypes/roguelike/tests/frames.ts +134 -0
  279. package/archetypes/roguelike/tests/lib.ts +83 -0
  280. package/archetypes/roguelike/tests/lose.og.ts +44 -0
  281. package/archetypes/roguelike/tests/pad.og.ts +54 -0
  282. package/archetypes/roguelike/tests/pause.og.ts +59 -0
  283. package/archetypes/roguelike/tests/phone.og.ts +54 -0
  284. package/archetypes/roguelike/tests/replay.og.ts +24 -0
  285. package/archetypes/roguelike/tests/win.og.ts +60 -0
  286. package/archetypes/roguelike/tools/make-assets.py +518 -0
  287. package/archetypes/roguelike/tools/oglite.py +285 -0
  288. package/archetypes/roguelike/tsconfig.json +17 -0
  289. package/archetypes/runner/.origin/setup +14 -0
  290. package/archetypes/runner/LICENSES.md +10 -0
  291. package/archetypes/runner/README.md +225 -0
  292. package/archetypes/runner/assets/audio/coin.wav +0 -0
  293. package/archetypes/runner/assets/audio/crash.wav +0 -0
  294. package/archetypes/runner/assets/audio/hold.ogt +9 -0
  295. package/archetypes/runner/assets/audio/jump.wav +0 -0
  296. package/archetypes/runner/assets/audio/start.wav +0 -0
  297. package/archetypes/runner/assets/fonts/OFL.txt +93 -0
  298. package/archetypes/runner/assets/fonts/ui.ttf +0 -0
  299. package/archetypes/runner/assets/fonts/ui.ttf.ogt +11 -0
  300. package/archetypes/runner/assets/maps/far.ogt +25 -0
  301. package/archetypes/runner/assets/maps/near.ogt +25 -0
  302. package/archetypes/runner/assets/maps/roofs.ogt +19 -0
  303. package/archetypes/runner/assets/scenes/main.ogt +35 -0
  304. package/archetypes/runner/assets/sprites/coin.ogt +11 -0
  305. package/archetypes/runner/assets/sprites/coin.png +0 -0
  306. package/archetypes/runner/assets/sprites/coin.png.ogt +7 -0
  307. package/archetypes/runner/assets/sprites/courier.ogt +32 -0
  308. package/archetypes/runner/assets/sprites/courier.png +0 -0
  309. package/archetypes/runner/assets/sprites/courier.png.ogt +7 -0
  310. package/archetypes/runner/assets/sprites/props.ogt +21 -0
  311. package/archetypes/runner/assets/sprites/props.png +0 -0
  312. package/archetypes/runner/assets/sprites/props.png.ogt +7 -0
  313. package/archetypes/runner/assets/sprites/sky.png +0 -0
  314. package/archetypes/runner/assets/sprites/sky.png.ogt +7 -0
  315. package/archetypes/runner/assets/tiles/city.ogt +18 -0
  316. package/archetypes/runner/assets/tiles/city.png +0 -0
  317. package/archetypes/runner/assets/tiles/city.png.ogt +7 -0
  318. package/archetypes/runner/gitattributes +22 -0
  319. package/archetypes/runner/gitignore +8 -0
  320. package/archetypes/runner/host.d.ts +46 -0
  321. package/archetypes/runner/package.json +18 -0
  322. package/archetypes/runner/project.ogt +18 -0
  323. package/archetypes/runner/references/metal/frames-coin.png +0 -0
  324. package/archetypes/runner/references/metal/frames-crash.png +0 -0
  325. package/archetypes/runner/references/metal/frames-title.png +0 -0
  326. package/archetypes/runner/src/art.ts +57 -0
  327. package/archetypes/runner/src/components.ts +94 -0
  328. package/archetypes/runner/src/main.ts +241 -0
  329. package/archetypes/runner/src/systems.ts +553 -0
  330. package/archetypes/runner/tests/coins.og.ts +30 -0
  331. package/archetypes/runner/tests/flow.og.ts +72 -0
  332. package/archetypes/runner/tests/frames.og.ts +37 -0
  333. package/archetypes/runner/tests/frames.ts +134 -0
  334. package/archetypes/runner/tests/jump.og.ts +44 -0
  335. package/archetypes/runner/tests/lib.ts +42 -0
  336. package/archetypes/runner/tests/records.og.ts +43 -0
  337. package/archetypes/runner/tests/replay.og.ts +36 -0
  338. package/archetypes/runner/tests/sounds.og.ts +43 -0
  339. package/archetypes/runner/tests/tune.og.ts +36 -0
  340. package/archetypes/runner/tools/make-assets.py +603 -0
  341. package/archetypes/runner/tools/oglite.py +285 -0
  342. package/archetypes/runner/tsconfig.json +17 -0
  343. package/archetypes/third-person/.origin/setup +14 -0
  344. package/archetypes/third-person/LICENSES.md +23 -0
  345. package/archetypes/third-person/README.md +249 -0
  346. package/archetypes/third-person/assets/ai/sentinel-east.ogt +69 -0
  347. package/archetypes/third-person/assets/ai/sentinel-north.ogt +69 -0
  348. package/archetypes/third-person/assets/ai/sentinel-west.ogt +69 -0
  349. package/archetypes/third-person/assets/anims/humanoid-clips.glb +0 -0
  350. package/archetypes/third-person/assets/audio/alarm.wav +0 -0
  351. package/archetypes/third-person/assets/audio/dawn.wav +0 -0
  352. package/archetypes/third-person/assets/audio/grab.wav +0 -0
  353. package/archetypes/third-person/assets/audio/ignite.wav +0 -0
  354. package/archetypes/third-person/assets/audio/jump.wav +0 -0
  355. package/archetypes/third-person/assets/audio/night.wav +0 -0
  356. package/archetypes/third-person/assets/audio/splash.wav +0 -0
  357. package/archetypes/third-person/assets/audio/step.ogt +9 -0
  358. package/archetypes/third-person/assets/audio/ui-close.ogt +9 -0
  359. package/archetypes/third-person/assets/audio/ui-error.ogt +9 -0
  360. package/archetypes/third-person/assets/audio/ui-open.ogt +9 -0
  361. package/archetypes/third-person/assets/audio/ui-press.ogt +9 -0
  362. package/archetypes/third-person/assets/audio/ui-success.ogt +9 -0
  363. package/archetypes/third-person/assets/audio/vale.wav +0 -0
  364. package/archetypes/third-person/assets/fonts/NotoSansSC-subset.ttf +0 -0
  365. package/archetypes/third-person/assets/fonts/NotoSansSC-subset.ttf.ogt +10 -0
  366. package/archetypes/third-person/assets/fonts/OFL.txt +93 -0
  367. package/archetypes/third-person/assets/fx/burst.ogt +25 -0
  368. package/archetypes/third-person/assets/fx/fire.ogt +24 -0
  369. package/archetypes/third-person/assets/fx/smoke.ogt +24 -0
  370. package/archetypes/third-person/assets/fx/splash.ogt +24 -0
  371. package/archetypes/third-person/assets/luts/teal-orange.cube +4917 -0
  372. package/archetypes/third-person/assets/models/stout.glb +0 -0
  373. package/archetypes/third-person/assets/models/strider.glb +0 -0
  374. package/archetypes/third-person/assets/models/strider.glb.ogt +9 -0
  375. package/archetypes/third-person/assets/nav/vale.ogt +43 -0
  376. package/archetypes/third-person/assets/rigs/strider.ogt +6 -0
  377. package/archetypes/third-person/assets/skins/ember/Cinzel-Bold.ttf +0 -0
  378. package/archetypes/third-person/assets/skins/ember/Cinzel-Bold.ttf.ogt +9 -0
  379. package/archetypes/third-person/assets/skins/ember/LICENSES.md +13 -0
  380. package/archetypes/third-person/assets/skins/ember/Newsreader-Medium.ttf +0 -0
  381. package/archetypes/third-person/assets/skins/ember/Newsreader-Medium.ttf.ogt +9 -0
  382. package/archetypes/third-person/assets/skins/ember/OFL.txt +94 -0
  383. package/archetypes/third-person/assets/skins/ember/atlas.png +0 -0
  384. package/archetypes/third-person/assets/skins/ember/atlas.png.ogt +7 -0
  385. package/archetypes/third-person/assets/skins/ember/icons.png +0 -0
  386. package/archetypes/third-person/assets/skins/ember/icons.png.ogt +7 -0
  387. package/archetypes/third-person/assets/skins/ember/skin.ogt +109 -0
  388. package/archetypes/third-person/assets/strings/en.ogt +47 -0
  389. package/archetypes/third-person/assets/strings/zh-CN.ogt +47 -0
  390. package/archetypes/third-person/assets/terrain/vale-control.png +0 -0
  391. package/archetypes/third-person/assets/terrain/vale.ogt +42 -0
  392. package/archetypes/third-person/assets/terrain/vale.png +0 -0
  393. package/archetypes/third-person/assets/textures/decals.png +0 -0
  394. package/archetypes/third-person/assets/textures/flame.png +0 -0
  395. package/archetypes/third-person/assets/textures/smoke.png +0 -0
  396. package/archetypes/third-person/assets/textures/spark.png +0 -0
  397. package/archetypes/third-person/assets/textures/terrain-grass.png +0 -0
  398. package/archetypes/third-person/assets/textures/terrain-path.png +0 -0
  399. package/archetypes/third-person/assets/textures/terrain-rock.png +0 -0
  400. package/archetypes/third-person/assets/textures/terrain-sand.png +0 -0
  401. package/archetypes/third-person/gitattributes +22 -0
  402. package/archetypes/third-person/gitignore +8 -0
  403. package/archetypes/third-person/host.d.ts +46 -0
  404. package/archetypes/third-person/package.json +18 -0
  405. package/archetypes/third-person/project.ogt +14 -0
  406. package/archetypes/third-person/references/metal/beacon.png +0 -0
  407. package/archetypes/third-person/references/metal/dawn.png +0 -0
  408. package/archetypes/third-person/references/metal/title.png +0 -0
  409. package/archetypes/third-person/references/webgl2/beacon.png +0 -0
  410. package/archetypes/third-person/src/anim.ts +87 -0
  411. package/archetypes/third-person/src/beacons.ts +80 -0
  412. package/archetypes/third-person/src/components.ts +148 -0
  413. package/archetypes/third-person/src/hero.ts +293 -0
  414. package/archetypes/third-person/src/main.ts +164 -0
  415. package/archetypes/third-person/src/sentinels.ts +159 -0
  416. package/archetypes/third-person/src/sound.ts +66 -0
  417. package/archetypes/third-person/src/ui.ts +451 -0
  418. package/archetypes/third-person/src/world.ts +212 -0
  419. package/archetypes/third-person/tests/flow.og.ts +70 -0
  420. package/archetypes/third-person/tests/frames.og.ts +35 -0
  421. package/archetypes/third-person/tests/frames.ts +134 -0
  422. package/archetypes/third-person/tests/hitstop.og.ts +26 -0
  423. package/archetypes/third-person/tests/lib.ts +87 -0
  424. package/archetypes/third-person/tests/lose.og.ts +44 -0
  425. package/archetypes/third-person/tests/pause.og.ts +64 -0
  426. package/archetypes/third-person/tests/phone.og.ts +65 -0
  427. package/archetypes/third-person/tests/replay.og.ts +32 -0
  428. package/archetypes/third-person/tests/restart.og.ts +28 -0
  429. package/archetypes/third-person/tests/sentinels.og.ts +48 -0
  430. package/archetypes/third-person/tests/win.og.ts +62 -0
  431. package/archetypes/third-person/tools/make-assets.py +353 -0
  432. package/archetypes/third-person/tools/oglite.py +285 -0
  433. package/archetypes/third-person/tsconfig.json +17 -0
  434. package/archetypes/topdown/.origin/setup +14 -0
  435. package/archetypes/topdown/LICENSES.md +10 -0
  436. package/archetypes/topdown/README.md +235 -0
  437. package/archetypes/topdown/assets/ai/slime.ogt +49 -0
  438. package/archetypes/topdown/assets/audio/coin.wav +0 -0
  439. package/archetypes/topdown/assets/audio/door.wav +0 -0
  440. package/archetypes/topdown/assets/audio/hit.wav +0 -0
  441. package/archetypes/topdown/assets/audio/hurt.wav +0 -0
  442. package/archetypes/topdown/assets/audio/key.wav +0 -0
  443. package/archetypes/topdown/assets/audio/step.ogt +9 -0
  444. package/archetypes/topdown/assets/fonts/OFL.txt +93 -0
  445. package/archetypes/topdown/assets/fonts/ui.ttf +0 -0
  446. package/archetypes/topdown/assets/fonts/ui.ttf.ogt +9 -0
  447. package/archetypes/topdown/assets/maps/tomb.tmj +2183 -0
  448. package/archetypes/topdown/assets/sprites/hero.ogt +58 -0
  449. package/archetypes/topdown/assets/sprites/hero.png +0 -0
  450. package/archetypes/topdown/assets/sprites/hero.png.ogt +7 -0
  451. package/archetypes/topdown/assets/sprites/items.ogt +15 -0
  452. package/archetypes/topdown/assets/sprites/items.png +0 -0
  453. package/archetypes/topdown/assets/sprites/items.png.ogt +7 -0
  454. package/archetypes/topdown/assets/sprites/slime.ogt +17 -0
  455. package/archetypes/topdown/assets/sprites/slime.png +0 -0
  456. package/archetypes/topdown/assets/sprites/slime.png.ogt +7 -0
  457. package/archetypes/topdown/assets/tiles/dungeon.ogt +65 -0
  458. package/archetypes/topdown/assets/tiles/dungeon.png +0 -0
  459. package/archetypes/topdown/assets/tiles/dungeon.png.ogt +7 -0
  460. package/archetypes/topdown/gitattributes +22 -0
  461. package/archetypes/topdown/gitignore +8 -0
  462. package/archetypes/topdown/host.d.ts +46 -0
  463. package/archetypes/topdown/package.json +18 -0
  464. package/archetypes/topdown/project.ogt +14 -0
  465. package/archetypes/topdown/references/metal/crit.png +0 -0
  466. package/archetypes/topdown/references/metal/dash.png +0 -0
  467. package/archetypes/topdown/references/metal/east.png +0 -0
  468. package/archetypes/topdown/references/metal/start.png +0 -0
  469. package/archetypes/topdown/src/art.ts +48 -0
  470. package/archetypes/topdown/src/components.ts +128 -0
  471. package/archetypes/topdown/src/main.ts +275 -0
  472. package/archetypes/topdown/src/systems.ts +503 -0
  473. package/archetypes/topdown/tests/ai.og.ts +64 -0
  474. package/archetypes/topdown/tests/combat.og.ts +72 -0
  475. package/archetypes/topdown/tests/door.og.ts +62 -0
  476. package/archetypes/topdown/tests/flee.og.ts +49 -0
  477. package/archetypes/topdown/tests/frames.og.ts +45 -0
  478. package/archetypes/topdown/tests/frames.ts +134 -0
  479. package/archetypes/topdown/tests/lib.ts +71 -0
  480. package/archetypes/topdown/tests/replay.og.ts +40 -0
  481. package/archetypes/topdown/tests/walk.og.ts +46 -0
  482. package/archetypes/topdown/tools/make-assets.py +623 -0
  483. package/archetypes/topdown/tools/oglite.py +285 -0
  484. package/archetypes/topdown/tsconfig.json +17 -0
  485. package/archetypes/tower-defense/.origin/setup +14 -0
  486. package/archetypes/tower-defense/LICENSES.md +15 -0
  487. package/archetypes/tower-defense/README.md +240 -0
  488. package/archetypes/tower-defense/assets/ai/plant.ogt +16 -0
  489. package/archetypes/tower-defense/assets/audio/clear.wav +0 -0
  490. package/archetypes/tower-defense/assets/audio/frost.wav +0 -0
  491. package/archetypes/tower-defense/assets/audio/leak.wav +0 -0
  492. package/archetypes/tower-defense/assets/audio/lost.wav +0 -0
  493. package/archetypes/tower-defense/assets/audio/night.wav +0 -0
  494. package/archetypes/tower-defense/assets/audio/plant.wav +0 -0
  495. package/archetypes/tower-defense/assets/audio/pop.wav +0 -0
  496. package/archetypes/tower-defense/assets/audio/thorn.wav +0 -0
  497. package/archetypes/tower-defense/assets/audio/ui-close.ogt +9 -0
  498. package/archetypes/tower-defense/assets/audio/ui-error.ogt +9 -0
  499. package/archetypes/tower-defense/assets/audio/ui-open.ogt +9 -0
  500. package/archetypes/tower-defense/assets/audio/ui-press.ogt +9 -0
  501. package/archetypes/tower-defense/assets/audio/ui-success.ogt +9 -0
  502. package/archetypes/tower-defense/assets/audio/wave.wav +0 -0
  503. package/archetypes/tower-defense/assets/audio/won.wav +0 -0
  504. package/archetypes/tower-defense/assets/fonts/NotoSansSC-subset.ttf +0 -0
  505. package/archetypes/tower-defense/assets/fonts/NotoSansSC-subset.ttf.ogt +10 -0
  506. package/archetypes/tower-defense/assets/fonts/OFL.txt +93 -0
  507. package/archetypes/tower-defense/assets/fx/fireflies.ogt +21 -0
  508. package/archetypes/tower-defense/assets/fx/pop.ogt +21 -0
  509. package/archetypes/tower-defense/assets/maps/garden.ogt +91 -0
  510. package/archetypes/tower-defense/assets/skins/pathguard/Fredoka-SemiBold.ttf +0 -0
  511. package/archetypes/tower-defense/assets/skins/pathguard/Fredoka-SemiBold.ttf.ogt +9 -0
  512. package/archetypes/tower-defense/assets/skins/pathguard/LICENSES.md +13 -0
  513. package/archetypes/tower-defense/assets/skins/pathguard/LilitaOne-Regular.ttf +0 -0
  514. package/archetypes/tower-defense/assets/skins/pathguard/LilitaOne-Regular.ttf.ogt +9 -0
  515. package/archetypes/tower-defense/assets/skins/pathguard/OFL.txt +94 -0
  516. package/archetypes/tower-defense/assets/skins/pathguard/atlas.png +0 -0
  517. package/archetypes/tower-defense/assets/skins/pathguard/atlas.png.ogt +7 -0
  518. package/archetypes/tower-defense/assets/skins/pathguard/icons.png +0 -0
  519. package/archetypes/tower-defense/assets/skins/pathguard/icons.png.ogt +7 -0
  520. package/archetypes/tower-defense/assets/skins/pathguard/skin.ogt +111 -0
  521. package/archetypes/tower-defense/assets/sprites/garden.ogt +66 -0
  522. package/archetypes/tower-defense/assets/sprites/garden.png +0 -0
  523. package/archetypes/tower-defense/assets/sprites/garden.png.ogt +7 -0
  524. package/archetypes/tower-defense/assets/sprites/glow.png +0 -0
  525. package/archetypes/tower-defense/assets/sprites/glow.png.ogt +7 -0
  526. package/archetypes/tower-defense/assets/sprites/ring.png +0 -0
  527. package/archetypes/tower-defense/assets/sprites/ring.png.ogt +7 -0
  528. package/archetypes/tower-defense/assets/sprites/spark.png +0 -0
  529. package/archetypes/tower-defense/assets/sprites/spark.png.ogt +7 -0
  530. package/archetypes/tower-defense/assets/strings/en.ogt +47 -0
  531. package/archetypes/tower-defense/assets/strings/zh-CN.ogt +47 -0
  532. package/archetypes/tower-defense/assets/tiles/garden.ogt +10 -0
  533. package/archetypes/tower-defense/assets/tiles/garden.png +0 -0
  534. package/archetypes/tower-defense/assets/tiles/garden.png.ogt +7 -0
  535. package/archetypes/tower-defense/gitattributes +22 -0
  536. package/archetypes/tower-defense/gitignore +8 -0
  537. package/archetypes/tower-defense/host.d.ts +46 -0
  538. package/archetypes/tower-defense/package.json +18 -0
  539. package/archetypes/tower-defense/project.ogt +14 -0
  540. package/archetypes/tower-defense/references/metal/end.png +0 -0
  541. package/archetypes/tower-defense/references/metal/title.png +0 -0
  542. package/archetypes/tower-defense/references/metal/wave.png +0 -0
  543. package/archetypes/tower-defense/src/art.ts +24 -0
  544. package/archetypes/tower-defense/src/components.ts +156 -0
  545. package/archetypes/tower-defense/src/main.ts +253 -0
  546. package/archetypes/tower-defense/src/systems.ts +658 -0
  547. package/archetypes/tower-defense/src/ui.ts +382 -0
  548. package/archetypes/tower-defense/tests/flow.og.ts +56 -0
  549. package/archetypes/tower-defense/tests/frames.og.ts +31 -0
  550. package/archetypes/tower-defense/tests/frames.ts +134 -0
  551. package/archetypes/tower-defense/tests/lib.ts +81 -0
  552. package/archetypes/tower-defense/tests/lose.og.ts +40 -0
  553. package/archetypes/tower-defense/tests/maze.og.ts +53 -0
  554. package/archetypes/tower-defense/tests/pad.og.ts +41 -0
  555. package/archetypes/tower-defense/tests/pause.og.ts +59 -0
  556. package/archetypes/tower-defense/tests/phone.og.ts +49 -0
  557. package/archetypes/tower-defense/tests/replay.og.ts +28 -0
  558. package/archetypes/tower-defense/tests/win.og.ts +58 -0
  559. package/archetypes/tower-defense/tools/make-assets.py +640 -0
  560. package/archetypes/tower-defense/tools/oglite.py +285 -0
  561. package/archetypes/tower-defense/tsconfig.json +17 -0
  562. package/bin/create.ts +503 -0
  563. package/looks/catalogue.json +1871 -0
  564. package/package.json +31 -4
  565. package/template/.origin/setup +14 -0
  566. package/template/LICENSES.md +23 -0
  567. package/template/README.md +37 -0
  568. package/template/assets/ai/guard.ogt +48 -0
  569. package/template/assets/audio/blip.wav +0 -0
  570. package/template/assets/audio/click.ogt +9 -0
  571. package/template/assets/fonts/NotoSansSC-Regular-subset.ttf +0 -0
  572. package/template/assets/fonts/NotoSansSC-Regular-subset.ttf.ogt +12 -0
  573. package/template/assets/fonts/OFL.txt +93 -0
  574. package/template/assets/looks/origin-game.ogt +12 -0
  575. package/template/assets/models/dropship.glb +0 -0
  576. package/template/assets/models/walker.glb +0 -0
  577. package/template/assets/nav/yard.ogt +27 -0
  578. package/template/assets/scenes/main.ogt +34 -0
  579. package/template/assets/strings/en.ogt +14 -0
  580. package/template/assets/textures/stone.png +0 -0
  581. package/template/assets/textures/stone_n.png +0 -0
  582. package/template/assets/textures/stone_n.png.ogt +7 -0
  583. package/template/gitattributes +22 -0
  584. package/template/gitignore +8 -0
  585. package/template/package.json +18 -0
  586. package/template/project.ogt +25 -0
  587. package/template/src/main.ts +246 -0
  588. package/template/tests/guard.og.ts +67 -0
  589. package/template/tests/smoke.og.ts +43 -0
  590. 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,10 @@
1
+ # Asset licences
2
+
3
+ | File | Licence | Origin |
4
+ |---|---|---|
5
+ | `assets/sprites/*.png`, `assets/sprites/*.ogt` | CC0 1.0 | self-made: the courier, coin, props and sky are drawn texel by texel by `tools/make-assets.py` (standard library only, deterministic), with their flipbook sheets and import settings |
6
+ | `assets/tiles/city.png`, `assets/tiles/*.ogt` | CC0 1.0 | self-made: the city tileset, same script |
7
+ | `assets/maps/*.ogt` | CC0 1.0 | self-made: the far, near and roof tilemaps, same script |
8
+ | `assets/audio/*.wav` | CC0 1.0 | self-made: synthesised tones and noise, same script |
9
+ | `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` |
10
+ | `references/*/*.png` | CC0 1.0 | frames of this game recorded by `tests/frames.og.ts` |
@@ -0,0 +1,225 @@
1
+ # Rooftop Run — the runner archetype (2D)
2
+
3
+ A courier runs the night roofs on her own; the player decides every jump. A
4
+ tap is a hop that clears a crate, a hold is a full jump that clears a fence,
5
+ and coins hang where the arcs go. The run speeds up until a crash ends it;
6
+ the score is the distance plus the coins.
7
+
8
+ 屋顶快跑:信使在夜晚的屋顶上自己奔跑,每一次起跳由你决定。点按小跳越过木箱,按住高跳越过路障,金币挂在跳跃的弧线上。速度越来越快,直到撞上障碍。
9
+
10
+ This is a complete Origin Engine project: `og run .` plays it headless,
11
+ `og build .` makes the play page, `og test .` runs its playtests. It
12
+ replaces the platform's Godot Discover runner (Skyline Post) and keeps its
13
+ feel (one thumb, tap for a hop, hold for a jump, pace that ramps), not its
14
+ code, art or route.
15
+
16
+ ```sh
17
+ og cook . # assets/ into cooked/ (og run and og build cook too)
18
+ og run . --headless --commands "0.5:key_down:Space;0.55:key_up:Space;3:screenshot:play.png;3.1:quit"
19
+ og test . # tests/*.og.ts through og run --headless --commands
20
+ og build . # dist/: the play page for the browser
21
+ ```
22
+
23
+ ## What it demonstrates, and the skills it exercises
24
+
25
+ A one-button 2D game end to end: og.PlatformerController with its designer
26
+ units in a `Tuning` resource and its CharacterEvents driving the take-off
27
+ stretch and landing squash (og-game §13; og-feel §5, §12), a scrolling world
28
+ of flipbooks and parallax tile layers (og-game §8; og-feel §9–§11), coins
29
+ with floating text, hit stop, shake and kick on a crash (og-feel §3, §4,
30
+ §7), every action heard through one `Voices` system (og-audio §1), the best
31
+ score and a leaderboard through og.platform's requests answered later
32
+ (og-platform-sdk §1–§4), and playtests for jumps, tuning, records and a
33
+ replay to one hash (og-build §1, §3). `og polish .` (2026-10-19): feel 99
34
+ (taste n/a: the HUD is screen-space text, not og.ui).
35
+
36
+
37
+ ## Rules
38
+
39
+ - **Title.** The city scrolls slowly; the first press (Space, ArrowUp, W, a
40
+ click or a touch) starts the run. That press does not also jump.
41
+ - **Running.** The courier stays at x = −5 and the world scrolls left at the
42
+ run speed, which starts at `Tuning.speed` and ramps by `Tuning.speedRamp`
43
+ up to `Tuning.speedMax`. Every `Tuning.spawnInterval` seconds (×0.85–1.25
44
+ from the dice) a pattern enters from the right: a crate, a crate under an
45
+ arc of coins, a line of coins, and after 60 m a fence or a fence under a
46
+ high coin, and after 150 m two crates in a row.
47
+ - **Jumping.** The courier's body is an `og.PlatformerController` that
48
+ never runs (the world scrolls past it) on a static roof collider: a press
49
+ jumps to `Tuning.jumpHeight` in `Tuning.timeToApex`, hanging a little at
50
+ the top (`apexGravity`) and coming down a little faster (`fallGravity`);
51
+ releasing while rising multiplies gravity by `jumpCut`. A two-tick tap is
52
+ the shortest hop (1.30 m) and clears a crate (0.7 m); only a full jump
53
+ (2.12 m) clears a fence (1.55 m). A press up to 0.1 s before landing jumps
54
+ on landing (the controller's buffer), and one 0.08 s after running off an
55
+ edge still jumps (its coyote time).
56
+ - **Score.** `floor(distance) + coins × Tuning.coinValue`. Touching a crate or
57
+ a fence ends the round; the best score is kept for the session.
58
+ - **Game over.** The card holds for 30 ticks, then a press starts the next
59
+ round at once.
60
+
61
+ Everything is deterministic from the project seed (`project.ogt`, or
62
+ `og run --seed`): the patterns come from `og.Rng`, the clock is the fixed
63
+ tick, and the feel (tweens, flipbooks, hit stop, shake, floating text,
64
+ afterimages) is engine world state, so the same script gives the same world
65
+ hash on the native and the web host (`tests/replay.og.ts` runs it twice).
66
+
67
+ ## The world
68
+
69
+ A night city in pixel art: every sheet is drawn texel by texel by
70
+ `tools/make-assets.py`, imported as `kind pixel` (lossless, sampled
71
+ nearest) and outlined in the brand ink `#14161b` so the silhouettes read
72
+ on the dark sky. Layers, back to front:
73
+
74
+ | Layer | What | Drawn by |
75
+ |---|---|---|
76
+ | −40 | the sky's colour bands | `og.Sprite` over `sprites/sky.png` |
77
+ | −38, −36 | the moon, three clouds (drifting at 0.06 of the speed) | `og.Sprite` + `og.Flipbook` (`sprites/props.ogt`) |
78
+ | −30 | the far skyline, antenna lights blinking | `og.Tilemap` of `maps/far.ogt`, parallax 0.15 |
79
+ | −20 | the near buildings, warm windows (one goes on and off), a neon sign, a water tank | `og.Tilemap` of `maps/near.ogt`, parallax 0.45 |
80
+ | −10 | the roof the courier runs on | `og.Tilemap` of `maps/roofs.ogt`, parallax 1 |
81
+ | 0, 1 | crates and fences; coins (a 6-frame turn) and dust puffs | `og.Sprite` + `og.Flipbook` |
82
+ | 2 | the courier (idle, run, jump, fall, crash) | `og.Sprite` + `og.Flipbook` (`sprites/courier.ogt`) + `og.Afterimage` |
83
+ | 10, 100 | the HUD; "+10" | `og.render.text`; `og.render.floatingText` |
84
+
85
+ The three city strips are text tilemaps (`.ogt` rows of legend
86
+ characters: the script writes them, a person can edit them by hand) over one
87
+ tileset (`tiles/city.ogt`, with its animated tiles) and draw with `repeat
88
+ x`; the camera stays still, so each strip's entity scrolls left at the run
89
+ speed times its parallax and jumps right by its own width, seamlessly. The
90
+ crates, fences, coins and dust are pools (4, 3, 16 and 4) parked at
91
+ x = −1000 until a pattern or a footfall puts them in play.
92
+
93
+ | Component | On | What it holds |
94
+ |---|---|---|
95
+ | `Actor` | every row | `kind` (sky, moon, cloud, city, dust, runner, crate, fence, coin), `active` (collides), the hit box `w`×`h`, `parallax` (the share of the run speed a row scrolls at), `wrap` (the span scenery jumps right by), `vy` |
96
+ | `Run` | every row; **the runner's is the authority** | `phase` (0 title, 1 running, 2 over), `phaseTicks`, `speed`, `distance`, `coins`, `score`, `best`, `rounds`, `spawnIn`, and the body's `grounded` (copied from the controller), `startHeld` (the starting press is not a jump) and `kick` (a speed Director or Collide gave the body) |
97
+ | `Tuning` | every row; **the runner's is the authority** | the tunables below |
98
+ | `Hud` | the runner only | the font handle and the visible area the HUD lays out in |
99
+
100
+ The runner's position is its feet (the sheet's pivot is `0.5 0`), so a
101
+ squash keeps them on the roof; its hit box is centred 0.8125 m above them.
102
+
103
+ Why `Run` and `Tuning` sit on every row: a system sees exactly one query,
104
+ the AND of what it declares, and inside a system the engine reaches no other
105
+ entity and no game resource yet. So the systems that move obstacles and end
106
+ the round must find the run's state on the same rows as the obstacles. The
107
+ other rows' copies keep their defaults and nothing reads them. When the
108
+ engine lets a system read another entity or a resource, `Run` and `Tuning`
109
+ become a resource or the runner's alone and the systems keep their shape.
110
+
111
+ ## Systems (in tick order)
112
+
113
+ | System | Reads | Writes | Job |
114
+ |---|---|---|---|
115
+ | `Director` | `og.Input`, `Tuning` | `Run`, `Actor`, `og.Transform`, `og.Sprite` | phases; the speed ramp, distance and score; a new round (pools retired, the courier stood up); a press during the card's hold answered by the hold tick |
116
+ | `Jump` | `og.Input`, `Tuning`, `og.CharacterEvent` | `Run`, `Actor`, `og.PlatformerController` | the controller's jump held while the press is, its tunables from `Tuning`; its take-off (a stretch and the sound) and landing (a squash) events |
117
+ | `Scroll` | `Run` | `Actor`, `og.Transform` | everything left at speed × parallax; scenery wraps by its span; pooled rows retire past x = −13 |
118
+ | `Spawn` | `Tuning` | `og.Rng`, `Run`, `Actor`, `og.Transform`, `og.Sprite` | the next pattern at x = 13 from the dice |
119
+ | `Collide` | `og.Transform`, `Tuning` | `Run`, `Actor` | coins collected ("+10" and the coin's pop), crashes (the crash's feel), the best score |
120
+ | `Dust` | `og.FlipbookEvent`, `Run` | `Actor`, `og.Transform` | a dust puff at the feet on each `step` event of the run clip |
121
+ | `Animate` | `Run`, `Actor`, `Tuning` | `og.Flipbook`, `og.Afterimage` | the courier's clip from the phase and the body, the run clip's pace from the speed, the afterimage near top speed |
122
+ | `Hud` | `Run`, `Hud`, `Tuning` | — | the score line, the title card and the game-over card (`og.render.text`) |
123
+
124
+ Motion reads `Time.scaledDt`, so a hit stop freezes the world while the
125
+ camera still shakes. Spawning and retiring at fixed x (beyond the widest
126
+ view) keeps the play surface's shape out of the simulation: a phone and a
127
+ desktop see the same obstacles at the same ticks.
128
+
129
+ ## Feel (E4)
130
+
131
+ | Moment | What happens | Where |
132
+ |---|---|---|
133
+ | running | an 8-frame run at 14 fps, faster with the speed (×0.8–1.6); `step` events on the footfalls kick up dust | `sprites/courier.ogt`, `Animate`, `Dust` |
134
+ | take-off | stretch (0.78, 1.28), then the jump frame | `og.tween.squash` in `Jump` |
135
+ | landing | squash (1.3, 0.72), recovering with `backOut` | `og.tween.squash` in `Jump` |
136
+ | a coin | "+10" pops and rises; the coin grows, lifts and fades | `og.render.floatingText`, `og.tween.parallel` in `Collide` |
137
+ | a crash | 8 ticks of hit stop, shake 0.5, a kick of the view, the courier knocked back 0.9 m and up, flashing red, the crash clip played once | `og.time.hitStop`, `og.camera.shake`/`kick`, tweens in `Collide` |
138
+ | top speed | four mint ghosts trail the courier | `og.Afterimage` in `Animate` |
139
+
140
+ The numbers are `FEEL` in `src/systems.ts`. None of them changes a rule:
141
+ the playtests below hold with any of them.
142
+
143
+ ## Tunables (`Tuning`, on the runner)
144
+
145
+ | Field | Default | Range | Unit | What it changes |
146
+ |---|---|---|---|---|
147
+ | `speed` | 6 | 3–12 | m/s | the pace a round starts at |
148
+ | `speedRamp` | 0.12 | 0–1 | m/s² | how fast the pace rises (the cap after 50 s) |
149
+ | `speedMax` | 12 | 4–20 | m/s | the top pace (and where the afterimage shows) |
150
+ | `jumpHeight` | 2 | 0.5–6 | m | a held jump's height |
151
+ | `timeToApex` | 0.333 | 0.15–1 | s | how long it takes to peak (with the height: gravity and take-off speed) |
152
+ | `jumpCut` | 1.8 | 1–6 | × | gravity while rising with the press released: the hop's height |
153
+ | `apexGravity` | 0.75 | 0.2–1 | × | gravity near the top of a held jump: the hang |
154
+ | `fallGravity` | 1.15 | 1–3 | × | gravity on the way down: the landing's snap |
155
+ | `spawnInterval` | 1.3 | 0.5–60 | s | the gap between patterns |
156
+ | `coinValue` | 10 | 0–100 | points | what a coin adds (and the floating text shows) |
157
+
158
+ They are written in `assets/scenes/main.ogt` (the runner's `Tuning` block)
159
+ and live with `set:runner.Tuning.<field>=<value>` from the command channel
160
+ or Tune. The hop and jump heights above were measured with `get:runner.og.Transform.position`
161
+ through a tap and a hold; `tests/jump.og.ts` holds them against the obstacles.
162
+
163
+ ## What a Maker changes first
164
+
165
+ 1. **Feel**: `jumpHeight`, `timeToApex`, `jumpCut`, `apexGravity` and `fallGravity` in the scene's `Tuning`.
166
+ Keep the hop below the fence and above the crate (`tests/jump.og.ts`
167
+ checks exactly that). The juice is `FEEL` in `src/systems.ts`.
168
+ 2. **Pace**: `speed`, `speedRamp`, `speedMax`, `spawnInterval`.
169
+ 3. **What comes**: `placePattern` and the `top` gate in `Spawn`
170
+ (`src/systems.ts`): add a pattern, change when fences appear.
171
+ 4. **Look**: the pixel art and the city in `tools/make-assets.py`
172
+ (`courier`, `run_frame`, `tile`, `far_rows`, `near_rows`), then
173
+ `python3 tools/make-assets.py && og cook .`. A new courier clip goes in
174
+ `COURIER_OGT` there and `COURIER` in `src/art.ts` (which checks the
175
+ order). Re-record the reference frames afterwards (below).
176
+ 5. **Words**: the HUD strings in `Hud`. A CJK character must be in `CHARS`
177
+ of `tools/make-assets.py` (it writes `assets/fonts/ui.ttf.ogt`).
178
+
179
+ ## Commands (for scripts and agents)
180
+
181
+ | Action | Does |
182
+ |---|---|
183
+ | `place:<crate\|fence\|coin>:<x>[:<y>]` | puts a pooled obstacle or coin in play at x (y defaults to its resting height) |
184
+ | core actions | `key_down:Space`/`key_up:Space` (or `touch_start`/`touch_end`) jump; `set:runner.Tuning.<field>=<v>` tunes; `dump_entity:runner` shows `Run` |
185
+
186
+ `facts` (the probe's `state()`) reports `phase`, `score`, `coins`,
187
+ `distance`, `speed`, `best` and `rounds`.
188
+
189
+ ## Playtests (`og test .`)
190
+
191
+ | File | Proves |
192
+ |---|---|
193
+ | `tests/flow.og.ts` | title → a press starts → an untouched crate ends the round → the card holds → a press starts round two from zero, best kept; every system matches its rows |
194
+ | `tests/coins.og.ts` | a coin in reach is collected and adds `coinValue`; one hung at 3.2 m passes over a standing runner |
195
+ | `tests/jump.og.ts` | a full jump clears a crate and a fence; a hop clears a crate and crashes into a fence |
196
+ | `tests/tune.og.ts` | `set` writes `Tuning`: the start speed and the jump height follow |
197
+ | `tests/frames.og.ts` | the title, a coin's pickup ("+10", the pop, dust) and the crash inside its hit stop (red flash, shake) match `references/<tier>/frames-*.png` under og-tests' tolerance (`tests/frames.ts`) |
198
+ | `tests/replay.og.ts` | the same script of jumps, coins, a crash and a second round, run twice in fresh processes, ends on one world hash |
199
+
200
+ Each one fails when the behaviour it names is broken (checked by breaking
201
+ coin collection, the hop's minimum hold, the card's hold, the coin's
202
+ floating text, the crash flash through the hit stop and the determinism of
203
+ the dust). After a deliberate change to the look, re-record the frames:
204
+ `OG_FX_CAPTURE=1 og test .` (a tier without its own references compares
205
+ with `metal` and says so).
206
+
207
+ ## Assets
208
+
209
+ `tools/make-assets.py` regenerates every asset byte for byte (sheets,
210
+ tileset, maps, sounds, the font subset); `LICENSES.md` lists them. The
211
+ sounds play through one `og.AudioSource` voice each: Director (a round
212
+ starts, and a quiet tick, og sfx's `click` preset in `assets/audio/hold.ogt`,
213
+ for a press while the game-over card holds), Jump and Collide (a coin, a
214
+ crash) set bits of the `Sounds` resource and Voices plays each once
215
+ (`og polish` found the archetype silent, no input answered by a sound;
216
+ tests/sounds.og.ts holds it, and tests/flow.og.ts the held press's tick).
217
+
218
+ ## Known limits
219
+
220
+ - Systems cannot read other entities (hence `Run` and `Tuning` on every
221
+ row; a game resource they declare, `Sounds`, they can) and cannot spawn (hence the pools, the dust's
222
+ included); the camera stays still and the world scrolls.
223
+ - The view's size is read once in `start`; on the web the renderer is not
224
+ attached yet then, so the layout assumes 16:9 and a portrait phone sees a
225
+ narrow slice of the roofs.
@@ -0,0 +1,9 @@
1
+ type sfx
2
+ version 1
3
+ ---
4
+ # a tiny tick: a press while the game-over card holds is heard, not ignored.
5
+ preset "click"
6
+ seed 0
7
+ pitch 1
8
+ length 1
9
+ volume 1
@@ -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.