@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,477 +0,0 @@
1
- // Candy Crush's rules, with no React: build a run with `createGame`, give it a layout, `start` it and
2
- // `tick` it every frame. Swipe a candy into a neighbour; the swap stays if it lines up 3 or more of a
3
- // color (in a row or column), else they bump and go back. Matches clear for 50 a candy, the candies
4
- // above fall into the gaps, new ones drop in, and any matches that makes cascade at 1.25x per step.
5
- // Lining up 5 leaves a color bomb: swap it with any candy to clear every candy of that color.
6
- // Score as much as you can before the timer runs out (every finished run counts as a win).
7
- import { type Camera, type Entity, type Vec3, World } from '@nayan-ui/engine';
8
- import type { GameTheme } from '../../services/ThemeService';
9
- import { introPlayed } from '../shared/EngineUtils';
10
- import {
11
- BOMB,
12
- BOMB_MATCH,
13
- BOMB_MULTIPLIER,
14
- CANDY_TYPES,
15
- CELL_GAP,
16
- CLEAR_RIPPLE,
17
- COMBO_MULTIPLIER,
18
- FALL_SPRING,
19
- FALL_TIME,
20
- GRID_SIZE,
21
- INTRO_COL_STAGGER,
22
- INTRO_ROW_STAGGER,
23
- type Layout,
24
- LIFT_SCALE,
25
- LIFT_SPRING,
26
- MATCH_TIME,
27
- MIN_MATCH,
28
- NUDGE_DISTANCE,
29
- NUDGE_SPRING,
30
- NUDGE_TIME,
31
- POINTS_PER_CANDY,
32
- RETURN_SPRING,
33
- SWAP_TIME,
34
- TIME_LIMIT,
35
- WARNING_TIMES,
36
- ZAP_TIME
37
- } from './CandyCrushConstants';
38
- import {
39
- buildScenery,
40
- candyPosition,
41
- crushCandy,
42
- dragZ,
43
- popInBomb,
44
- removeScenery,
45
- type Scenery,
46
- setSceneryTheme,
47
- spawnCandy,
48
- zap
49
- } from './CandyCrushScene';
50
-
51
- export type Phase = 'ready' | 'playing' | 'over';
52
- export type Direction = 'up' | 'down' | 'left' | 'right';
53
-
54
- type Candy = { type: number; row: number; col: number; root: Entity | null };
55
- type Grid = (Candy | null)[];
56
-
57
- const WORLD_CAPACITY = 1000; // 49 candies (a color bomb is 7 parts), candies on their way out, zaps, scenery, bursts
58
-
59
- const at = (row: number, col: number) => row * GRID_SIZE + col;
60
- const randomType = () => Math.floor(Math.random() * CANDY_TYPES);
61
-
62
- /** Would a candy of `type` at (row, col) line up 3 with what's already placed? */
63
- function wouldMatch(grid: Grid, row: number, col: number, type: number) {
64
- const run = (dr: number, dc: number) => {
65
- let n = 0;
66
- for (let r = row + dr, c = col + dc; r >= 0 && r < GRID_SIZE && c >= 0 && c < GRID_SIZE; r += dr, c += dc) {
67
- if (grid[at(r, c)]?.type !== type) break;
68
- n++;
69
- }
70
- return n;
71
- };
72
- return 1 + run(0, -1) + run(0, 1) >= MIN_MATCH || 1 + run(-1, 0) + run(1, 0) >= MIN_MATCH;
73
- }
74
-
75
- /** A random board with (almost always) no matches to start: each cell gets 10 tries at a safe color. */
76
- function generateGrid(): Grid {
77
- const grid: Grid = new Array(GRID_SIZE * GRID_SIZE).fill(null);
78
- for (let row = 0; row < GRID_SIZE; row++) {
79
- for (let col = 0; col < GRID_SIZE; col++) {
80
- let type = randomType();
81
- for (let tries = 1; tries < 10 && wouldMatch(grid, row, col, type); tries++) type = randomType();
82
- grid[at(row, col)] = { type, row, col, root: null };
83
- }
84
- }
85
- return grid;
86
- }
87
-
88
- /** Every candy in a straight run of 3+ of one color (across rows, then down columns), and the runs of 5+ (each leaves a color bomb). */
89
- function findMatches(grid: Grid): { matched: Candy[]; fives: Candy[][] } {
90
- const found = new Set<Candy>();
91
- const fives: Candy[][] = [];
92
- const scan = (cell: (line: number, i: number) => Candy | null) => {
93
- for (let line = 0; line < GRID_SIZE; line++) {
94
- let i = 0;
95
- while (i < GRID_SIZE) {
96
- const first = cell(line, i);
97
- let end = i + 1;
98
- while (first && first.type !== BOMB && end < GRID_SIZE && cell(line, end)?.type === first.type) end++;
99
- if (first && first.type !== BOMB && end - i >= MIN_MATCH) {
100
- for (let k = i; k < end; k++) found.add(cell(line, k)!);
101
- if (end - i >= BOMB_MATCH) fives.push(Array.from({ length: end - i }, (_, k) => cell(line, i + k)!));
102
- }
103
- i = end;
104
- }
105
- }
106
- };
107
- scan((row, col) => grid[at(row, col)] ?? null);
108
- scan((col, row) => grid[at(row, col)] ?? null);
109
- return { matched: [...found], fives };
110
- }
111
-
112
- export function createGame(theme: GameTheme) {
113
- const world = new World(WORLD_CAPACITY);
114
- const camera: Camera = { eye: [0, 0, 400], target: [0, 0, 0], fov: 1, ortho: 1 };
115
- const g = {
116
- world,
117
- camera,
118
- theme,
119
- layout: null as Layout | null,
120
- scenery: null as Scenery | null,
121
- phase: 'ready' as Phase,
122
- /** Score and the countdown live in the engine (Rust), advanced by world.update. */
123
- get score() {
124
- return world.scoreboard.score;
125
- },
126
- get timeLeft() {
127
- return world.scoreboard.shownSeconds;
128
- },
129
- /** Game clock, seconds: drives the delayed steps (they pause with the frame loop). */
130
- time: 0,
131
- grid: generateGrid(),
132
- /** A swap is resolving (matches, falls, cascades): no new moves until it settles. */
133
- busy: false,
134
- combo: 0,
135
- /** The candy under the finger. */
136
- dragging: null as Candy | null,
137
- /** The next board to appear rains in. */
138
- intro: true,
139
- /** Game seconds the current intro has been playing (-1 until its board spawns). */
140
- introAge: -1,
141
- // UI hooks, set by the screen.
142
- onPhase: (_p: Phase) => {},
143
- onScore: (_s: number) => {},
144
- onTime: (_t: number) => {},
145
- onSelect: () => {},
146
- onSwap: () => {},
147
- onInvalid: () => {},
148
- onMatch: (_combo: number) => {},
149
- /** A color bomb was made. */
150
- onBomb: () => {},
151
- /** A color bomb went off. */
152
- onBlast: () => {},
153
- onWarning: (_secondsLeft: number) => {},
154
- onTimeUp: () => {}
155
- };
156
- world.scoreboard.reset(0, TIME_LIMIT);
157
- world.scoreboard.handlers = {
158
- onSecond: (t) => {
159
- g.onTime(t);
160
- if (t > 0 && (WARNING_TIMES as readonly number[]).includes(t)) g.onWarning(t);
161
- },
162
- onTimeUp: () => g.phase === 'playing' && end(g)
163
- };
164
- return g;
165
- }
166
- export type Game = ReturnType<typeof createGame>;
167
-
168
- const after = (g: Game, seconds: number, run: () => void) => g.world.after(seconds, run);
169
-
170
- // ── Scene ─────────────────────────────────────────────────────────────
171
-
172
- /** Lays the scene out for the view (first layout, header height, rotation): rebuilt from the run's state. */
173
- export function setLayout(g: Game, l: Layout) {
174
- if (g.scenery) removeScenery(g.world, g.scenery);
175
- g.layout = l;
176
- g.camera.ortho = l.height / 2;
177
- g.scenery = buildScenery(g.world, l, g.theme);
178
- g.dragging = null;
179
- spawnAll(g);
180
- }
181
-
182
- /** A new theme: the background and board are repainted; the candies and the run carry on. */
183
- export function setTheme(g: Game, theme: GameTheme) {
184
- g.theme = theme;
185
- if (g.layout && g.scenery && !g.world.isDisposed) setSceneryTheme(g.world, g.layout, g.scenery, theme);
186
- }
187
-
188
- function despawnCandy(g: Game, c: Candy) {
189
- if (c.root != null) g.world.despawn(c.root); // its parts go with it
190
- c.root = null;
191
- }
192
-
193
- /** (Re)creates every candy at its cell; a new board rains in, column by column, bottom rows first. */
194
- function spawnAll(g: Game) {
195
- const l = g.layout;
196
- if (!l) return;
197
- const intro = g.intro;
198
- if (intro) g.introAge = 0;
199
- for (const c of g.grid) {
200
- if (!c) continue;
201
- despawnCandy(g, c);
202
- if (!intro) {
203
- c.root = spawnCandy(g.world, l, c.type, candyPosition(l, c.row, c.col), 1);
204
- continue;
205
- }
206
- c.root = spawnCandy(g.world, l, c.type, candyPosition(l, c.row - 2, c.col), 0);
207
- const delay = c.col * INTRO_COL_STAGGER + (GRID_SIZE - 1 - c.row) * INTRO_ROW_STAGGER;
208
- g.world.animate(c.root, { position: candyPosition(l, c.row, c.col) }, { spring: FALL_SPRING, delay });
209
- g.world.animate(c.root, { scale: 1 }, { duration: FALL_TIME * 0.6, delay, easing: 'back' });
210
- }
211
- }
212
-
213
- // ── Run ───────────────────────────────────────────────────────────────
214
-
215
- export function start(g: Game) {
216
- if (g.phase !== 'ready') return;
217
- g.phase = 'playing';
218
- g.world.scoreboard.startCountdown(TIME_LIMIT);
219
- g.onPhase('playing');
220
- }
221
-
222
- /** A new board and timer (Stop, Play Again). The world, and the GPU view drawing it, are kept. */
223
- export function reset(g: Game) {
224
- g.world.cancelTimers(); // a cascade in progress stops here, so it can't touch the new board
225
- for (const c of g.grid) if (c) despawnCandy(g, c);
226
- g.grid = generateGrid();
227
- g.busy = false;
228
- g.combo = 0;
229
- g.dragging = null;
230
- g.intro = true;
231
- spawnAll(g);
232
- g.world.scoreboard.reset(0, TIME_LIMIT);
233
- g.phase = 'ready';
234
- g.onScore(0);
235
- g.onTime(TIME_LIMIT);
236
- g.onPhase('ready');
237
- }
238
-
239
- export function dispose(g: Game) {
240
- g.world.cancelTimers();
241
- g.world.dispose();
242
- }
243
-
244
- /** Time up. A cascade still resolving plays out on screen, but scores no more. */
245
- function end(g: Game) {
246
- g.world.scoreboard.stop();
247
- if (g.dragging) release(g);
248
- g.phase = 'over';
249
- g.onTimeUp();
250
- g.onPhase('over');
251
- }
252
-
253
- export function tick(g: Game, dt: number) {
254
- if (g.world.isDisposed) return;
255
- introPlayed(g, dt);
256
- g.time += dt;
257
- g.world.update(dt);
258
- }
259
-
260
- // ── Touch ─────────────────────────────────────────────────────────────
261
-
262
- /** The board cell under a view point, or null (cells own the gap after them, as on the original board). */
263
- function cellAt(l: Layout, x: number, y: number): [number, number] | null {
264
- const col = Math.floor((x - l.boardLeft - CELL_GAP) / l.step);
265
- const row = Math.floor((y - l.boardTop - CELL_GAP) / l.step);
266
- return row < 0 || row >= GRID_SIZE || col < 0 || col >= GRID_SIZE ? null : [row, col];
267
- }
268
-
269
- /** Finger down: the candy under it lifts and follows the finger. */
270
- export function touchStart(g: Game, x: number, y: number) {
271
- const l = g.layout;
272
- if (!l || g.phase !== 'playing' || g.busy) return;
273
- const cell = cellAt(l, x, y);
274
- const candy = cell ? g.grid[at(cell[0], cell[1])] : null;
275
- if (!candy || candy.root == null) return;
276
- g.dragging = candy;
277
- g.onSelect();
278
- g.world.stopAnimation(candy.root);
279
- g.world.set(candy.root, { position: candyPosition(l, candy.row, candy.col, dragZ(l)) });
280
- g.world.animate(candy.root, { scale: LIFT_SCALE }, { spring: LIFT_SPRING });
281
- }
282
-
283
- export function touchMove(g: Game, dx: number, dy: number) {
284
- const l = g.layout;
285
- const c = g.dragging;
286
- if (!l || !c || c.root == null) return;
287
- const home = candyPosition(l, c.row, c.col, dragZ(l));
288
- g.world.set(c.root, { position: [home[0] + dx, home[1] - dy, home[2]] });
289
- }
290
-
291
- /** Finger up: a long enough drag swaps toward its main direction; otherwise the candy settles back. */
292
- export function touchEnd(g: Game, dx: number, dy: number, cancelled = false) {
293
- const c = g.dragging;
294
- const l = g.layout;
295
- if (!c || !l) return;
296
- g.dragging = null;
297
- const ax = Math.abs(dx);
298
- const ay = Math.abs(dy);
299
- if (!cancelled && g.phase === 'playing' && Math.max(ax, ay) > l.swipeThreshold) {
300
- swap(g, c, ax > ay ? (dx > 0 ? 'right' : 'left') : dy > 0 ? 'down' : 'up');
301
- } else {
302
- settle(g, c);
303
- }
304
- }
305
-
306
- function release(g: Game) {
307
- const c = g.dragging;
308
- g.dragging = null;
309
- if (c) settle(g, c);
310
- }
311
-
312
- /** Springs a candy back to its cell at rest size. */
313
- function settle(g: Game, c: Candy) {
314
- const l = g.layout;
315
- if (!l || c.root == null) return;
316
- g.world.animate(c.root, { position: candyPosition(l, c.row, c.col) }, { spring: RETURN_SPRING });
317
- g.world.animate(c.root, { scale: 1 }, { spring: RETURN_SPRING });
318
- }
319
-
320
- const STEP: Record<Direction, [number, number]> = { up: [-1, 0], down: [1, 0], left: [0, -1], right: [0, 1] };
321
-
322
- function place(g: Game, c: Candy, row: number, col: number) {
323
- c.row = row;
324
- c.col = col;
325
- g.grid[at(row, col)] = c;
326
- }
327
-
328
- function swap(g: Game, a: Candy, dir: Direction) {
329
- const l = g.layout!;
330
- const w = g.world;
331
- const [dr, dc] = STEP[dir];
332
- const row = a.row + dr;
333
- const col = a.col + dc;
334
- const b = row >= 0 && row < GRID_SIZE && col >= 0 && col < GRID_SIZE ? g.grid[at(row, col)] : null;
335
- if (!b || g.busy) {
336
- if (!b && !g.busy) g.onInvalid();
337
- settle(g, a);
338
- return;
339
- }
340
- const [ar, ac] = [a.row, a.col];
341
- place(g, a, row, col);
342
- place(g, b, ar, ac);
343
- const bomb = a.type === BOMB ? a : b.type === BOMB ? b : null;
344
-
345
- if (bomb || findMatches(g.grid).matched.length) {
346
- // The two glide past each other (the dragged one from under the finger), then the board resolves.
347
- g.busy = true;
348
- g.combo = 0;
349
- if (a.root != null) {
350
- w.animate(a.root, { position: candyPosition(l, a.row, a.col) }, { duration: SWAP_TIME, easing: 'easeOut' });
351
- w.animate(a.root, { scale: 1 }, { spring: RETURN_SPRING });
352
- }
353
- if (b.root != null) w.animate(b.root, { position: candyPosition(l, b.row, b.col) }, { duration: SWAP_TIME, easing: 'easeOut' });
354
- g.onSwap();
355
- after(g, SWAP_TIME, () => (bomb ? blastColor(g, bomb, bomb === a ? b : a) : resolve(g, [a, b])));
356
- return;
357
- }
358
-
359
- // No match: undo it. The dragged candy springs home and the other bumps toward it and back.
360
- place(g, b, row, col);
361
- place(g, a, ar, ac);
362
- settle(g, a);
363
- const root = b.root;
364
- if (root != null) {
365
- const home = candyPosition(l, b.row, b.col);
366
- const bump: Vec3 = [home[0] - dc * NUDGE_DISTANCE * l.step, home[1] + dr * NUDGE_DISTANCE * l.step, home[2]];
367
- w.animate(root, { position: bump }, { duration: NUDGE_TIME, easing: 'easeOut' }).then(() => {
368
- if (b.root === root && g.dragging !== b) w.animate(root, { position: home }, { spring: NUDGE_SPRING });
369
- });
370
- }
371
- g.onInvalid();
372
- }
373
-
374
- // ── Resolving ─────────────────────────────────────────────────────────
375
-
376
- /**
377
- * Clears the board's matches, scores them, then drops candies in; repeats until nothing matches. Each
378
- * run of 5+ leaves a color bomb: where the swapped candy (`moved`) landed, else in the run's middle.
379
- */
380
- function resolve(g: Game, moved: readonly Candy[] = []) {
381
- const l = g.layout;
382
- const { matched, fives } = findMatches(g.grid);
383
- if (!l || !matched.length) {
384
- g.busy = false;
385
- g.combo = 0;
386
- return;
387
- }
388
- g.combo++;
389
- if (g.phase === 'playing') {
390
- g.onScore(g.world.scoreboard.add(Math.floor(matched.length * POINTS_PER_CANDY * Math.pow(COMBO_MULTIPLIER, g.combo - 1))));
391
- }
392
- g.onMatch(g.combo);
393
-
394
- const bombs = new Set(fives.map((run) => run.find((c) => moved.includes(c)) ?? run[Math.floor(run.length / 2)]!));
395
- const w = g.world;
396
- // Clears ripple out from where the swap landed (a cascade's, from its first match), as in Block Blast
397
- const origin = moved.find((c) => matched.includes(c)) ?? matched[0]!;
398
- for (const c of matched) {
399
- if (bombs.has(c)) continue;
400
- g.grid[at(c.row, c.col)] = null;
401
- crush(g, l, c, Math.hypot(c.row - origin.row, c.col - origin.col) * CLEAR_RIPPLE);
402
- }
403
- for (const c of bombs) {
404
- if (c.root != null) w.despawn(c.root);
405
- c.type = BOMB;
406
- c.root = spawnCandy(w, l, BOMB, candyPosition(l, c.row, c.col), 1);
407
- popInBomb(w, c.root);
408
- }
409
- if (bombs.size) g.onBomb();
410
- const ripple = Math.max(...matched.map((c) => Math.hypot(c.row - origin.row, c.col - origin.col))) * CLEAR_RIPPLE;
411
- after(g, MATCH_TIME + ripple, () => {
412
- drop(g);
413
- after(g, FALL_TIME, () => resolve(g));
414
- });
415
- }
416
-
417
- /** A candy leaves the board: it crushes (after `delay`) and is despawned once gone. */
418
- function crush(g: Game, l: Layout, c: Candy, delay: number) {
419
- const root = c.root;
420
- c.root = null;
421
- if (root == null) return;
422
- crushCandy(g.world, l, root, c.type, candyPosition(l, c.row, c.col), MATCH_TIME * 0.95, delay).then(() => {
423
- g.world.despawn(root);
424
- });
425
- }
426
-
427
- /**
428
- * A color bomb swapped with a candy: every candy of that color is zapped and crushed with the bomb
429
- * (another bomb: every candy on the board), at double points; then the board falls and resolves.
430
- */
431
- function blastColor(g: Game, bomb: Candy, other: Candy) {
432
- const l = g.layout;
433
- if (!l) return;
434
- const all = other.type === BOMB;
435
- const targets = g.grid.filter((c): c is Candy => !!c && c !== bomb && (all || c.type === other.type));
436
- g.combo = 1;
437
- if (g.phase === 'playing') g.onScore(g.world.scoreboard.add((targets.length + 1) * POINTS_PER_CANDY * BOMB_MULTIPLIER));
438
- g.onBlast();
439
- const from = candyPosition(l, bomb.row, bomb.col);
440
- const stagger = Math.min(0.012, 0.3 / Math.max(1, targets.length));
441
- targets.forEach((c, i) => {
442
- zap(g.world, l, from, candyPosition(l, c.row, c.col), all ? BOMB : c.type, i * stagger);
443
- g.grid[at(c.row, c.col)] = null;
444
- crush(g, l, c, ZAP_TIME + i * stagger);
445
- });
446
- g.grid[at(bomb.row, bomb.col)] = null;
447
- crush(g, l, bomb, ZAP_TIME);
448
- after(g, ZAP_TIME + targets.length * stagger + MATCH_TIME, () => {
449
- drop(g);
450
- after(g, FALL_TIME, () => resolve(g));
451
- });
452
- }
453
-
454
- /** Gravity per column: the candies left fall to the bottom, new ones grow in as they drop into the top. */
455
- function drop(g: Game) {
456
- const l = g.layout;
457
- if (!l) return;
458
- const w = g.world;
459
- for (let col = 0; col < GRID_SIZE; col++) {
460
- let row = GRID_SIZE - 1;
461
- for (let r = GRID_SIZE - 1; r >= 0; r--) {
462
- const c = g.grid[at(r, col)];
463
- if (!c) continue;
464
- g.grid[at(r, col)] = null;
465
- place(g, c, row, col);
466
- if (r !== row && c.root != null) w.animate(c.root, { position: candyPosition(l, row, col) }, { spring: FALL_SPRING });
467
- row--;
468
- }
469
- for (; row >= 0; row--) {
470
- const c: Candy = { type: randomType(), row, col, root: null };
471
- g.grid[at(row, col)] = c;
472
- c.root = spawnCandy(w, l, c.type, candyPosition(l, row - 1, col), 0);
473
- w.animate(c.root, { position: candyPosition(l, row, col) }, { spring: FALL_SPRING });
474
- w.animate(c.root, { scale: 1 }, { duration: FALL_TIME * 0.6, easing: 'back' });
475
- }
476
- }
477
- }
@@ -1,209 +0,0 @@
1
- // Everything Candy Crush draws. Orthographic camera, one world unit per point, looking down -z: x right
2
- // and y up from the view's centre. Depth (toward the camera): the game background, the board panel and
3
- // its empty cells, the candies, a dragged candy. Each candy is an invisible root at its cell's centre
4
- // carrying a matte raised block (shared/EngineBlocks, as Block Blast's, without its gloss or shadow),
5
- // so moves, swells and shrinks animate the root alone. Every part is a shared mesh: mesh ids are
6
- // app-wide and limited. The engine doesn't clip, so new candies grow in as they drop rather
7
- // than fall from behind the board's top edge.
8
- import { type Color, type Entity, extrude, loft, type Model, Path, quat, type Vec3, type World } from '@nayan-ui/engine';
9
- import type { GameTheme } from '../../services/ThemeService';
10
- import { setBackdropTheme, spawnBackdrop } from '../shared/EngineBackdrop';
11
- import { popAndBurst } from '../shared/EngineBlasts';
12
- import { spawnRaisedBlock } from '../shared/EngineBlocks';
13
- import { cacheGameAsset, createGameMesh as createShape } from '../shared/EngineMeshes';
14
- import { toColor } from '../shared/EngineUtils';
15
- import {
16
- BOMB,
17
- CANDY_COLORS,
18
- CELL_GAP,
19
- cellCenter,
20
- CLASSIC_BOARD,
21
- CLASSIC_BORDER,
22
- CLASSIC_CELL,
23
- CLASSIC_RADIUS,
24
- GRID_SIZE,
25
- type Layout,
26
- THEMED_RADIUS
27
- } from './CandyCrushConstants';
28
-
29
- const Z_BACKDROP = -20;
30
- const Z_BOARD = 0;
31
- const Z_CELLS = 0.2;
32
- const Z_RIM = 0.4;
33
-
34
- /** A view point (from the top-left) at depth `z`, in world space. */
35
- export const toWorld = (l: Layout, x: number, y: number, z = 0): Vec3 => [x - l.width / 2, l.height / 2 - y, z];
36
-
37
- const candyDepth = (l: Layout) => l.cell * 0.4;
38
- const candyZ = (l: Layout) => Z_RIM + candyDepth(l) / 2 + 1;
39
- export const dragZ = (l: Layout) => candyZ(l) + candyDepth(l) * 2;
40
-
41
- /** Where the candy at (row, col) rests (row may be negative: above the board). */
42
- export const candyPosition = (l: Layout, row: number, col: number, z = candyZ(l)): Vec3 => {
43
- const [x, y] = cellCenter(l, row, col);
44
- return toWorld(l, x, y, z);
45
- };
46
-
47
- // ── Meshes (registered once per size: mesh ids are app-wide and limited) ──
48
-
49
- const meshes = new Map<string, Model>();
50
- const mesh = (key: string, build: () => Model) => {
51
- let m = meshes.get(key);
52
- if (!m) {
53
- m = cacheGameAsset('candy-crush/CandyCrushScene:' + key, build);
54
- meshes.set(key, m);
55
- }
56
- return m;
57
- };
58
- /** A flat rounded square from its top-left; with `rim`, only its outline. */
59
- const panelMesh = (size: number, radius: number, rim = 0) =>
60
- mesh(`panel:${size}:${radius}:${rim}`, () => {
61
- const path = new Path().addRoundedRect(0, 0, size, size, radius);
62
- if (rim > 0) path.addRoundedRect(rim, rim, size - rim * 2, size - rim * 2, radius - rim);
63
- return createShape(extrude(path, { depth: 0, fillRule: 'evenodd' }), { center: false });
64
- });
65
- /** All 49 empty cells in one flat mesh, from the board's top-left. */
66
- const cellsMesh = (l: Layout) =>
67
- mesh(`candy-cells:${l.cell}`, () => {
68
- const path = new Path();
69
- for (let r = 0; r < GRID_SIZE; r++)
70
- for (let c = 0; c < GRID_SIZE; c++) path.addRoundedRect(CELL_GAP + c * l.step, CELL_GAP + r * l.step, l.cell, l.cell, l.cell * 0.2);
71
- return createShape(extrude(path, { depth: 0 }), { center: false });
72
- });
73
-
74
- // ── Board ─────────────────────────────────────────────────────────────
75
-
76
- export type Scenery = { backdrop: Entity; parts: Entity[] };
77
-
78
- /** The board panel, its empty cells and its border, for a theme. */
79
- function spawnBoard(world: World, l: Layout, theme: GameTheme): Entity[] {
80
- const classic = theme.mode === 'classic';
81
- const radius = classic ? CLASSIC_RADIUS : THEMED_RADIUS;
82
- const origin = (z: number) => toWorld(l, l.boardLeft, l.boardTop, z);
83
- const flat = (m: Model, z: number, color: string) => world.spawn({ mesh: m, position: origin(z), color: toColor(color), pickable: false });
84
- return [
85
- flat(panelMesh(l.boardSize, radius), Z_BOARD, classic ? CLASSIC_BOARD : theme.BOARD.SURFACE),
86
- flat(cellsMesh(l), Z_CELLS, classic ? CLASSIC_CELL : theme.BOARD.CELL_EMPTY),
87
- flat(panelMesh(l.boardSize, radius, 1.5), Z_RIM, classic ? CLASSIC_BORDER : theme.BOARD.BORDER)
88
- ];
89
- }
90
-
91
- export function buildScenery(world: World, l: Layout, theme: GameTheme): Scenery {
92
- return { backdrop: spawnBackdrop(world, l.width, l.height, Z_BACKDROP, theme), parts: spawnBoard(world, l, theme) };
93
- }
94
-
95
- export function removeScenery(world: World, s: Scenery) {
96
- world.despawn(s.backdrop);
97
- for (const e of s.parts) world.despawn(e);
98
- }
99
-
100
- /** A new theme: the background is repainted and the board rebuilt in its colors. */
101
- export function setSceneryTheme(world: World, l: Layout, s: Scenery, theme: GameTheme) {
102
- setBackdropTheme(world, s.backdrop, theme);
103
- for (const e of s.parts) world.despawn(e);
104
- s.parts = spawnBoard(world, l, theme);
105
- }
106
-
107
- // ── Candies ───────────────────────────────────────────────────────────
108
-
109
- const BODY = CANDY_COLORS.map((c) => toColor(c));
110
- const WHITE: Color = [1, 1, 1, 1];
111
- const BOMB_BURST: Color = [1, 0.85, 0.4, 1];
112
- const WHITE_HOT: Color = [2, 2, 2, 1]; // above 1 glows, as the shared pop's flash
113
- /** Each candy's block (by its root), which flashes as the candy pops. */
114
- const blocks = new Map<Entity, Entity>();
115
- export const candyColor = (type: number) => (type === BOMB ? BOMB_BURST : BODY[type % BODY.length]!);
116
-
117
- let bomb: Model | null = null;
118
- /**
119
- * The color bomb's block: the same bevelled block as the others, its colors baked in, blending smoothly
120
- * from one block color at each corner (top-left, top-right, bottom-right, bottom-left) to the next.
121
- */
122
- function bombMesh(): Model {
123
- if (bomb) return bomb;
124
- const corner = (i: number) => BODY[i % BODY.length]!;
125
- const [tl, tr, br, bl] = [corner(0), corner(1), corner(2), corner(3)];
126
- const lerp = (a: Color, b: Color, t: number): Color => [a[0] + (b[0] - a[0]) * t, a[1] + (b[1] - a[1]) * t, a[2] + (b[2] - a[2]) * t, 1];
127
- const blend = ([x, y]: Vec3): Color => {
128
- const u = Math.max(0, Math.min(1, x + 0.5));
129
- const v = Math.max(0, Math.min(1, y + 0.5));
130
- return lerp(lerp(bl, br, u), lerp(tl, tr, u), v);
131
- };
132
- bomb = createShape(
133
- loft(
134
- [
135
- { z: -0.5, bottom: -0.5, top: 0.5, width: 0.5, square: 7 },
136
- { z: 0.2, bottom: -0.5, top: 0.5, width: 0.5, square: 7 },
137
- { z: 0.4, bottom: -0.465, top: 0.465, width: 0.465, square: 6.5 },
138
- { z: 0.5, bottom: -0.39, top: 0.39, width: 0.39, square: 5.5 }
139
- ],
140
- { around: 64, smoothness: 3, color: blend }
141
- ),
142
- { center: false }
143
- );
144
- return bomb;
145
- }
146
-
147
- /**
148
- * A candy at view-world `position`, `scale` of full size. A color bomb is a block blending all the
149
- * colors, gently pulsing so it stands out.
150
- */
151
- export function spawnCandy(world: World, l: Layout, type: number, position: Vec3, scale: number): Entity {
152
- const size = l.cell - 4; // the original body's 2 point inset
153
- const depth = candyDepth(l);
154
- const root = world.spawn({ mesh: 'none', position, scale, pickable: false });
155
- if (type !== BOMB) {
156
- blocks.set(
157
- root,
158
- spawnRaisedBlock(world, { parent: root, position: [0, 0, 0], size: [size, size, depth], color: candyColor(type), gloss: false, shadow: false })
159
- );
160
- return root;
161
- }
162
- const block = world.spawn({ mesh: bombMesh(), parent: root, scale: [size, size, depth], color: WHITE, pickable: false });
163
- blocks.set(root, block);
164
- world.animate(block, { scale: [size * 1.07, size * 1.07, depth] }, { duration: 0.5, repeat: 'forever', yoyo: true, easing: 'easeInOut' });
165
- return root;
166
- }
167
-
168
- /** A color bomb just made: it grows in where its match was, with a little overshoot. */
169
- export function popInBomb(world: World, root: Entity) {
170
- world.animate(root, [{ scale: 0.3 }, { scale: 1.25, at: 0.6 }, { scale: 1 }], { duration: 0.35, easing: 'easeOut' });
171
- }
172
-
173
- /** A thin zap from a color bomb to a block it clears, fading. */
174
- export function zap(world: World, l: Layout, from: Vec3, to: Vec3, type: number, delay: number) {
175
- const dx = to[0] - from[0];
176
- const dy = to[1] - from[1];
177
- const angle = Math.atan2(dy, dx);
178
- const length = Math.hypot(dx, dy);
179
- const [r, g, b] = type === BOMB ? [1, 1, 1] : candyColor(type);
180
- const z = from[2] + candyDepth(l);
181
- world.after(delay, () => {
182
- const bar = world.spawn({
183
- mesh: 'cube',
184
- position: [(from[0] + to[0]) / 2, (from[1] + to[1]) / 2, z],
185
- rotation: quat.z(angle),
186
- scale: [length, l.cell * 0.08, 1],
187
- color: [r, g, b, 0.9],
188
- pickable: false
189
- });
190
- world.animate(bar, { scale: [length, 0.01, 1], color: [r, g, b, 0] }, { duration: 0.3 }).then(() => {
191
- if (world.has(bar)) world.despawn(bar);
192
- });
193
- });
194
- }
195
-
196
- /** A matched candy pops as Block Blast's blocks do (shared/EngineBlasts): it swells, flashes white, settles and shrinks away, bursting in its color over a fading glow. Resolves when it's gone. */
197
- export function crushCandy(world: World, l: Layout, root: Entity, type: number, at: Vec3, duration: number, delay = 0): Promise<void> {
198
- const color = type === BOMB ? BOMB_BURST : candyColor(type);
199
- const block = blocks.get(root);
200
- blocks.delete(root);
201
- if (block != null)
202
- world.animate(block, [{ color: WHITE_HOT, at: 0.33 }, { color: type === BOMB ? WHITE : color }], { duration: duration * 0.3, delay });
203
- return popAndBurst(
204
- world,
205
- root,
206
- { scale: 1, delay, duration },
207
- { position: [at[0], at[1], at[2] + candyDepth(l)], size: l.cell, color, glowZ: Z_RIM + 0.2 }
208
- );
209
- }