@nayan-ui/games 1.20.0 → 1.21.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 (552) hide show
  1. package/lib/module/games/arrows/Arrows.js +1 -1
  2. package/lib/module/games/arrows/ArrowsScene.js +1 -1
  3. package/lib/module/games/balloon-blaster/BalloonBlaster.js +1 -1
  4. package/lib/module/games/balloon-blaster/BalloonBlasterScene.js +1 -1
  5. package/lib/module/games/bike-racing/BikeMeshes.js +1 -1
  6. package/lib/module/games/bike-racing/BikeRacing.js +1 -1
  7. package/lib/module/games/bike-racing/BikeRacingConstants.js +1 -1
  8. package/lib/module/games/bike-racing/BikeRacingScene.js +1 -1
  9. package/lib/module/games/block-blast/BlockBlast.js +1 -1
  10. package/lib/module/games/block-blast/BlockBlastScene.js +1 -1
  11. package/lib/module/games/block-breaker/BlockBreaker.js +1 -1
  12. package/lib/module/games/block-breaker/BlockBreakerScene.js +1 -1
  13. package/lib/module/games/bluk/Bluk.js +1 -1
  14. package/lib/module/games/bluk/BlukScene.js +1 -1
  15. package/lib/module/games/bubble-shooter/BubbleShooter.js +1 -1
  16. package/lib/module/games/bubble-shooter/BubbleShooterScene.js +1 -1
  17. package/lib/module/games/candy-crush/CandyCrush.js +1 -1
  18. package/lib/module/games/candy-crush/CandyCrushScene.js +1 -1
  19. package/lib/module/games/car-racing/CarMeshes.js +1 -1
  20. package/lib/module/games/car-racing/CarRacing.js +1 -1
  21. package/lib/module/games/car-racing/CarRacingScene.js +1 -1
  22. package/lib/module/games/chameleon-run/ChameleonRun.js +1 -1
  23. package/lib/module/games/chameleon-run/ChameleonRunBackdrop.js +1 -1
  24. package/lib/module/games/chameleon-run/ChameleonRunMeshes.js +1 -1
  25. package/lib/module/games/checkers/Checkers.js +1 -1
  26. package/lib/module/games/checkers/CheckersScene.js +1 -1
  27. package/lib/module/games/color-switch/ColorSwitch.js +1 -1
  28. package/lib/module/games/color-switch/ColorSwitchScene.js +1 -1
  29. package/lib/module/games/colors-sort/ColorsSort.js +1 -1
  30. package/lib/module/games/colors-sort/ColorsSortScene.js +1 -1
  31. package/lib/module/games/connect-em-all/ConnectEmAll.js +1 -1
  32. package/lib/module/games/connect-em-all/ConnectEmAllScene.js +1 -1
  33. package/lib/module/games/crossy-road/CrossyRoad.js +1 -1
  34. package/lib/module/games/crossy-road/CrossyRoadMeshes.js +1 -1
  35. package/lib/module/games/crossy-road/CrossyRoadPerson.js +1 -1
  36. package/lib/module/games/dino-jump/DinoJump.js +1 -1
  37. package/lib/module/games/dino-jump/DinoJumpScene.js +1 -1
  38. package/lib/module/games/dots-and-boxes/DotsAndBoxes.js +1 -1
  39. package/lib/module/games/dots-and-boxes/DotsAndBoxesScene.js +1 -1
  40. package/lib/module/games/falling-sticks/FallingSticks.js +1 -1
  41. package/lib/module/games/falling-sticks/FallingSticksScene.js +1 -1
  42. package/lib/module/games/find-different-number/FindDifferentNumber.js +1 -1
  43. package/lib/module/games/find-different-number/FindDifferentNumberScene.js +1 -1
  44. package/lib/module/games/flappy-bird/FlappyBird.js +1 -1
  45. package/lib/module/games/flappy-bird/FlappyBirdScene.js +1 -1
  46. package/lib/module/games/fruit-merger/FruitMerger.js +1 -1
  47. package/lib/module/games/fruit-merger/FruitMergerScene.js +1 -1
  48. package/lib/module/games/fruit-ninja/FruitNinja.js +1 -1
  49. package/lib/module/games/fruit-ninja/FruitNinjaScene.js +1 -1
  50. package/lib/module/games/fruit-ninja/FruitNinjaWorld.js +1 -1
  51. package/lib/module/games/game-2048/Game2048.js +1 -1
  52. package/lib/module/games/game-2048/Game2048Scene.js +1 -1
  53. package/lib/module/games/knife-hit/KnifeHit.js +1 -1
  54. package/lib/module/games/knife-hit/KnifeHitScene.js +1 -1
  55. package/lib/module/games/ludo-king/LudoKing.js +1 -1
  56. package/lib/module/games/ludo-king/LudoKingScene.js +1 -1
  57. package/lib/module/games/maze-runner/MazeRunner.js +1 -1
  58. package/lib/module/games/maze-runner/MazeRunnerScene.js +1 -1
  59. package/lib/module/games/memory-match/MemoryMatch.js +1 -1
  60. package/lib/module/games/memory-match/MemoryMatchScene.js +1 -1
  61. package/lib/module/games/mine-sweeper/MineSweeper.js +1 -1
  62. package/lib/module/games/mine-sweeper/MineSweeperScene.js +1 -1
  63. package/lib/module/games/mob-control/MobControl.js +1 -1
  64. package/lib/module/games/mob-control/MobControlGame.js +1 -1
  65. package/lib/module/games/mob-control/MobControlMeshes.js +1 -1
  66. package/lib/module/games/mob-control/MobControlRenderer.js +1 -1
  67. package/lib/module/games/mob-control/MobControlRules.js +1 -1
  68. package/lib/module/games/mob-control/MobControlScene.js +1 -1
  69. package/lib/module/games/nuts-and-bolts/NutsAndBolts.js +1 -1
  70. package/lib/module/games/nuts-and-bolts/NutsAndBoltsScene.js +1 -1
  71. package/lib/module/games/pac-man/PacMan.js +1 -1
  72. package/lib/module/games/pac-man/PacManGame.js +1 -1
  73. package/lib/module/games/pac-man/PacManScene.js +1 -1
  74. package/lib/module/games/paper-io/PaperIo.js +1 -1
  75. package/lib/module/games/paper-io/PaperIoMeshes.js +1 -1
  76. package/lib/module/games/paper-io/PaperIoScene.js +1 -1
  77. package/lib/module/games/penguin-run/PenguinMeshes.js +1 -1
  78. package/lib/module/games/penguin-run/PenguinRun.js +1 -1
  79. package/lib/module/games/penguin-run/PenguinRunScene.js +1 -1
  80. package/lib/module/games/perfect-circle/PerfectCircle.js +1 -1
  81. package/lib/module/games/perfect-circle/PerfectCircleScene.js +1 -1
  82. package/lib/module/games/pipe-connect/PipeConnect.js +1 -1
  83. package/lib/module/games/pipe-connect/PipeConnectScene.js +1 -1
  84. package/lib/module/games/play-with-tua/PlayWithTua.js +1 -1
  85. package/lib/module/games/popit-fidget/PopitFidget.js +1 -1
  86. package/lib/module/games/popit-fidget/PopitFidgetScene.js +1 -1
  87. package/lib/module/games/reversi/Reversi.js +1 -1
  88. package/lib/module/games/reversi/ReversiScene.js +1 -1
  89. package/lib/module/games/search-grid/SearchGrid.js +1 -1
  90. package/lib/module/games/search-grid/SearchGridScene.js +1 -1
  91. package/lib/module/games/shared/BackdropCard.js +1 -1
  92. package/lib/module/games/shared/EngineBackdrop.js +1 -1
  93. package/lib/module/games/shared/EngineBlasts.js +1 -1
  94. package/lib/module/games/shared/EngineBlocks.js +1 -1
  95. package/lib/module/games/shared/EngineDice.js +1 -1
  96. package/lib/module/games/shared/EngineFruits.js +1 -1
  97. package/lib/module/games/shared/EngineGameLoader.js +1 -1
  98. package/lib/module/games/shared/EngineGameScreen.js +1 -1
  99. package/lib/module/games/shared/EngineGlyphs.js +1 -1
  100. package/lib/module/games/shared/EngineHud.js +1 -1
  101. package/lib/module/games/shared/EngineMeadow.js +1 -1
  102. package/lib/module/games/shared/EngineTouchSurface.js +1 -1
  103. package/lib/module/games/shared/GameActivity.js +1 -1
  104. package/lib/module/games/shared/GameLoading.js +1 -1
  105. package/lib/module/games/shared/GameLoadingTransition.js +1 -1
  106. package/lib/module/games/sliding-numbers/SlidingNumbers.js +1 -1
  107. package/lib/module/games/sliding-numbers/SlidingNumbersScene.js +1 -1
  108. package/lib/module/games/snake-3d/Snake3D.js +1 -1
  109. package/lib/module/games/snake-3d/Snake3DScene.js +1 -1
  110. package/lib/module/games/snakes-and-ladders/SnakesAndLadders.js +1 -1
  111. package/lib/module/games/snakes-and-ladders/SnakesAndLaddersScene.js +1 -1
  112. package/lib/module/games/space-fighter/SpaceFighter.js +1 -1
  113. package/lib/module/games/space-fighter/SpaceFighterScene.js +1 -1
  114. package/lib/module/games/spider-solitaire/SpiderSolitaire.js +1 -1
  115. package/lib/module/games/spider-solitaire/SpiderSolitaireScene.js +1 -1
  116. package/lib/module/games/stack-tower/StackTower.js +1 -1
  117. package/lib/module/games/stack-tower/StackTowerScene.js +1 -1
  118. package/lib/module/games/sudoku/Sudoku.js +1 -1
  119. package/lib/module/games/sudoku/SudokuScene.js +1 -1
  120. package/lib/module/games/tangram/Tangram.js +1 -1
  121. package/lib/module/games/tangram/TangramScene.js +1 -1
  122. package/lib/module/games/tank-1990/Tank1990.js +1 -1
  123. package/lib/module/games/tank-1990/Tank1990Scene.js +1 -1
  124. package/lib/module/games/tic-tac-toe/TicTacToe.js +1 -1
  125. package/lib/module/games/tic-tac-toe/TicTacToeScene.js +1 -1
  126. package/lib/module/games/tile-home/TileHome.js +1 -1
  127. package/lib/module/games/tile-home/TileHomeScene.js +1 -1
  128. package/lib/module/games/treasure-hunt/TreasureHunt.js +1 -1
  129. package/lib/module/games/treasure-hunt/TreasureHuntConstants.js +1 -1
  130. package/lib/module/games/treasure-hunt/TreasureHuntModel.js +1 -1
  131. package/lib/module/games/treasure-hunt/TreasureHuntScene.js +1 -1
  132. package/lib/module/games/whack-a-mole/WhackAMole.js +1 -1
  133. package/lib/module/games/whack-a-mole/WhackAMoleScene.js +1 -1
  134. package/lib/module/helpers/GameSettingsModal.js +1 -1
  135. package/lib/module/helpers/GameTheme.js +1 -1
  136. package/package.json +1 -2
  137. package/src/assets/fonts/Inter-SemiBold.ttf +0 -0
  138. package/src/assets/models/explorer/explorer.glb +0 -0
  139. package/src/assets/models/explorer/params.json +0 -51
  140. package/src/assets/models/explorer/source.json +0 -222
  141. package/src/assets/models/play-with-tua/play-with-tua.glb +0 -0
  142. package/src/assets/models/play-with-tua/sources.json +0 -141
  143. package/src/assets/sfx/balloon_pop.wav +0 -0
  144. package/src/assets/sfx/blocked.wav +0 -0
  145. package/src/assets/sfx/boing.wav +0 -0
  146. package/src/assets/sfx/bonus.wav +0 -0
  147. package/src/assets/sfx/boom.wav +0 -0
  148. package/src/assets/sfx/bump.wav +0 -0
  149. package/src/assets/sfx/cannon.wav +0 -0
  150. package/src/assets/sfx/capture.wav +0 -0
  151. package/src/assets/sfx/card_flip.wav +0 -0
  152. package/src/assets/sfx/card_place.wav +0 -0
  153. package/src/assets/sfx/catch.wav +0 -0
  154. package/src/assets/sfx/chime.wav +0 -0
  155. package/src/assets/sfx/chomp.wav +0 -0
  156. package/src/assets/sfx/chomp_alt.wav +0 -0
  157. package/src/assets/sfx/clack.wav +0 -0
  158. package/src/assets/sfx/clang.wav +0 -0
  159. package/src/assets/sfx/clash.wav +0 -0
  160. package/src/assets/sfx/click.wav +0 -0
  161. package/src/assets/sfx/coin.wav +0 -0
  162. package/src/assets/sfx/combo.wav +0 -0
  163. package/src/assets/sfx/crash.wav +0 -0
  164. package/src/assets/sfx/crunch.wav +0 -0
  165. package/src/assets/sfx/dance.wav +0 -0
  166. package/src/assets/sfx/deselect.wav +0 -0
  167. package/src/assets/sfx/dice_roll.wav +0 -0
  168. package/src/assets/sfx/die.wav +0 -0
  169. package/src/assets/sfx/draw.wav +0 -0
  170. package/src/assets/sfx/drop.wav +0 -0
  171. package/src/assets/sfx/eat.wav +0 -0
  172. package/src/assets/sfx/engine.wav +0 -0
  173. package/src/assets/sfx/error.wav +0 -0
  174. package/src/assets/sfx/flag.wav +0 -0
  175. package/src/assets/sfx/flap.wav +0 -0
  176. package/src/assets/sfx/flip_disc.wav +0 -0
  177. package/src/assets/sfx/footstep_run.wav +0 -0
  178. package/src/assets/sfx/footstep_walk.wav +0 -0
  179. package/src/assets/sfx/game_over.wav +0 -0
  180. package/src/assets/sfx/gate.wav +0 -0
  181. package/src/assets/sfx/hit.wav +0 -0
  182. package/src/assets/sfx/hop.wav +0 -0
  183. package/src/assets/sfx/hurt.wav +0 -0
  184. package/src/assets/sfx/invalid.wav +0 -0
  185. package/src/assets/sfx/jump.wav +0 -0
  186. package/src/assets/sfx/ladder.wav +0 -0
  187. package/src/assets/sfx/land.wav +0 -0
  188. package/src/assets/sfx/laugh.wav +0 -0
  189. package/src/assets/sfx/lose.wav +0 -0
  190. package/src/assets/sfx/merge.wav +0 -0
  191. package/src/assets/sfx/miss.wav +0 -0
  192. package/src/assets/sfx/nitro.wav +0 -0
  193. package/src/assets/sfx/pew.wav +0 -0
  194. package/src/assets/sfx/place.wav +0 -0
  195. package/src/assets/sfx/pling.wav +0 -0
  196. package/src/assets/sfx/point.wav +0 -0
  197. package/src/assets/sfx/pop.wav +0 -0
  198. package/src/assets/sfx/pop_soft.wav +0 -0
  199. package/src/assets/sfx/power_up.wav +0 -0
  200. package/src/assets/sfx/reveal.wav +0 -0
  201. package/src/assets/sfx/robot.wav +0 -0
  202. package/src/assets/sfx/rotate.wav +0 -0
  203. package/src/assets/sfx/run_steps.wav +0 -0
  204. package/src/assets/sfx/select.wav +0 -0
  205. package/src/assets/sfx/shuffle.wav +0 -0
  206. package/src/assets/sfx/six.wav +0 -0
  207. package/src/assets/sfx/slice.wav +0 -0
  208. package/src/assets/sfx/slide.wav +0 -0
  209. package/src/assets/sfx/snake.wav +0 -0
  210. package/src/assets/sfx/snap.wav +0 -0
  211. package/src/assets/sfx/splash.wav +0 -0
  212. package/src/assets/sfx/star.wav +0 -0
  213. package/src/assets/sfx/start.wav +0 -0
  214. package/src/assets/sfx/swoosh.wav +0 -0
  215. package/src/assets/sfx/tap.wav +0 -0
  216. package/src/assets/sfx/thud.wav +0 -0
  217. package/src/assets/sfx/thunk.wav +0 -0
  218. package/src/assets/sfx/tick.wav +0 -0
  219. package/src/assets/sfx/time_up.wav +0 -0
  220. package/src/assets/sfx/tock.wav +0 -0
  221. package/src/assets/sfx/walk_steps.wav +0 -0
  222. package/src/assets/sfx/warning.wav +0 -0
  223. package/src/assets/sfx/whack.wav +0 -0
  224. package/src/assets/sfx/whoosh.wav +0 -0
  225. package/src/assets/sfx/win.wav +0 -0
  226. package/src/assets/sfx/zap.wav +0 -0
  227. package/src/assets/textures/ad_bolt.png +0 -0
  228. package/src/assets/textures/ad_bubbles.png +0 -0
  229. package/src/assets/textures/ad_chevrons.png +0 -0
  230. package/src/assets/textures/asphalt.png +0 -0
  231. package/src/assets/textures/bark.jpg +0 -0
  232. package/src/assets/textures/explorer-atlas.png +0 -0
  233. package/src/assets/textures/facade.png +0 -0
  234. package/src/assets/textures/grass.png +0 -0
  235. package/src/assets/textures/leaves.png +0 -0
  236. package/src/assets/textures/limestone.jpg +0 -0
  237. package/src/assets/textures/meadow.jpg +0 -0
  238. package/src/assets/textures/nature-sources.json +0 -87
  239. package/src/assets/textures/pine.png +0 -0
  240. package/src/assets/textures/river.jpg +0 -0
  241. package/src/assets/textures/soft_glow.png +0 -0
  242. package/src/games/arrows/Arrows.tsx +0 -69
  243. package/src/games/arrows/ArrowsConstants.ts +0 -107
  244. package/src/games/arrows/ArrowsGame.ts +0 -735
  245. package/src/games/arrows/ArrowsScene.ts +0 -395
  246. package/src/games/balloon-blaster/BalloonBlaster.tsx +0 -75
  247. package/src/games/balloon-blaster/BalloonBlasterConstants.ts +0 -79
  248. package/src/games/balloon-blaster/BalloonBlasterGame.ts +0 -287
  249. package/src/games/balloon-blaster/BalloonBlasterPhysics.ts +0 -95
  250. package/src/games/balloon-blaster/BalloonBlasterScene.ts +0 -225
  251. package/src/games/bike-racing/BikeMeshes.ts +0 -273
  252. package/src/games/bike-racing/BikeRacing.tsx +0 -211
  253. package/src/games/bike-racing/BikeRacingConstants.ts +0 -103
  254. package/src/games/bike-racing/BikeRacingGame.ts +0 -557
  255. package/src/games/bike-racing/BikeRacingScene.ts +0 -119
  256. package/src/games/block-blast/BlockBlast.tsx +0 -73
  257. package/src/games/block-blast/BlockBlastConstants.ts +0 -179
  258. package/src/games/block-blast/BlockBlastGame.ts +0 -471
  259. package/src/games/block-blast/BlockBlastScene.ts +0 -156
  260. package/src/games/block-breaker/BlockBreaker.tsx +0 -79
  261. package/src/games/block-breaker/BlockBreakerConstants.ts +0 -139
  262. package/src/games/block-breaker/BlockBreakerGame.ts +0 -459
  263. package/src/games/block-breaker/BlockBreakerScene.ts +0 -257
  264. package/src/games/bluk/Bluk.tsx +0 -82
  265. package/src/games/bluk/BlukConstants.ts +0 -121
  266. package/src/games/bluk/BlukGame.ts +0 -323
  267. package/src/games/bluk/BlukRules.ts +0 -154
  268. package/src/games/bluk/BlukScene.ts +0 -514
  269. package/src/games/bubble-shooter/BubbleShooter.tsx +0 -76
  270. package/src/games/bubble-shooter/BubbleShooterConstants.ts +0 -103
  271. package/src/games/bubble-shooter/BubbleShooterGame.ts +0 -459
  272. package/src/games/bubble-shooter/BubbleShooterScene.ts +0 -158
  273. package/src/games/candy-crush/CandyCrush.tsx +0 -77
  274. package/src/games/candy-crush/CandyCrushConstants.ts +0 -94
  275. package/src/games/candy-crush/CandyCrushGame.ts +0 -477
  276. package/src/games/candy-crush/CandyCrushScene.ts +0 -209
  277. package/src/games/car-racing/CarMeshes.ts +0 -440
  278. package/src/games/car-racing/CarRacing.tsx +0 -211
  279. package/src/games/car-racing/CarRacingConstants.ts +0 -167
  280. package/src/games/car-racing/CarRacingFacade.ts +0 -40
  281. package/src/games/car-racing/CarRacingGame.ts +0 -539
  282. package/src/games/car-racing/CarRacingScene.ts +0 -1026
  283. package/src/games/car-racing/CarRacingScenery.ts +0 -265
  284. package/src/games/chameleon-run/ChameleonRun.tsx +0 -96
  285. package/src/games/chameleon-run/ChameleonRunBackdrop.ts +0 -186
  286. package/src/games/chameleon-run/ChameleonRunConstants.ts +0 -47
  287. package/src/games/chameleon-run/ChameleonRunGame.ts +0 -309
  288. package/src/games/chameleon-run/ChameleonRunMeshes.ts +0 -305
  289. package/src/games/chameleon-run/ChameleonRunRules.ts +0 -252
  290. package/src/games/chameleon-run/ChameleonRunScene.ts +0 -310
  291. package/src/games/checkers/Checkers.tsx +0 -83
  292. package/src/games/checkers/CheckersAI.ts +0 -255
  293. package/src/games/checkers/CheckersConstants.ts +0 -68
  294. package/src/games/checkers/CheckersGame.ts +0 -322
  295. package/src/games/checkers/CheckersRules.ts +0 -167
  296. package/src/games/checkers/CheckersScene.ts +0 -308
  297. package/src/games/color-switch/ColorSwitch.tsx +0 -75
  298. package/src/games/color-switch/ColorSwitchConstants.ts +0 -61
  299. package/src/games/color-switch/ColorSwitchGame.ts +0 -329
  300. package/src/games/color-switch/ColorSwitchScene.ts +0 -220
  301. package/src/games/colors-sort/ColorsSort.tsx +0 -82
  302. package/src/games/colors-sort/ColorsSortConstants.ts +0 -119
  303. package/src/games/colors-sort/ColorsSortGame.ts +0 -246
  304. package/src/games/colors-sort/ColorsSortScene.ts +0 -315
  305. package/src/games/connect-em-all/ConnectEmAll.tsx +0 -70
  306. package/src/games/connect-em-all/ConnectEmAllConstants.ts +0 -77
  307. package/src/games/connect-em-all/ConnectEmAllGame.ts +0 -401
  308. package/src/games/connect-em-all/ConnectEmAllScene.ts +0 -235
  309. package/src/games/crossy-road/CrossyRoad.tsx +0 -74
  310. package/src/games/crossy-road/CrossyRoadCamera.ts +0 -59
  311. package/src/games/crossy-road/CrossyRoadConstants.ts +0 -132
  312. package/src/games/crossy-road/CrossyRoadGame.ts +0 -293
  313. package/src/games/crossy-road/CrossyRoadMeshes.ts +0 -195
  314. package/src/games/crossy-road/CrossyRoadPerson.ts +0 -198
  315. package/src/games/crossy-road/CrossyRoadRules.ts +0 -99
  316. package/src/games/crossy-road/CrossyRoadScene.ts +0 -355
  317. package/src/games/dino-jump/DinoJump.tsx +0 -77
  318. package/src/games/dino-jump/DinoJumpConstants.ts +0 -80
  319. package/src/games/dino-jump/DinoJumpGame.ts +0 -344
  320. package/src/games/dino-jump/DinoJumpScene.ts +0 -686
  321. package/src/games/dots-and-boxes/DotsAndBoxes.tsx +0 -83
  322. package/src/games/dots-and-boxes/DotsAndBoxesConstants.ts +0 -77
  323. package/src/games/dots-and-boxes/DotsAndBoxesGame.ts +0 -271
  324. package/src/games/dots-and-boxes/DotsAndBoxesScene.ts +0 -249
  325. package/src/games/falling-sticks/FallingSticks.tsx +0 -72
  326. package/src/games/falling-sticks/FallingSticksConstants.ts +0 -62
  327. package/src/games/falling-sticks/FallingSticksGame.ts +0 -220
  328. package/src/games/falling-sticks/FallingSticksRules.ts +0 -145
  329. package/src/games/falling-sticks/FallingSticksScene.ts +0 -245
  330. package/src/games/find-different-number/FindDifferentNumber.tsx +0 -74
  331. package/src/games/find-different-number/FindDifferentNumberConstants.ts +0 -74
  332. package/src/games/find-different-number/FindDifferentNumberGame.ts +0 -174
  333. package/src/games/find-different-number/FindDifferentNumberRules.ts +0 -43
  334. package/src/games/find-different-number/FindDifferentNumberScene.ts +0 -193
  335. package/src/games/flappy-bird/FlappyBird.tsx +0 -73
  336. package/src/games/flappy-bird/FlappyBirdConstants.ts +0 -95
  337. package/src/games/flappy-bird/FlappyBirdGame.ts +0 -375
  338. package/src/games/flappy-bird/FlappyBirdScene.ts +0 -630
  339. package/src/games/fruit-merger/FruitMerger.tsx +0 -73
  340. package/src/games/fruit-merger/FruitMergerConstants.ts +0 -102
  341. package/src/games/fruit-merger/FruitMergerGame.ts +0 -285
  342. package/src/games/fruit-merger/FruitMergerRules.ts +0 -286
  343. package/src/games/fruit-merger/FruitMergerScene.ts +0 -498
  344. package/src/games/fruit-ninja/FruitNinja.tsx +0 -129
  345. package/src/games/fruit-ninja/FruitNinjaConstants.ts +0 -107
  346. package/src/games/fruit-ninja/FruitNinjaGame.ts +0 -391
  347. package/src/games/fruit-ninja/FruitNinjaScene.ts +0 -319
  348. package/src/games/fruit-ninja/FruitNinjaWorld.ts +0 -17
  349. package/src/games/game-2048/Game2048.tsx +0 -84
  350. package/src/games/game-2048/Game2048Constants.ts +0 -68
  351. package/src/games/game-2048/Game2048Game.ts +0 -181
  352. package/src/games/game-2048/Game2048Rules.ts +0 -101
  353. package/src/games/game-2048/Game2048Scene.ts +0 -206
  354. package/src/games/knife-hit/KnifeHit.tsx +0 -78
  355. package/src/games/knife-hit/KnifeHitConstants.ts +0 -89
  356. package/src/games/knife-hit/KnifeHitGame.ts +0 -264
  357. package/src/games/knife-hit/KnifeHitScene.ts +0 -360
  358. package/src/games/ludo-king/LudoKing.tsx +0 -86
  359. package/src/games/ludo-king/LudoKingConstants.ts +0 -212
  360. package/src/games/ludo-king/LudoKingGame.ts +0 -326
  361. package/src/games/ludo-king/LudoKingRules.ts +0 -143
  362. package/src/games/ludo-king/LudoKingScene.ts +0 -397
  363. package/src/games/maze-runner/MazeRunner.tsx +0 -88
  364. package/src/games/maze-runner/MazeRunnerConstants.ts +0 -65
  365. package/src/games/maze-runner/MazeRunnerGame.ts +0 -176
  366. package/src/games/maze-runner/MazeRunnerRules.ts +0 -161
  367. package/src/games/maze-runner/MazeRunnerScene.ts +0 -245
  368. package/src/games/memory-match/MemoryMatch.tsx +0 -77
  369. package/src/games/memory-match/MemoryMatchConstants.ts +0 -105
  370. package/src/games/memory-match/MemoryMatchGame.ts +0 -222
  371. package/src/games/memory-match/MemoryMatchRules.ts +0 -38
  372. package/src/games/memory-match/MemoryMatchScene.ts +0 -268
  373. package/src/games/mine-sweeper/MineSweeper.tsx +0 -77
  374. package/src/games/mine-sweeper/MineSweeperConstants.ts +0 -94
  375. package/src/games/mine-sweeper/MineSweeperGame.ts +0 -234
  376. package/src/games/mine-sweeper/MineSweeperRules.ts +0 -67
  377. package/src/games/mine-sweeper/MineSweeperScene.ts +0 -262
  378. package/src/games/mob-control/MobControl.tsx +0 -73
  379. package/src/games/mob-control/MobControlConstants.ts +0 -106
  380. package/src/games/mob-control/MobControlGame.ts +0 -176
  381. package/src/games/mob-control/MobControlMeshes.ts +0 -85
  382. package/src/games/mob-control/MobControlRenderer.ts +0 -108
  383. package/src/games/mob-control/MobControlRules.ts +0 -522
  384. package/src/games/mob-control/MobControlScene.ts +0 -399
  385. package/src/games/number-search/NumberSearch.tsx +0 -18
  386. package/src/games/number-search/NumberSearchNumbers.ts +0 -623
  387. package/src/games/nuts-and-bolts/NutsAndBolts.tsx +0 -85
  388. package/src/games/nuts-and-bolts/NutsAndBoltsConstants.ts +0 -75
  389. package/src/games/nuts-and-bolts/NutsAndBoltsGame.ts +0 -298
  390. package/src/games/nuts-and-bolts/NutsAndBoltsRules.ts +0 -474
  391. package/src/games/nuts-and-bolts/NutsAndBoltsScene.ts +0 -498
  392. package/src/games/pac-man/PacMan.tsx +0 -86
  393. package/src/games/pac-man/PacManConstants.ts +0 -169
  394. package/src/games/pac-man/PacManGame.ts +0 -406
  395. package/src/games/pac-man/PacManRules.ts +0 -255
  396. package/src/games/pac-man/PacManScene.ts +0 -387
  397. package/src/games/paper-io/PaperIo.tsx +0 -91
  398. package/src/games/paper-io/PaperIoConstants.ts +0 -86
  399. package/src/games/paper-io/PaperIoGame.ts +0 -193
  400. package/src/games/paper-io/PaperIoMeshes.ts +0 -233
  401. package/src/games/paper-io/PaperIoRules.ts +0 -315
  402. package/src/games/paper-io/PaperIoScene.ts +0 -310
  403. package/src/games/penguin-run/PenguinMeshes.ts +0 -269
  404. package/src/games/penguin-run/PenguinModel.ts +0 -712
  405. package/src/games/penguin-run/PenguinRun.tsx +0 -77
  406. package/src/games/penguin-run/PenguinRunConstants.ts +0 -69
  407. package/src/games/penguin-run/PenguinRunGame.ts +0 -406
  408. package/src/games/penguin-run/PenguinRunScene.ts +0 -949
  409. package/src/games/perfect-circle/PerfectCircle.tsx +0 -74
  410. package/src/games/perfect-circle/PerfectCircleConstants.ts +0 -52
  411. package/src/games/perfect-circle/PerfectCircleGame.ts +0 -153
  412. package/src/games/perfect-circle/PerfectCircleRules.ts +0 -111
  413. package/src/games/perfect-circle/PerfectCircleScene.ts +0 -176
  414. package/src/games/pipe-connect/PipeConnect.tsx +0 -69
  415. package/src/games/pipe-connect/PipeConnectConstants.ts +0 -101
  416. package/src/games/pipe-connect/PipeConnectGame.ts +0 -179
  417. package/src/games/pipe-connect/PipeConnectRules.ts +0 -326
  418. package/src/games/pipe-connect/PipeConnectScene.ts +0 -271
  419. package/src/games/play-with-tua/PlayWithTua.tsx +0 -123
  420. package/src/games/play-with-tua/PlayWithTuaConstants.ts +0 -70
  421. package/src/games/play-with-tua/PlayWithTuaGame.ts +0 -167
  422. package/src/games/play-with-tua/PlayWithTuaModel.ts +0 -42
  423. package/src/games/play-with-tua/PlayWithTuaScene.ts +0 -36
  424. package/src/games/popit-fidget/PopitFidget.tsx +0 -72
  425. package/src/games/popit-fidget/PopitFidgetConstants.ts +0 -71
  426. package/src/games/popit-fidget/PopitFidgetGame.ts +0 -148
  427. package/src/games/popit-fidget/PopitFidgetScene.ts +0 -242
  428. package/src/games/reversi/Reversi.tsx +0 -94
  429. package/src/games/reversi/ReversiConstants.ts +0 -67
  430. package/src/games/reversi/ReversiGame.ts +0 -266
  431. package/src/games/reversi/ReversiRules.ts +0 -176
  432. package/src/games/reversi/ReversiScene.ts +0 -240
  433. package/src/games/search-grid/SearchGrid.tsx +0 -92
  434. package/src/games/search-grid/SearchGridConstants.ts +0 -178
  435. package/src/games/search-grid/SearchGridGame.ts +0 -209
  436. package/src/games/search-grid/SearchGridScene.ts +0 -301
  437. package/src/games/shared/BackdropCard.tsx +0 -54
  438. package/src/games/shared/EngineBackdrop.ts +0 -300
  439. package/src/games/shared/EngineBlasts.ts +0 -136
  440. package/src/games/shared/EngineBlocks.ts +0 -91
  441. package/src/games/shared/EngineControlText.ts +0 -17
  442. package/src/games/shared/EngineDice.ts +0 -250
  443. package/src/games/shared/EngineFootprint.ts +0 -35
  444. package/src/games/shared/EngineFruits.ts +0 -1435
  445. package/src/games/shared/EngineGameLoader.tsx +0 -88
  446. package/src/games/shared/EngineGameScreen.tsx +0 -325
  447. package/src/games/shared/EngineGameWidth.ts +0 -3
  448. package/src/games/shared/EngineGameWidth.web.ts +0 -3
  449. package/src/games/shared/EngineGlyphs.ts +0 -178
  450. package/src/games/shared/EngineHud.ts +0 -815
  451. package/src/games/shared/EngineLoading.ts +0 -477
  452. package/src/games/shared/EngineMeadow.ts +0 -725
  453. package/src/games/shared/EngineMeshCache.ts +0 -15
  454. package/src/games/shared/EngineMeshes.ts +0 -10
  455. package/src/games/shared/EngineRacingChase.ts +0 -21
  456. package/src/games/shared/EngineRacingHandling.ts +0 -48
  457. package/src/games/shared/EngineReadyContext.ts +0 -4
  458. package/src/games/shared/EngineTilt.ts +0 -44
  459. package/src/games/shared/EngineTouchSurface.tsx +0 -103
  460. package/src/games/shared/EngineUtils.ts +0 -52
  461. package/src/games/shared/GameActivity.ts +0 -13
  462. package/src/games/shared/GameLoading.tsx +0 -202
  463. package/src/games/shared/GameLoadingTransition.tsx +0 -61
  464. package/src/games/shared/ProceduralCacheVersion.ts +0 -2
  465. package/src/games/shared/useEngineGame.ts +0 -240
  466. package/src/games/shared/useGameResource.ts +0 -21
  467. package/src/games/shared/useLiveState.ts +0 -58
  468. package/src/games/sliding-numbers/SlidingNumbers.tsx +0 -71
  469. package/src/games/sliding-numbers/SlidingNumbersConstants.ts +0 -65
  470. package/src/games/sliding-numbers/SlidingNumbersGame.ts +0 -192
  471. package/src/games/sliding-numbers/SlidingNumbersRules.ts +0 -79
  472. package/src/games/sliding-numbers/SlidingNumbersScene.ts +0 -193
  473. package/src/games/snake-3d/Snake3D.tsx +0 -76
  474. package/src/games/snake-3d/Snake3DConstants.ts +0 -61
  475. package/src/games/snake-3d/Snake3DGame.ts +0 -192
  476. package/src/games/snake-3d/Snake3DMotion.ts +0 -22
  477. package/src/games/snake-3d/Snake3DRules.ts +0 -116
  478. package/src/games/snake-3d/Snake3DScene.ts +0 -322
  479. package/src/games/snakes-and-ladders/SnakesAndLadders.tsx +0 -87
  480. package/src/games/snakes-and-ladders/SnakesAndLaddersConstants.ts +0 -136
  481. package/src/games/snakes-and-ladders/SnakesAndLaddersGame.ts +0 -310
  482. package/src/games/snakes-and-ladders/SnakesAndLaddersScene.ts +0 -515
  483. package/src/games/space-fighter/SpaceFighter.tsx +0 -74
  484. package/src/games/space-fighter/SpaceFighterConstants.ts +0 -86
  485. package/src/games/space-fighter/SpaceFighterGame.ts +0 -292
  486. package/src/games/space-fighter/SpaceFighterScene.ts +0 -550
  487. package/src/games/spider-solitaire/SpiderSolitaire.tsx +0 -80
  488. package/src/games/spider-solitaire/SpiderSolitaireConstants.ts +0 -107
  489. package/src/games/spider-solitaire/SpiderSolitaireGame.ts +0 -387
  490. package/src/games/spider-solitaire/SpiderSolitaireRules.ts +0 -123
  491. package/src/games/spider-solitaire/SpiderSolitaireScene.ts +0 -352
  492. package/src/games/stack-tower/StackTower.tsx +0 -76
  493. package/src/games/stack-tower/StackTowerConstants.ts +0 -74
  494. package/src/games/stack-tower/StackTowerGame.ts +0 -236
  495. package/src/games/stack-tower/StackTowerScene.ts +0 -186
  496. package/src/games/sudoku/Sudoku.tsx +0 -73
  497. package/src/games/sudoku/SudokuConstants.ts +0 -127
  498. package/src/games/sudoku/SudokuGame.ts +0 -250
  499. package/src/games/sudoku/SudokuRules.ts +0 -125
  500. package/src/games/sudoku/SudokuScene.ts +0 -304
  501. package/src/games/tangram/Tangram.tsx +0 -79
  502. package/src/games/tangram/TangramConstants.ts +0 -64
  503. package/src/games/tangram/TangramGame.ts +0 -356
  504. package/src/games/tangram/TangramRules.ts +0 -409
  505. package/src/games/tangram/TangramScene.ts +0 -203
  506. package/src/games/tank-1990/Tank1990.tsx +0 -78
  507. package/src/games/tank-1990/Tank1990Constants.ts +0 -81
  508. package/src/games/tank-1990/Tank1990Game.ts +0 -331
  509. package/src/games/tank-1990/Tank1990Rules.ts +0 -390
  510. package/src/games/tank-1990/Tank1990Scene.ts +0 -434
  511. package/src/games/tic-tac-toe/TicTacToe.tsx +0 -98
  512. package/src/games/tic-tac-toe/TicTacToeConstants.ts +0 -69
  513. package/src/games/tic-tac-toe/TicTacToeGame.ts +0 -200
  514. package/src/games/tic-tac-toe/TicTacToeRules.ts +0 -103
  515. package/src/games/tic-tac-toe/TicTacToeScene.ts +0 -245
  516. package/src/games/tile-home/TileHome.tsx +0 -92
  517. package/src/games/tile-home/TileHomeConstants.ts +0 -139
  518. package/src/games/tile-home/TileHomeGame.ts +0 -435
  519. package/src/games/tile-home/TileHomeScene.ts +0 -154
  520. package/src/games/treasure-hunt/TreasureHunt.tsx +0 -206
  521. package/src/games/treasure-hunt/TreasureHuntConstants.ts +0 -266
  522. package/src/games/treasure-hunt/TreasureHuntControls.ts +0 -280
  523. package/src/games/treasure-hunt/TreasureHuntGame.ts +0 -402
  524. package/src/games/treasure-hunt/TreasureHuntMeshes.ts +0 -422
  525. package/src/games/treasure-hunt/TreasureHuntModel.ts +0 -506
  526. package/src/games/treasure-hunt/TreasureHuntRules.ts +0 -1210
  527. package/src/games/treasure-hunt/TreasureHuntScene.ts +0 -586
  528. package/src/games/whack-a-mole/WhackAMole.tsx +0 -79
  529. package/src/games/whack-a-mole/WhackAMoleConstants.ts +0 -94
  530. package/src/games/whack-a-mole/WhackAMoleGame.ts +0 -233
  531. package/src/games/whack-a-mole/WhackAMoleScene.ts +0 -349
  532. package/src/games/word-search/WordSearch.tsx +0 -18
  533. package/src/games/word-search/WordSearchWords.ts +0 -1642
  534. package/src/helpers/GamePatternData.ts +0 -120
  535. package/src/helpers/GameSettingsModal.tsx +0 -384
  536. package/src/helpers/GameTheme.tsx +0 -37
  537. package/src/helpers/IconPaths.ts +0 -6
  538. package/src/helpers/index.ts +0 -2
  539. package/src/index.tsx +0 -60
  540. package/src/services/GameAssetLoader.ts +0 -111
  541. package/src/services/GameAssets.ts +0 -149
  542. package/src/services/GameLoaders.ts +0 -93
  543. package/src/services/GamesConstants.ts +0 -193
  544. package/src/services/GamesMetadata.ts +0 -711
  545. package/src/services/GamesService.ts +0 -116
  546. package/src/services/HapticsService.ts +0 -48
  547. package/src/services/ScoringService.ts +0 -19
  548. package/src/services/SfxSources.ts +0 -81
  549. package/src/services/SoundsService.ts +0 -582
  550. package/src/services/ThemeService.ts +0 -281
  551. package/src/services/UtilsService.ts +0 -134
  552. package/src/services/index.ts +0 -6
@@ -1,36 +0,0 @@
1
- import type { Camera, Entity, LoadedModel, World } from '@nayan-ui/engine';
2
- import type { GameTheme } from '../../services/ThemeService';
3
- import { getScoreBoardTop } from '../shared/EngineHud';
4
- import { toRgb } from '../shared/EngineUtils';
5
- import { PLAY_WITH_TUA_CAMERA_HEIGHT, PLAY_WITH_TUA_CONTROLS_HEIGHT } from './PlayWithTuaConstants';
6
- import { spawnCharacter } from './PlayWithTuaModel';
7
-
8
- export interface Scene {
9
- character: Entity;
10
- floor: Entity;
11
- camera: Camera;
12
- }
13
-
14
- export function buildScene(world: World, model: LoadedModel, theme: GameTheme): Scene {
15
- return {
16
- character: spawnCharacter(world, model),
17
- floor: world.spawn({ mesh: 'cube', position: [0, -0.055, 0], scale: [200, 0.1, 200], color: toRgb(theme.BACKGROUND), pickable: false }),
18
- camera: { eye: [0, PLAY_WITH_TUA_CAMERA_HEIGHT + 0.12, 9], target: [0, PLAY_WITH_TUA_CAMERA_HEIGHT, 0], fov: 0.7 }
19
- };
20
- }
21
-
22
- export function layoutScene(scene: Scene, width: number, height: number, offset: number) {
23
- const top = getScoreBoardTop(offset) + 88;
24
- const bottom = height - PLAY_WITH_TUA_CONTROLS_HEIGHT;
25
- const available = Math.max(80, bottom - top);
26
- const halfHeight = Math.max((2.12 * height) / available, (1.9 * height) / Math.max(1, width));
27
- const center = (top + bottom) / 2;
28
- const targetY = PLAY_WITH_TUA_CAMERA_HEIGHT + (center / Math.max(1, height) - 0.5) * 2 * halfHeight;
29
- scene.camera.target = [0, targetY, 0];
30
- scene.camera.eye = [0, targetY + 0.12, halfHeight / Math.tan(scene.camera.fov / 2)];
31
- return { top, bottom };
32
- }
33
-
34
- export function setSceneTheme(world: World, scene: Scene, theme: GameTheme) {
35
- world.set(scene.floor, { color: toRgb(theme.BACKGROUND) });
36
- }
@@ -1,72 +0,0 @@
1
- // Popit Fidget's screen, on the Nayan engine: the silicone sheet, its domes and dimples are one 3D scene
2
- // (an orthographic camera leaning back over the sheet), under Playtura's scoreboard, controls and
3
- // modals. The rules are in PopitFidgetGame.ts, what it draws in PopitFidgetScene.ts.
4
- //
5
- // One world serves the whole visit: Start, Stop and Play Again reset it in place and a theme change
6
- // repaints the backdrop, so the GPU view is never rebuilt. Pops animate in the engine's Rust core; JS
7
- // hit-tests touches (on touch-down, like the original version) and steps the clock and the world.
8
- import { useMemo } from 'react';
9
- import { HapticType } from '../../services/HapticsService';
10
- import { GAME_SOUNDS } from '../../services/SoundsService';
11
- import { GAME_IDS } from '../../services/UtilsService';
12
- import { engineGame, EngineGameScreen } from '../shared/EngineGameScreen';
13
- import { scoreColumn, timerColumn } from '../shared/EngineHud';
14
- import { toRgb } from '../shared/EngineUtils';
15
- import { useEngineGame } from '../shared/useEngineGame';
16
- import { useLiveState } from '../shared/useLiveState';
17
- import { getLayout, LIGHT, TIME_LIMIT, TIME_WARNING } from './PopitFidgetConstants';
18
- import { createGame, dispose, press, reset, setLayout, setTheme, start, tick } from './PopitFidgetGame';
19
-
20
- const SOUNDS = GAME_SOUNDS.POPIT_FIDGET;
21
-
22
- export const PopitFidget = engineGame(GAME_IDS.POPIT_FIDGET, (props) => {
23
- const [score, setScore] = useLiveState(0);
24
- const [timeLeft, setTimeLeft] = useLiveState(TIME_LIMIT);
25
-
26
- // Win or lose when it ends
27
- const { theme, status, screen, gameOver } = useEngineGame(props, {
28
- gameId: GAME_IDS.POPIT_FIDGET,
29
- create: createGame,
30
- start,
31
- reset,
32
- dispose,
33
- tick,
34
- setTheme,
35
- resize: (g, width, height, offset) => {
36
- const l = getLayout(width, height, offset);
37
- setLayout(g, l);
38
- return l.sheet;
39
- },
40
- // Pops on touch-down, like a real pop-it (a tap would wait for the finger to lift)
41
- drag: (g, e) => {
42
- if (e.phase === 'start') press(g, e.x, e.y);
43
- },
44
- sounds: SOUNDS,
45
- onStart: (fx) => fx(SOUNDS.START, HapticType.MEDIUM),
46
- onOver: (fx, s) => fx(s === 'win' ? GAME_SOUNDS.WELL_DONE : SOUNDS.GAME_OVER),
47
- wire: (g, fx) => {
48
- g.onScore = setScore;
49
- g.onTime = setTimeLeft;
50
- g.onPop = () => fx(SOUNDS.POP, HapticType.LIGHT);
51
- }
52
- });
53
-
54
- const background = useMemo(() => toRgb(theme.BACKGROUND), [theme.BACKGROUND]);
55
-
56
- return (
57
- <EngineGameScreen
58
- {...screen}
59
- light={LIGHT}
60
- background={background}
61
- columns={[scoreColumn(score), timerColumn(timeLeft, theme, TIME_WARNING)]}
62
- subtext="Pop bubbles to relax!"
63
- gameOver={gameOver({
64
- title: status === 'win' ? 'YOU WON!' : 'TIME UP!',
65
- message: status === 'win' ? 'All bubbles popped!' : 'You ran out of time!',
66
- scoreLabel: 'Final Score',
67
- score,
68
- buttonText: 'Pop Again!'
69
- })}
70
- />
71
- );
72
- });
@@ -1,71 +0,0 @@
1
- // Popit Fidget's rules, colors and layout. Rules, scoring and sizes match the original version
2
- // (games/popit-fidget), so scores carry over.
3
- import { getScoreBoardTop } from '../shared/EngineHud';
4
- import type { TiltView } from '../shared/EngineTilt';
5
- import { frontLight, gameWidthFor } from '../shared/EngineUtils';
6
-
7
- // ── Rules ─────────────────────────────────────────────────────────────
8
-
9
- export const GRID_SIZE = 6; // bubbles a side
10
- export const TIME_LIMIT = 120; // seconds
11
- export const POINTS_PER_BUBBLE = 250;
12
- export const TIME_WARNING = 10; // the timer turns red for the last ten seconds
13
-
14
- /** One vivid color per row, top to bottom. */
15
- export const ROW_COLORS = ['#FF3B3B', '#32CD32', '#FFD700', '#4DA6FF', '#BF5AF2', '#FF9500'] as const;
16
-
17
- // ── Feel (seconds) ────────────────────────────────────────────────────
18
-
19
- export const PRESS_TIME = 0.07; // the dome squashes under the finger...
20
- export const FLIP_TIME = 0.16; // ...and the dimple springs out in its place
21
-
22
- // ── The scene ─────────────────────────────────────────────────────────
23
-
24
- /** The camera leans back from straight down, so the domes stand up off the sheet. */
25
- export const TILT = 0.4;
26
- /** Lit from straight overhead with strong ambient, so nothing falls into shadow; surfaces facing up off the sheet (+z) keep their exact color. */
27
- export const LIGHT = frontLight([0, 0.12, 1], 0.72);
28
-
29
- // ── Layout (view points) ──────────────────────────────────────────────
30
-
31
- const SCOREBOARD_HEIGHT = 82;
32
- const CONTROLS_HEIGHT = 110;
33
- const SPACING = 1.12; // centre to centre, in bubbles
34
- const GRID_PADDING = 8;
35
-
36
- export type Layout = TiltView & {
37
- bubble: number;
38
- spacing: number;
39
- /** The sheet: the bubbles plus `GRID_PADDING` all round. */
40
- sheet: number;
41
- };
42
-
43
- /**
44
- * A bubble as big as the original grid had it (the game area, 30 narrower than the screen and at most 500
45
- * across, filled edge to edge), smaller if the screen is short; the sheet centred under the scoreboard.
46
- */
47
- export function getLayout(width: number, height: number, offset: number): Layout {
48
- const gameWidth = gameWidthFor(width);
49
- const top = getScoreBoardTop(offset) + SCOREBOARD_HEIGHT;
50
- const room = Math.max(200, height - top - CONTROLS_HEIGHT);
51
- const perBubble = (GRID_SIZE - 1) * SPACING + 1;
52
- const fitWidth = (gameWidth - GRID_PADDING * 2) / perBubble;
53
- // The sheet foreshortened by the tilt, plus the domes standing up at its far edge
54
- const fitHeight = (room / Math.cos(TILT) - GRID_PADDING * 2) / (perBubble + 0.5 * Math.tan(TILT));
55
- const bubble = Math.min(fitWidth, fitHeight);
56
- return {
57
- width,
58
- height,
59
- centerY: top + room / 2,
60
- tilt: TILT,
61
- bubble,
62
- spacing: bubble * SPACING,
63
- sheet: (GRID_SIZE - 1) * bubble * SPACING + bubble + GRID_PADDING * 2
64
- };
65
- }
66
-
67
- /** A bubble's centre on the sheet (row 0 along the top), in world units. */
68
- export function bubbleCentre(l: Layout, row: number, col: number): [number, number] {
69
- const first = -((GRID_SIZE - 1) * l.spacing) / 2;
70
- return [first + col * l.spacing, -first - row * l.spacing];
71
- }
@@ -1,148 +0,0 @@
1
- // Popit Fidget's rules, with no React: build a game with `createGame`, give it a layout, `start` it and
2
- // `tick` it every frame. Touch a bubble to pop it (250 points), on touch-down, like a real pop-it; pop
3
- // all 36 inside two minutes to win (the score then rewards the time left, as the original version did).
4
- import { type Camera, World } from '@nayan-ui/engine';
5
- import { calculateTimeBasedScore } from '../../services/ScoringService';
6
- import type { GameTheme } from '../../services/ThemeService';
7
- import { aimTilted, unproject } from '../shared/EngineTilt';
8
- import { bubbleCentre, GRID_SIZE, type Layout, POINTS_PER_BUBBLE, TIME_LIMIT } from './PopitFidgetConstants';
9
- import { buildScene, celebrate, pop, removeScene, restore, type Scene, setSceneTheme } from './PopitFidgetScene';
10
-
11
- export type Phase = 'ready' | 'playing' | 'over';
12
-
13
- const BUBBLES = GRID_SIZE * GRID_SIZE;
14
- const WORLD_CAPACITY = 300; // domes and dimples (72), the sheet, the backdrop, and flecks
15
- const HIT_RADIUS = 0.45; // of a bubble: how near its centre a touch pops it (as the original grid)
16
-
17
- export function createGame(theme: GameTheme) {
18
- const world = new World(WORLD_CAPACITY);
19
- const camera: Camera = { eye: [0, 0, 240], target: [0, 0, 0], fov: 1, ortho: 1 };
20
- const g = {
21
- world,
22
- camera,
23
- theme,
24
- layout: null as Layout | null,
25
- scene: null as Scene | null,
26
- phase: 'ready' as Phase,
27
- popped: new Array<boolean>(BUBBLES).fill(false),
28
- count: 0,
29
- /** Score and the countdown live in the engine (Rust), advanced by world.update. */
30
- get score() {
31
- return world.scoreboard.score;
32
- },
33
- get timeLeft() {
34
- return world.scoreboard.shownSeconds;
35
- },
36
- won: false,
37
- // UI hooks, set by the screen.
38
- onPhase: (_p: Phase) => {},
39
- onScore: (_s: number) => {},
40
- onTime: (_t: number) => {},
41
- onPop: () => {}
42
- };
43
- world.scoreboard.reset(0, TIME_LIMIT);
44
- world.scoreboard.handlers = {
45
- onSecond: (t) => g.onTime(t),
46
- onTimeUp: () => {
47
- if (g.phase !== 'playing') return;
48
- g.won = false;
49
- g.phase = 'over';
50
- g.onPhase('over');
51
- }
52
- };
53
- return g;
54
- }
55
- export type Game = ReturnType<typeof createGame>;
56
-
57
- // ── Scene ─────────────────────────────────────────────────────────────
58
-
59
- /** Lays the scene out for the view (first layout, header height, rotation): rebuilt from the sheet's state. */
60
- export function setLayout(g: Game, l: Layout) {
61
- if (g.scene) removeScene(g.world, g.scene);
62
- g.layout = l;
63
- aimTilted(g.camera, l);
64
- g.scene = buildScene(g.world, l, g.theme, g.popped);
65
- }
66
-
67
- export function setTheme(g: Game, theme: GameTheme) {
68
- g.theme = theme;
69
- if (g.scene) setSceneTheme(g.world, g.scene, theme);
70
- }
71
-
72
- // ── Run ───────────────────────────────────────────────────────────────
73
-
74
- /** A fresh sheet, and the clock running. */
75
- export function start(g: Game) {
76
- if (g.phase !== 'ready') return;
77
- freshSheet(g);
78
- g.phase = 'playing';
79
- g.world.scoreboard.startCountdown(TIME_LIMIT);
80
- g.onPhase('playing');
81
- }
82
-
83
- /** A fresh sheet, not started (Stop, Play Again). The world, and the GPU view drawing it, are kept. */
84
- export function reset(g: Game) {
85
- freshSheet(g);
86
- g.won = false;
87
- g.phase = 'ready';
88
- g.onPhase('ready');
89
- }
90
-
91
- function freshSheet(g: Game) {
92
- g.popped.fill(false);
93
- g.count = 0;
94
- g.world.scoreboard.reset(0, TIME_LIMIT);
95
- if (g.layout && g.scene) restore(g.world, g.layout, g.scene);
96
- g.onScore(0);
97
- g.onTime(TIME_LIMIT);
98
- }
99
-
100
- export function dispose(g: Game) {
101
- g.world.dispose();
102
- }
103
-
104
- export function tick(g: Game, dt: number) {
105
- if (g.world.isDisposed) return;
106
- g.world.update(dt);
107
- }
108
-
109
- // ── Touch ─────────────────────────────────────────────────────────────
110
-
111
- /** The unpopped bubble under a view point, if any. */
112
- export function bubbleAt(g: Game, x: number, y: number): number | null {
113
- const l = g.layout;
114
- if (!l) return null;
115
- // Half way up a dome, where the eye sees the bubble
116
- const [wx, wy] = unproject(l, x, y, l.bubble * 0.17);
117
- const first = -((GRID_SIZE - 1) * l.spacing) / 2;
118
- const col = Math.round((wx - first) / l.spacing);
119
- const row = Math.round((-first - wy) / l.spacing);
120
- if (row < 0 || row >= GRID_SIZE || col < 0 || col >= GRID_SIZE) return null;
121
- const [cx, cy] = bubbleCentre(l, row, col);
122
- const index = row * GRID_SIZE + col;
123
- if (g.popped[index] || Math.hypot(wx - cx, wy - cy) > l.bubble * HIT_RADIUS) return null;
124
- return index;
125
- }
126
-
127
- /** A finger comes down: pops the bubble under it. */
128
- export function press(g: Game, x: number, y: number) {
129
- if (g.phase !== 'playing') return;
130
- const index = bubbleAt(g, x, y);
131
- if (index == null) return;
132
- g.popped[index] = true;
133
- g.count += 1;
134
- g.world.scoreboard.add(POINTS_PER_BUBBLE);
135
- if (g.layout && g.scene) pop(g.world, g.layout, g.scene, index);
136
- g.onPop();
137
- if (g.count >= BUBBLES) {
138
- g.world.scoreboard.set(calculateTimeBasedScore(TIME_LIMIT - g.timeLeft, TIME_LIMIT, g.score));
139
- g.world.scoreboard.stop();
140
- g.won = true;
141
- g.phase = 'over';
142
- if (g.layout) celebrate(g.world, g.layout);
143
- g.onScore(g.score);
144
- g.onPhase('over');
145
- return;
146
- }
147
- g.onScore(g.score);
148
- }
@@ -1,242 +0,0 @@
1
- // Everything Popit Fidget draws: a moulded silicone sheet lying flat (a band of color per row, as the
2
- // original sheet), a dome standing up for every bubble, and a dimple for every popped one, seen from a
3
- // little in front of straight down (shared/EngineTilt: an orthographic camera leaning back, one world
4
- // unit per point). Popping squashes the dome flat and springs a dimple out in its place. The domes
5
- // share one mesh and so do the dimples (one instanced draw each); the sheet is one mesh per size.
6
- import { type Color, effects, type Entity, extrude, lathe, merge, type Model, Path, quat, type World } from '@nayan-ui/engine';
7
- import { darken, lighten } from '../../services/GamesConstants';
8
- import type { GameTheme } from '../../services/ThemeService';
9
- import { setBackdropTheme, spawnBackdrop } from '../shared/EngineBackdrop';
10
- import { popBurst } from '../shared/EngineBlasts';
11
- import { cacheGameAsset, createGameMesh as createShape } from '../shared/EngineMeshes';
12
- import { placeTiltedBackdrop } from '../shared/EngineTilt';
13
- import { toColor } from '../shared/EngineUtils';
14
- import { bubbleCentre, FLIP_TIME, GRID_SIZE, type Layout, PRESS_TIME, ROW_COLORS } from './PopitFidgetConstants';
15
-
16
- const meshes = new Map<string, Model>();
17
- const cached = (key: string, build: () => Model) => {
18
- let m = meshes.get(key);
19
- if (!m) {
20
- m = cacheGameAsset('popit-fidget/PopitFidgetScene:' + key, build);
21
- meshes.set(key, m);
22
- }
23
- return m;
24
- };
25
- /** Stands a lathe (built around +y) up off the sheet (+z). */
26
- const STAND_UP = quat.x(Math.PI / 2);
27
- const SHEET_DEPTH = 10;
28
- const CORNER = 22;
29
- const BACKDROP_DEPTH = 25;
30
-
31
- const rgb = (css: string): [number, number, number] => {
32
- const [r, g, b] = toColor(css);
33
- return [r, g, b];
34
- };
35
- const sheetShade = (row: number) => rgb(lighten(ROW_COLORS[row]!, 0.22));
36
- const domeColor = (row: number): Color => toColor(ROW_COLORS[row]!);
37
- const dimpleColor = (row: number): Color => toColor(darken(ROW_COLORS[row]!, 0.12));
38
-
39
- // ── Meshes ────────────────────────────────────────────────────────────
40
-
41
- /**
42
- * The silicone sheet `size` across, its top face at z = 0: a band per row, split half way between
43
- * rows, the top and bottom ones carrying the rounded corners.
44
- */
45
- const sheetMesh = (l: Layout) =>
46
- cached(`pf-sheet:${l.sheet.toFixed(1)}:${l.spacing.toFixed(2)}`, () => {
47
- const half = l.sheet / 2;
48
- const r = Math.min(CORNER, l.spacing / 2);
49
- const parts = Array.from({ length: GRID_SIZE }, (_, row) => {
50
- // Path coordinates run y down, from the sheet's top edge
51
- const [, cy] = bubbleCentre(l, row, 0);
52
- const top = row === 0 ? -half : -(cy + l.spacing / 2);
53
- const bottom = row === GRID_SIZE - 1 ? half : -(cy - l.spacing / 2);
54
- const p = new Path();
55
- if (row === 0) {
56
- p.moveTo(-half, bottom)
57
- .lineTo(-half, top + r)
58
- .quadraticTo(-half, top, -half + r, top)
59
- .lineTo(half - r, top)
60
- .quadraticTo(half, top, half, top + r)
61
- .lineTo(half, bottom)
62
- .close();
63
- } else if (row === GRID_SIZE - 1) {
64
- p.moveTo(-half, top)
65
- .lineTo(half, top)
66
- .lineTo(half, bottom - r)
67
- .quadraticTo(half, bottom, half - r, bottom)
68
- .lineTo(-half + r, bottom)
69
- .quadraticTo(-half, bottom, -half, bottom - r)
70
- .close();
71
- } else {
72
- p.addRect(-half, top, l.sheet, bottom - top);
73
- }
74
- return { geometry: extrude(p, { depth: SHEET_DEPTH }), color: sheetShade(row) };
75
- });
76
- return createShape(merge(parts), { shine: 0.25 });
77
- });
78
-
79
- /** A thin raised lip round the sheet's edge, catching the light. */
80
- const lipMesh = (l: Layout) =>
81
- cached(`pf-lip:${l.sheet.toFixed(1)}`, () => {
82
- const s = l.sheet;
83
- const r = Math.min(CORNER, l.spacing / 2);
84
- return createShape(
85
- extrude(new Path().addRoundedRect(-s / 2, -s / 2, s, s, r).addRoundedRect(-s / 2 + 3, -s / 2 + 3, s - 6, s - 6, r - 3), {
86
- depth: 2.5,
87
- fillRule: 'evenodd'
88
- }),
89
- { shine: 0.6 }
90
- );
91
- });
92
-
93
- const smooth = (a: number, b: number, x: number) => {
94
- const t = Math.min(1, Math.max(0, (x - a) / (b - a)));
95
- return t * t * (3 - 2 * t);
96
- };
97
- const grey = (k: number): [number, number, number] => [k, k, k];
98
-
99
- // The bubbles sit 1.12 apart (SPACING) and are 1.04 across at the foot, leaving a strip of sheet between.
100
- /**
101
- * A silicone bubble: a fillet curving up out of the sheet into near-upright walls and
102
- * a full round cap, like a real pop-it. Shaded in (it tints the row's color): a faint crease where
103
- * it meets the sheet, brightening up the walls to a pale top, which the light then picks out.
104
- */
105
- const domeMesh = () =>
106
- cached('pf-dome-v4', () => {
107
- const profile: [number, number][] = [];
108
- // The fillet into the sheet: a quarter circle from the foot to the wall
109
- for (let i = 0; i <= 8; i++) {
110
- const a = (i / 8) * (Math.PI / 2);
111
- profile.push([0.52 - 0.06 * Math.sin(a), 0.06 * (1 - Math.cos(a))]);
112
- }
113
- profile.reverse();
114
- // The cap: a squashed half circle on top of the walls
115
- const cap: [number, number][] = [];
116
- for (let i = 0; i <= 20; i++) {
117
- const a = (i / 20) * (Math.PI / 2);
118
- cap.push([Math.max(0.001, 0.46 * Math.cos(a)), 0.12 + 0.3 * Math.sin(a)]);
119
- }
120
- return createShape(
121
- lathe([...cap.reverse(), ...profile], {
122
- segments: 64,
123
- color: ({ position: p }) => grey(0.88 + 0.12 * smooth(0, 0.2, p[1]) + 0.04 * smooth(0.3, 0.43, p[1]))
124
- }),
125
- { center: false, shine: 0.38 }
126
- );
127
- });
128
-
129
- /**
130
- * A popped bubble, one unit across: a round lip and a deep soft dish inside it, its floor in shadow
131
- * and its far wall catching the light. (Run from the centre outward, so the dish faces the camera.)
132
- */
133
- const dimpleMesh = () =>
134
- cached('pf-dimple-v4', () => {
135
- const profile: [number, number][] = [];
136
- // The dish: a bowl from the centre up to the lip's crest
137
- for (let i = 0; i <= 14; i++) {
138
- const t = i / 14;
139
- profile.push([Math.max(0.001, 0.44 * t), 0.012 + 0.14 * t * t]);
140
- }
141
- // The lip: rolling over its crest and down into the sheet
142
- for (let i = 1; i <= 10; i++) {
143
- const a = (i / 10) * Math.PI;
144
- profile.push([0.475 - 0.035 * Math.cos(a) + 0.025 * (i / 10), 0.152 + 0.04 * Math.sin(a) - 0.19 * smooth(0.5, 1, i / 10)]);
145
- }
146
- return createShape(
147
- lathe(profile, {
148
- segments: 64,
149
- color: ({ position: p }) => grey(0.8 + 0.2 * smooth(0.02, 0.17, p[1]))
150
- }),
151
- { center: false, shine: 0.3 }
152
- );
153
- });
154
-
155
- // ── Spawning ──────────────────────────────────────────────────────────
156
-
157
- export type Scene = { backdrop: Entity; sheet: Entity; lip: Entity; domes: Entity[]; dimples: Entity[] };
158
-
159
- export function buildScene(world: World, l: Layout, theme: GameTheme, popped: readonly boolean[]): Scene {
160
- const backdrop = spawnBackdrop(world, l.width, l.height, -BACKDROP_DEPTH, theme);
161
- placeTiltedBackdrop(world, backdrop, l, BACKDROP_DEPTH);
162
- const sheet = world.spawn({ mesh: sheetMesh(l), position: [0, 0, -SHEET_DEPTH / 2], color: [1, 1, 1, 1], pickable: false });
163
- const lip = world.spawn({ mesh: lipMesh(l), position: [0, 0, 1.25], color: [1, 1, 1, 0.45], pickable: false });
164
- const domes: Entity[] = [];
165
- const dimples: Entity[] = [];
166
- for (let row = 0; row < GRID_SIZE; row++)
167
- for (let col = 0; col < GRID_SIZE; col++) {
168
- const [x, y] = bubbleCentre(l, row, col);
169
- const up = !popped[row * GRID_SIZE + col];
170
- domes.push(
171
- world.spawn({ mesh: domeMesh(), position: [x, y, 0], rotation: STAND_UP, scale: up ? l.bubble : 0, color: domeColor(row), pickable: false })
172
- );
173
- dimples.push(
174
- world.spawn({
175
- mesh: dimpleMesh(),
176
- position: [x, y, 0],
177
- rotation: STAND_UP,
178
- scale: up ? 0 : l.bubble,
179
- color: dimpleColor(row),
180
- pickable: false
181
- })
182
- );
183
- }
184
- return { backdrop, sheet, lip, domes, dimples };
185
- }
186
-
187
- export function removeScene(world: World, s: Scene) {
188
- for (const e of [s.backdrop, s.sheet, s.lip, ...s.domes, ...s.dimples]) world.despawn(e);
189
- }
190
-
191
- export function setSceneTheme(world: World, s: Scene, theme: GameTheme) {
192
- setBackdropTheme(world, s.backdrop, theme);
193
- }
194
-
195
- // ── Motion ────────────────────────────────────────────────────────────
196
-
197
- /** Pop: the dome squashes flat under the finger and a dimple springs out in its place, with a few flecks. */
198
- export function pop(world: World, l: Layout, s: Scene, index: number) {
199
- const b = l.bubble;
200
- const row = Math.floor(index / GRID_SIZE);
201
- const dome = s.domes[index]!;
202
- const dimple = s.dimples[index]!;
203
- world.stopAnimation(dome);
204
- world.stopAnimation(dimple);
205
- world.animate(dome, [{ scale: [b * 1.1, b * 0.18, b * 1.1], at: 0.75 }, { scale: 0 }], { duration: PRESS_TIME + 0.02, easing: 'easeIn' });
206
- world.set(dimple, { scale: 0 });
207
- world.animate(dimple, [{ scale: [b * 1.08, b * 1.4, b * 1.08], at: 0.55 }, { scale: b }], {
208
- duration: FLIP_TIME,
209
- delay: PRESS_TIME,
210
- easing: 'easeOut'
211
- });
212
- const [x, y] = bubbleCentre(l, row, index % GRID_SIZE);
213
- // The shared pop's burst (the bubble itself flips in rather than vanishing)
214
- popBurst(world, { position: [x, y, b * 0.5], size: b, color: domeColor(row), glowZ: b * 0.05, count: 7 });
215
- }
216
-
217
- /** Every bubble back up (a new sheet). */
218
- export function restore(world: World, l: Layout, s: Scene) {
219
- s.domes.forEach((d, i) => {
220
- world.stopAnimation(d);
221
- world.stopAnimation(s.dimples[i]!);
222
- });
223
- const updates = world.transforms;
224
- s.domes.forEach((d, i) => {
225
- updates.scale(d, l.bubble);
226
- updates.scale(s.dimples[i]!, 0);
227
- });
228
- updates.flush();
229
- }
230
-
231
- /** Confetti over the sheet when every bubble's popped. */
232
- export function celebrate(world: World, l: Layout) {
233
- effects.confetti(world, {
234
- position: [0, 0, l.bubble],
235
- count: 60,
236
- size: l.bubble * 0.16,
237
- speed: l.sheet * 1.4,
238
- lifetime: 1.3,
239
- gravity: -l.sheet * 2.4,
240
- colors: ROW_COLORS.slice(0, 4).map((c) => toColor(c))
241
- });
242
- }
@@ -1,94 +0,0 @@
1
- // Reversi's screen: a flat board seen directly overhead, with raised 3D discs,
2
- // under Playtura's scoreboard, controls and modals. The play is in
3
- // ReversiGame.ts (the rules and the robot in ReversiRules.ts), what it draws in ReversiScene.ts.
4
- //
5
- // One world serves the whole visit: Start, Stop and Play Again reset it in place and a theme change
6
- // repaints the backdrop, so the GPU view is never rebuilt. Discs drop and turn over in the engine's
7
- // Rust core; JS reads the finger and steps the clock (and the robot's think) once a frame.
8
- import { HapticType } from '../../services/HapticsService';
9
- import { GAME_SOUNDS } from '../../services/SoundsService';
10
- import { GAME_IDS } from '../../services/UtilsService';
11
- import { engineGame, EngineGameScreen } from '../shared/EngineGameScreen';
12
- import { scoreColumn, textColumn, timerColumn } from '../shared/EngineHud';
13
- import { useEngineGame } from '../shared/useEngineGame';
14
- import { useLiveState } from '../shared/useLiveState';
15
- import { BOARD_BORDER_WIDTH, GAME_DURATION, getLayout, LIGHT } from './ReversiConstants';
16
- import { createGame, dispose, drag, type GameEvent, reset, setLayout, setTheme, start, tick } from './ReversiGame';
17
-
18
- const SOUNDS = GAME_SOUNDS.REVERSI;
19
-
20
- /** Each event's sound and haptic, as the original version played them. */
21
- const FEEDBACK: Record<GameEvent, { sound?: (typeof SOUNDS)[keyof typeof SOUNDS]; haptic?: HapticType }> = {
22
- place: { sound: SOUNDS.PLACE, haptic: HapticType.MEDIUM },
23
- robot: { sound: SOUNDS.PLACE, haptic: HapticType.LIGHT },
24
- invalid: { sound: SOUNDS.INVALID, haptic: HapticType.LIGHT },
25
- pass: { sound: SOUNDS.PASS },
26
- win: { sound: SOUNDS.WIN, haptic: HapticType.SUCCESS },
27
- lose: { sound: SOUNDS.LOSE, haptic: HapticType.ERROR }
28
- };
29
-
30
- export const Reversi = engineGame(GAME_IDS.REVERSI, (props) => {
31
- const [score, setScore] = useLiveState(0);
32
- const [discs, setDiscs] = useLiveState({ black: 2, white: 2 });
33
- const [time, setTime] = useLiveState(GAME_DURATION);
34
-
35
- // A win when you finish ahead, a loss otherwise (a tie or the clock too)
36
- const { game, theme, status, screen, gameOver } = useEngineGame(props, {
37
- gameId: GAME_IDS.REVERSI,
38
- create: createGame,
39
- start,
40
- reset,
41
- dispose,
42
- tick,
43
- setTheme,
44
- resize: (g, width, height, offset) => {
45
- const l = getLayout(width, height, offset);
46
- setLayout(g, l);
47
- return l.size + BOARD_BORDER_WIDTH * 2;
48
- },
49
- drag,
50
- outcome: (g) => (g.winner === 'black' ? 'win' : 'lose'),
51
- sounds: SOUNDS,
52
- onStart: (fx) => fx(SOUNDS.START, HapticType.MEDIUM),
53
- onOver: (fx, _status, g) => {
54
- if (g.timedOut) fx(SOUNDS.TIME_UP, HapticType.ERROR);
55
- },
56
- wire: (g, fx) => {
57
- g.onScore = setScore;
58
- g.onCounts = (black, white) => setDiscs({ black, white });
59
- g.onTime = setTime;
60
- g.onEvent = (event) => {
61
- if (event === 'lose' && g.winner === null && !g.timedOut) fx(GAME_SOUNDS.DRAW, HapticType.MEDIUM);
62
- else fx(FEEDBACK[event].sound, FEEDBACK[event].haptic);
63
- };
64
- }
65
- });
66
-
67
- const { black, white, timedOut } = game;
68
- const tie = game.winner === null && !timedOut;
69
- const title = status === 'win' ? 'YOU WON!' : tie ? "IT'S A TIE!" : timedOut ? 'TIME UP!' : 'YOU LOST!';
70
- const message =
71
- status === 'win'
72
- ? `You finished ${black}-${white}!`
73
- : tie
74
- ? `Even at ${black}-${white}!`
75
- : timedOut
76
- ? 'You ran out of time!'
77
- : `The robot wins ${white}-${black}!`;
78
-
79
- return (
80
- <EngineGameScreen
81
- {...screen}
82
- light={LIGHT}
83
- columns={[scoreColumn(score), textColumn('YOU-AI', `${discs.black}-${discs.white}`), timerColumn(time, theme)]}
84
- subtext="Outflank the robot!"
85
- gameOver={gameOver({
86
- title,
87
- message,
88
- scoreLabel: 'Score',
89
- score,
90
- buttonText: 'Play Again!'
91
- })}
92
- />
93
- );
94
- });