@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.
- package/lib/module/games/arrows/Arrows.js +1 -1
- package/lib/module/games/arrows/ArrowsScene.js +1 -1
- package/lib/module/games/balloon-blaster/BalloonBlaster.js +1 -1
- package/lib/module/games/balloon-blaster/BalloonBlasterScene.js +1 -1
- package/lib/module/games/bike-racing/BikeMeshes.js +1 -1
- package/lib/module/games/bike-racing/BikeRacing.js +1 -1
- package/lib/module/games/bike-racing/BikeRacingConstants.js +1 -1
- package/lib/module/games/bike-racing/BikeRacingScene.js +1 -1
- package/lib/module/games/block-blast/BlockBlast.js +1 -1
- package/lib/module/games/block-blast/BlockBlastScene.js +1 -1
- package/lib/module/games/block-breaker/BlockBreaker.js +1 -1
- package/lib/module/games/block-breaker/BlockBreakerScene.js +1 -1
- package/lib/module/games/bluk/Bluk.js +1 -1
- package/lib/module/games/bluk/BlukScene.js +1 -1
- package/lib/module/games/bubble-shooter/BubbleShooter.js +1 -1
- package/lib/module/games/bubble-shooter/BubbleShooterScene.js +1 -1
- package/lib/module/games/candy-crush/CandyCrush.js +1 -1
- package/lib/module/games/candy-crush/CandyCrushScene.js +1 -1
- package/lib/module/games/car-racing/CarMeshes.js +1 -1
- package/lib/module/games/car-racing/CarRacing.js +1 -1
- package/lib/module/games/car-racing/CarRacingScene.js +1 -1
- package/lib/module/games/chameleon-run/ChameleonRun.js +1 -1
- package/lib/module/games/chameleon-run/ChameleonRunBackdrop.js +1 -1
- package/lib/module/games/chameleon-run/ChameleonRunMeshes.js +1 -1
- package/lib/module/games/checkers/Checkers.js +1 -1
- package/lib/module/games/checkers/CheckersScene.js +1 -1
- package/lib/module/games/color-switch/ColorSwitch.js +1 -1
- package/lib/module/games/color-switch/ColorSwitchScene.js +1 -1
- package/lib/module/games/colors-sort/ColorsSort.js +1 -1
- package/lib/module/games/colors-sort/ColorsSortScene.js +1 -1
- package/lib/module/games/connect-em-all/ConnectEmAll.js +1 -1
- package/lib/module/games/connect-em-all/ConnectEmAllScene.js +1 -1
- package/lib/module/games/crossy-road/CrossyRoad.js +1 -1
- package/lib/module/games/crossy-road/CrossyRoadMeshes.js +1 -1
- package/lib/module/games/crossy-road/CrossyRoadPerson.js +1 -1
- package/lib/module/games/dino-jump/DinoJump.js +1 -1
- package/lib/module/games/dino-jump/DinoJumpScene.js +1 -1
- package/lib/module/games/dots-and-boxes/DotsAndBoxes.js +1 -1
- package/lib/module/games/dots-and-boxes/DotsAndBoxesScene.js +1 -1
- package/lib/module/games/falling-sticks/FallingSticks.js +1 -1
- package/lib/module/games/falling-sticks/FallingSticksScene.js +1 -1
- package/lib/module/games/find-different-number/FindDifferentNumber.js +1 -1
- package/lib/module/games/find-different-number/FindDifferentNumberScene.js +1 -1
- package/lib/module/games/flappy-bird/FlappyBird.js +1 -1
- package/lib/module/games/flappy-bird/FlappyBirdScene.js +1 -1
- package/lib/module/games/fruit-merger/FruitMerger.js +1 -1
- package/lib/module/games/fruit-merger/FruitMergerScene.js +1 -1
- package/lib/module/games/fruit-ninja/FruitNinja.js +1 -1
- package/lib/module/games/fruit-ninja/FruitNinjaScene.js +1 -1
- package/lib/module/games/fruit-ninja/FruitNinjaWorld.js +1 -1
- package/lib/module/games/game-2048/Game2048.js +1 -1
- package/lib/module/games/game-2048/Game2048Scene.js +1 -1
- package/lib/module/games/knife-hit/KnifeHit.js +1 -1
- package/lib/module/games/knife-hit/KnifeHitScene.js +1 -1
- package/lib/module/games/ludo-king/LudoKing.js +1 -1
- package/lib/module/games/ludo-king/LudoKingScene.js +1 -1
- package/lib/module/games/maze-runner/MazeRunner.js +1 -1
- package/lib/module/games/maze-runner/MazeRunnerScene.js +1 -1
- package/lib/module/games/memory-match/MemoryMatch.js +1 -1
- package/lib/module/games/memory-match/MemoryMatchScene.js +1 -1
- package/lib/module/games/mine-sweeper/MineSweeper.js +1 -1
- package/lib/module/games/mine-sweeper/MineSweeperScene.js +1 -1
- package/lib/module/games/mob-control/MobControl.js +1 -1
- package/lib/module/games/mob-control/MobControlGame.js +1 -1
- package/lib/module/games/mob-control/MobControlMeshes.js +1 -1
- package/lib/module/games/mob-control/MobControlRenderer.js +1 -1
- package/lib/module/games/mob-control/MobControlRules.js +1 -1
- package/lib/module/games/mob-control/MobControlScene.js +1 -1
- package/lib/module/games/nuts-and-bolts/NutsAndBolts.js +1 -1
- package/lib/module/games/nuts-and-bolts/NutsAndBoltsScene.js +1 -1
- package/lib/module/games/pac-man/PacMan.js +1 -1
- package/lib/module/games/pac-man/PacManGame.js +1 -1
- package/lib/module/games/pac-man/PacManScene.js +1 -1
- package/lib/module/games/paper-io/PaperIo.js +1 -1
- package/lib/module/games/paper-io/PaperIoMeshes.js +1 -1
- package/lib/module/games/paper-io/PaperIoScene.js +1 -1
- package/lib/module/games/penguin-run/PenguinMeshes.js +1 -1
- package/lib/module/games/penguin-run/PenguinRun.js +1 -1
- package/lib/module/games/penguin-run/PenguinRunScene.js +1 -1
- package/lib/module/games/perfect-circle/PerfectCircle.js +1 -1
- package/lib/module/games/perfect-circle/PerfectCircleScene.js +1 -1
- package/lib/module/games/pipe-connect/PipeConnect.js +1 -1
- package/lib/module/games/pipe-connect/PipeConnectScene.js +1 -1
- package/lib/module/games/play-with-tua/PlayWithTua.js +1 -1
- package/lib/module/games/popit-fidget/PopitFidget.js +1 -1
- package/lib/module/games/popit-fidget/PopitFidgetScene.js +1 -1
- package/lib/module/games/reversi/Reversi.js +1 -1
- package/lib/module/games/reversi/ReversiScene.js +1 -1
- package/lib/module/games/search-grid/SearchGrid.js +1 -1
- package/lib/module/games/search-grid/SearchGridScene.js +1 -1
- package/lib/module/games/shared/BackdropCard.js +1 -1
- package/lib/module/games/shared/EngineBackdrop.js +1 -1
- package/lib/module/games/shared/EngineBlasts.js +1 -1
- package/lib/module/games/shared/EngineBlocks.js +1 -1
- package/lib/module/games/shared/EngineDice.js +1 -1
- package/lib/module/games/shared/EngineFruits.js +1 -1
- package/lib/module/games/shared/EngineGameLoader.js +1 -1
- package/lib/module/games/shared/EngineGameScreen.js +1 -1
- package/lib/module/games/shared/EngineGlyphs.js +1 -1
- package/lib/module/games/shared/EngineHud.js +1 -1
- package/lib/module/games/shared/EngineMeadow.js +1 -1
- package/lib/module/games/shared/EngineTouchSurface.js +1 -1
- package/lib/module/games/shared/GameActivity.js +1 -1
- package/lib/module/games/shared/GameLoading.js +1 -1
- package/lib/module/games/shared/GameLoadingTransition.js +1 -1
- package/lib/module/games/sliding-numbers/SlidingNumbers.js +1 -1
- package/lib/module/games/sliding-numbers/SlidingNumbersScene.js +1 -1
- package/lib/module/games/snake-3d/Snake3D.js +1 -1
- package/lib/module/games/snake-3d/Snake3DScene.js +1 -1
- package/lib/module/games/snakes-and-ladders/SnakesAndLadders.js +1 -1
- package/lib/module/games/snakes-and-ladders/SnakesAndLaddersScene.js +1 -1
- package/lib/module/games/space-fighter/SpaceFighter.js +1 -1
- package/lib/module/games/space-fighter/SpaceFighterScene.js +1 -1
- package/lib/module/games/spider-solitaire/SpiderSolitaire.js +1 -1
- package/lib/module/games/spider-solitaire/SpiderSolitaireScene.js +1 -1
- package/lib/module/games/stack-tower/StackTower.js +1 -1
- package/lib/module/games/stack-tower/StackTowerScene.js +1 -1
- package/lib/module/games/sudoku/Sudoku.js +1 -1
- package/lib/module/games/sudoku/SudokuScene.js +1 -1
- package/lib/module/games/tangram/Tangram.js +1 -1
- package/lib/module/games/tangram/TangramScene.js +1 -1
- package/lib/module/games/tank-1990/Tank1990.js +1 -1
- package/lib/module/games/tank-1990/Tank1990Scene.js +1 -1
- package/lib/module/games/tic-tac-toe/TicTacToe.js +1 -1
- package/lib/module/games/tic-tac-toe/TicTacToeScene.js +1 -1
- package/lib/module/games/tile-home/TileHome.js +1 -1
- package/lib/module/games/tile-home/TileHomeScene.js +1 -1
- package/lib/module/games/treasure-hunt/TreasureHunt.js +1 -1
- package/lib/module/games/treasure-hunt/TreasureHuntConstants.js +1 -1
- package/lib/module/games/treasure-hunt/TreasureHuntModel.js +1 -1
- package/lib/module/games/treasure-hunt/TreasureHuntScene.js +1 -1
- package/lib/module/games/whack-a-mole/WhackAMole.js +1 -1
- package/lib/module/games/whack-a-mole/WhackAMoleScene.js +1 -1
- package/lib/module/helpers/GameSettingsModal.js +1 -1
- package/lib/module/helpers/GameTheme.js +1 -1
- package/package.json +1 -2
- package/src/assets/fonts/Inter-SemiBold.ttf +0 -0
- package/src/assets/models/explorer/explorer.glb +0 -0
- package/src/assets/models/explorer/params.json +0 -51
- package/src/assets/models/explorer/source.json +0 -222
- package/src/assets/models/play-with-tua/play-with-tua.glb +0 -0
- package/src/assets/models/play-with-tua/sources.json +0 -141
- package/src/assets/sfx/balloon_pop.wav +0 -0
- package/src/assets/sfx/blocked.wav +0 -0
- package/src/assets/sfx/boing.wav +0 -0
- package/src/assets/sfx/bonus.wav +0 -0
- package/src/assets/sfx/boom.wav +0 -0
- package/src/assets/sfx/bump.wav +0 -0
- package/src/assets/sfx/cannon.wav +0 -0
- package/src/assets/sfx/capture.wav +0 -0
- package/src/assets/sfx/card_flip.wav +0 -0
- package/src/assets/sfx/card_place.wav +0 -0
- package/src/assets/sfx/catch.wav +0 -0
- package/src/assets/sfx/chime.wav +0 -0
- package/src/assets/sfx/chomp.wav +0 -0
- package/src/assets/sfx/chomp_alt.wav +0 -0
- package/src/assets/sfx/clack.wav +0 -0
- package/src/assets/sfx/clang.wav +0 -0
- package/src/assets/sfx/clash.wav +0 -0
- package/src/assets/sfx/click.wav +0 -0
- package/src/assets/sfx/coin.wav +0 -0
- package/src/assets/sfx/combo.wav +0 -0
- package/src/assets/sfx/crash.wav +0 -0
- package/src/assets/sfx/crunch.wav +0 -0
- package/src/assets/sfx/dance.wav +0 -0
- package/src/assets/sfx/deselect.wav +0 -0
- package/src/assets/sfx/dice_roll.wav +0 -0
- package/src/assets/sfx/die.wav +0 -0
- package/src/assets/sfx/draw.wav +0 -0
- package/src/assets/sfx/drop.wav +0 -0
- package/src/assets/sfx/eat.wav +0 -0
- package/src/assets/sfx/engine.wav +0 -0
- package/src/assets/sfx/error.wav +0 -0
- package/src/assets/sfx/flag.wav +0 -0
- package/src/assets/sfx/flap.wav +0 -0
- package/src/assets/sfx/flip_disc.wav +0 -0
- package/src/assets/sfx/footstep_run.wav +0 -0
- package/src/assets/sfx/footstep_walk.wav +0 -0
- package/src/assets/sfx/game_over.wav +0 -0
- package/src/assets/sfx/gate.wav +0 -0
- package/src/assets/sfx/hit.wav +0 -0
- package/src/assets/sfx/hop.wav +0 -0
- package/src/assets/sfx/hurt.wav +0 -0
- package/src/assets/sfx/invalid.wav +0 -0
- package/src/assets/sfx/jump.wav +0 -0
- package/src/assets/sfx/ladder.wav +0 -0
- package/src/assets/sfx/land.wav +0 -0
- package/src/assets/sfx/laugh.wav +0 -0
- package/src/assets/sfx/lose.wav +0 -0
- package/src/assets/sfx/merge.wav +0 -0
- package/src/assets/sfx/miss.wav +0 -0
- package/src/assets/sfx/nitro.wav +0 -0
- package/src/assets/sfx/pew.wav +0 -0
- package/src/assets/sfx/place.wav +0 -0
- package/src/assets/sfx/pling.wav +0 -0
- package/src/assets/sfx/point.wav +0 -0
- package/src/assets/sfx/pop.wav +0 -0
- package/src/assets/sfx/pop_soft.wav +0 -0
- package/src/assets/sfx/power_up.wav +0 -0
- package/src/assets/sfx/reveal.wav +0 -0
- package/src/assets/sfx/robot.wav +0 -0
- package/src/assets/sfx/rotate.wav +0 -0
- package/src/assets/sfx/run_steps.wav +0 -0
- package/src/assets/sfx/select.wav +0 -0
- package/src/assets/sfx/shuffle.wav +0 -0
- package/src/assets/sfx/six.wav +0 -0
- package/src/assets/sfx/slice.wav +0 -0
- package/src/assets/sfx/slide.wav +0 -0
- package/src/assets/sfx/snake.wav +0 -0
- package/src/assets/sfx/snap.wav +0 -0
- package/src/assets/sfx/splash.wav +0 -0
- package/src/assets/sfx/star.wav +0 -0
- package/src/assets/sfx/start.wav +0 -0
- package/src/assets/sfx/swoosh.wav +0 -0
- package/src/assets/sfx/tap.wav +0 -0
- package/src/assets/sfx/thud.wav +0 -0
- package/src/assets/sfx/thunk.wav +0 -0
- package/src/assets/sfx/tick.wav +0 -0
- package/src/assets/sfx/time_up.wav +0 -0
- package/src/assets/sfx/tock.wav +0 -0
- package/src/assets/sfx/walk_steps.wav +0 -0
- package/src/assets/sfx/warning.wav +0 -0
- package/src/assets/sfx/whack.wav +0 -0
- package/src/assets/sfx/whoosh.wav +0 -0
- package/src/assets/sfx/win.wav +0 -0
- package/src/assets/sfx/zap.wav +0 -0
- package/src/assets/textures/ad_bolt.png +0 -0
- package/src/assets/textures/ad_bubbles.png +0 -0
- package/src/assets/textures/ad_chevrons.png +0 -0
- package/src/assets/textures/asphalt.png +0 -0
- package/src/assets/textures/bark.jpg +0 -0
- package/src/assets/textures/explorer-atlas.png +0 -0
- package/src/assets/textures/facade.png +0 -0
- package/src/assets/textures/grass.png +0 -0
- package/src/assets/textures/leaves.png +0 -0
- package/src/assets/textures/limestone.jpg +0 -0
- package/src/assets/textures/meadow.jpg +0 -0
- package/src/assets/textures/nature-sources.json +0 -87
- package/src/assets/textures/pine.png +0 -0
- package/src/assets/textures/river.jpg +0 -0
- package/src/assets/textures/soft_glow.png +0 -0
- package/src/games/arrows/Arrows.tsx +0 -69
- package/src/games/arrows/ArrowsConstants.ts +0 -107
- package/src/games/arrows/ArrowsGame.ts +0 -735
- package/src/games/arrows/ArrowsScene.ts +0 -395
- package/src/games/balloon-blaster/BalloonBlaster.tsx +0 -75
- package/src/games/balloon-blaster/BalloonBlasterConstants.ts +0 -79
- package/src/games/balloon-blaster/BalloonBlasterGame.ts +0 -287
- package/src/games/balloon-blaster/BalloonBlasterPhysics.ts +0 -95
- package/src/games/balloon-blaster/BalloonBlasterScene.ts +0 -225
- package/src/games/bike-racing/BikeMeshes.ts +0 -273
- package/src/games/bike-racing/BikeRacing.tsx +0 -211
- package/src/games/bike-racing/BikeRacingConstants.ts +0 -103
- package/src/games/bike-racing/BikeRacingGame.ts +0 -557
- package/src/games/bike-racing/BikeRacingScene.ts +0 -119
- package/src/games/block-blast/BlockBlast.tsx +0 -73
- package/src/games/block-blast/BlockBlastConstants.ts +0 -179
- package/src/games/block-blast/BlockBlastGame.ts +0 -471
- package/src/games/block-blast/BlockBlastScene.ts +0 -156
- package/src/games/block-breaker/BlockBreaker.tsx +0 -79
- package/src/games/block-breaker/BlockBreakerConstants.ts +0 -139
- package/src/games/block-breaker/BlockBreakerGame.ts +0 -459
- package/src/games/block-breaker/BlockBreakerScene.ts +0 -257
- package/src/games/bluk/Bluk.tsx +0 -82
- package/src/games/bluk/BlukConstants.ts +0 -121
- package/src/games/bluk/BlukGame.ts +0 -323
- package/src/games/bluk/BlukRules.ts +0 -154
- package/src/games/bluk/BlukScene.ts +0 -514
- package/src/games/bubble-shooter/BubbleShooter.tsx +0 -76
- package/src/games/bubble-shooter/BubbleShooterConstants.ts +0 -103
- package/src/games/bubble-shooter/BubbleShooterGame.ts +0 -459
- package/src/games/bubble-shooter/BubbleShooterScene.ts +0 -158
- package/src/games/candy-crush/CandyCrush.tsx +0 -77
- package/src/games/candy-crush/CandyCrushConstants.ts +0 -94
- package/src/games/candy-crush/CandyCrushGame.ts +0 -477
- package/src/games/candy-crush/CandyCrushScene.ts +0 -209
- package/src/games/car-racing/CarMeshes.ts +0 -440
- package/src/games/car-racing/CarRacing.tsx +0 -211
- package/src/games/car-racing/CarRacingConstants.ts +0 -167
- package/src/games/car-racing/CarRacingFacade.ts +0 -40
- package/src/games/car-racing/CarRacingGame.ts +0 -539
- package/src/games/car-racing/CarRacingScene.ts +0 -1026
- package/src/games/car-racing/CarRacingScenery.ts +0 -265
- package/src/games/chameleon-run/ChameleonRun.tsx +0 -96
- package/src/games/chameleon-run/ChameleonRunBackdrop.ts +0 -186
- package/src/games/chameleon-run/ChameleonRunConstants.ts +0 -47
- package/src/games/chameleon-run/ChameleonRunGame.ts +0 -309
- package/src/games/chameleon-run/ChameleonRunMeshes.ts +0 -305
- package/src/games/chameleon-run/ChameleonRunRules.ts +0 -252
- package/src/games/chameleon-run/ChameleonRunScene.ts +0 -310
- package/src/games/checkers/Checkers.tsx +0 -83
- package/src/games/checkers/CheckersAI.ts +0 -255
- package/src/games/checkers/CheckersConstants.ts +0 -68
- package/src/games/checkers/CheckersGame.ts +0 -322
- package/src/games/checkers/CheckersRules.ts +0 -167
- package/src/games/checkers/CheckersScene.ts +0 -308
- package/src/games/color-switch/ColorSwitch.tsx +0 -75
- package/src/games/color-switch/ColorSwitchConstants.ts +0 -61
- package/src/games/color-switch/ColorSwitchGame.ts +0 -329
- package/src/games/color-switch/ColorSwitchScene.ts +0 -220
- package/src/games/colors-sort/ColorsSort.tsx +0 -82
- package/src/games/colors-sort/ColorsSortConstants.ts +0 -119
- package/src/games/colors-sort/ColorsSortGame.ts +0 -246
- package/src/games/colors-sort/ColorsSortScene.ts +0 -315
- package/src/games/connect-em-all/ConnectEmAll.tsx +0 -70
- package/src/games/connect-em-all/ConnectEmAllConstants.ts +0 -77
- package/src/games/connect-em-all/ConnectEmAllGame.ts +0 -401
- package/src/games/connect-em-all/ConnectEmAllScene.ts +0 -235
- package/src/games/crossy-road/CrossyRoad.tsx +0 -74
- package/src/games/crossy-road/CrossyRoadCamera.ts +0 -59
- package/src/games/crossy-road/CrossyRoadConstants.ts +0 -132
- package/src/games/crossy-road/CrossyRoadGame.ts +0 -293
- package/src/games/crossy-road/CrossyRoadMeshes.ts +0 -195
- package/src/games/crossy-road/CrossyRoadPerson.ts +0 -198
- package/src/games/crossy-road/CrossyRoadRules.ts +0 -99
- package/src/games/crossy-road/CrossyRoadScene.ts +0 -355
- package/src/games/dino-jump/DinoJump.tsx +0 -77
- package/src/games/dino-jump/DinoJumpConstants.ts +0 -80
- package/src/games/dino-jump/DinoJumpGame.ts +0 -344
- package/src/games/dino-jump/DinoJumpScene.ts +0 -686
- package/src/games/dots-and-boxes/DotsAndBoxes.tsx +0 -83
- package/src/games/dots-and-boxes/DotsAndBoxesConstants.ts +0 -77
- package/src/games/dots-and-boxes/DotsAndBoxesGame.ts +0 -271
- package/src/games/dots-and-boxes/DotsAndBoxesScene.ts +0 -249
- package/src/games/falling-sticks/FallingSticks.tsx +0 -72
- package/src/games/falling-sticks/FallingSticksConstants.ts +0 -62
- package/src/games/falling-sticks/FallingSticksGame.ts +0 -220
- package/src/games/falling-sticks/FallingSticksRules.ts +0 -145
- package/src/games/falling-sticks/FallingSticksScene.ts +0 -245
- package/src/games/find-different-number/FindDifferentNumber.tsx +0 -74
- package/src/games/find-different-number/FindDifferentNumberConstants.ts +0 -74
- package/src/games/find-different-number/FindDifferentNumberGame.ts +0 -174
- package/src/games/find-different-number/FindDifferentNumberRules.ts +0 -43
- package/src/games/find-different-number/FindDifferentNumberScene.ts +0 -193
- package/src/games/flappy-bird/FlappyBird.tsx +0 -73
- package/src/games/flappy-bird/FlappyBirdConstants.ts +0 -95
- package/src/games/flappy-bird/FlappyBirdGame.ts +0 -375
- package/src/games/flappy-bird/FlappyBirdScene.ts +0 -630
- package/src/games/fruit-merger/FruitMerger.tsx +0 -73
- package/src/games/fruit-merger/FruitMergerConstants.ts +0 -102
- package/src/games/fruit-merger/FruitMergerGame.ts +0 -285
- package/src/games/fruit-merger/FruitMergerRules.ts +0 -286
- package/src/games/fruit-merger/FruitMergerScene.ts +0 -498
- package/src/games/fruit-ninja/FruitNinja.tsx +0 -129
- package/src/games/fruit-ninja/FruitNinjaConstants.ts +0 -107
- package/src/games/fruit-ninja/FruitNinjaGame.ts +0 -391
- package/src/games/fruit-ninja/FruitNinjaScene.ts +0 -319
- package/src/games/fruit-ninja/FruitNinjaWorld.ts +0 -17
- package/src/games/game-2048/Game2048.tsx +0 -84
- package/src/games/game-2048/Game2048Constants.ts +0 -68
- package/src/games/game-2048/Game2048Game.ts +0 -181
- package/src/games/game-2048/Game2048Rules.ts +0 -101
- package/src/games/game-2048/Game2048Scene.ts +0 -206
- package/src/games/knife-hit/KnifeHit.tsx +0 -78
- package/src/games/knife-hit/KnifeHitConstants.ts +0 -89
- package/src/games/knife-hit/KnifeHitGame.ts +0 -264
- package/src/games/knife-hit/KnifeHitScene.ts +0 -360
- package/src/games/ludo-king/LudoKing.tsx +0 -86
- package/src/games/ludo-king/LudoKingConstants.ts +0 -212
- package/src/games/ludo-king/LudoKingGame.ts +0 -326
- package/src/games/ludo-king/LudoKingRules.ts +0 -143
- package/src/games/ludo-king/LudoKingScene.ts +0 -397
- package/src/games/maze-runner/MazeRunner.tsx +0 -88
- package/src/games/maze-runner/MazeRunnerConstants.ts +0 -65
- package/src/games/maze-runner/MazeRunnerGame.ts +0 -176
- package/src/games/maze-runner/MazeRunnerRules.ts +0 -161
- package/src/games/maze-runner/MazeRunnerScene.ts +0 -245
- package/src/games/memory-match/MemoryMatch.tsx +0 -77
- package/src/games/memory-match/MemoryMatchConstants.ts +0 -105
- package/src/games/memory-match/MemoryMatchGame.ts +0 -222
- package/src/games/memory-match/MemoryMatchRules.ts +0 -38
- package/src/games/memory-match/MemoryMatchScene.ts +0 -268
- package/src/games/mine-sweeper/MineSweeper.tsx +0 -77
- package/src/games/mine-sweeper/MineSweeperConstants.ts +0 -94
- package/src/games/mine-sweeper/MineSweeperGame.ts +0 -234
- package/src/games/mine-sweeper/MineSweeperRules.ts +0 -67
- package/src/games/mine-sweeper/MineSweeperScene.ts +0 -262
- package/src/games/mob-control/MobControl.tsx +0 -73
- package/src/games/mob-control/MobControlConstants.ts +0 -106
- package/src/games/mob-control/MobControlGame.ts +0 -176
- package/src/games/mob-control/MobControlMeshes.ts +0 -85
- package/src/games/mob-control/MobControlRenderer.ts +0 -108
- package/src/games/mob-control/MobControlRules.ts +0 -522
- package/src/games/mob-control/MobControlScene.ts +0 -399
- package/src/games/number-search/NumberSearch.tsx +0 -18
- package/src/games/number-search/NumberSearchNumbers.ts +0 -623
- package/src/games/nuts-and-bolts/NutsAndBolts.tsx +0 -85
- package/src/games/nuts-and-bolts/NutsAndBoltsConstants.ts +0 -75
- package/src/games/nuts-and-bolts/NutsAndBoltsGame.ts +0 -298
- package/src/games/nuts-and-bolts/NutsAndBoltsRules.ts +0 -474
- package/src/games/nuts-and-bolts/NutsAndBoltsScene.ts +0 -498
- package/src/games/pac-man/PacMan.tsx +0 -86
- package/src/games/pac-man/PacManConstants.ts +0 -169
- package/src/games/pac-man/PacManGame.ts +0 -406
- package/src/games/pac-man/PacManRules.ts +0 -255
- package/src/games/pac-man/PacManScene.ts +0 -387
- package/src/games/paper-io/PaperIo.tsx +0 -91
- package/src/games/paper-io/PaperIoConstants.ts +0 -86
- package/src/games/paper-io/PaperIoGame.ts +0 -193
- package/src/games/paper-io/PaperIoMeshes.ts +0 -233
- package/src/games/paper-io/PaperIoRules.ts +0 -315
- package/src/games/paper-io/PaperIoScene.ts +0 -310
- package/src/games/penguin-run/PenguinMeshes.ts +0 -269
- package/src/games/penguin-run/PenguinModel.ts +0 -712
- package/src/games/penguin-run/PenguinRun.tsx +0 -77
- package/src/games/penguin-run/PenguinRunConstants.ts +0 -69
- package/src/games/penguin-run/PenguinRunGame.ts +0 -406
- package/src/games/penguin-run/PenguinRunScene.ts +0 -949
- package/src/games/perfect-circle/PerfectCircle.tsx +0 -74
- package/src/games/perfect-circle/PerfectCircleConstants.ts +0 -52
- package/src/games/perfect-circle/PerfectCircleGame.ts +0 -153
- package/src/games/perfect-circle/PerfectCircleRules.ts +0 -111
- package/src/games/perfect-circle/PerfectCircleScene.ts +0 -176
- package/src/games/pipe-connect/PipeConnect.tsx +0 -69
- package/src/games/pipe-connect/PipeConnectConstants.ts +0 -101
- package/src/games/pipe-connect/PipeConnectGame.ts +0 -179
- package/src/games/pipe-connect/PipeConnectRules.ts +0 -326
- package/src/games/pipe-connect/PipeConnectScene.ts +0 -271
- package/src/games/play-with-tua/PlayWithTua.tsx +0 -123
- package/src/games/play-with-tua/PlayWithTuaConstants.ts +0 -70
- package/src/games/play-with-tua/PlayWithTuaGame.ts +0 -167
- package/src/games/play-with-tua/PlayWithTuaModel.ts +0 -42
- package/src/games/play-with-tua/PlayWithTuaScene.ts +0 -36
- package/src/games/popit-fidget/PopitFidget.tsx +0 -72
- package/src/games/popit-fidget/PopitFidgetConstants.ts +0 -71
- package/src/games/popit-fidget/PopitFidgetGame.ts +0 -148
- package/src/games/popit-fidget/PopitFidgetScene.ts +0 -242
- package/src/games/reversi/Reversi.tsx +0 -94
- package/src/games/reversi/ReversiConstants.ts +0 -67
- package/src/games/reversi/ReversiGame.ts +0 -266
- package/src/games/reversi/ReversiRules.ts +0 -176
- package/src/games/reversi/ReversiScene.ts +0 -240
- package/src/games/search-grid/SearchGrid.tsx +0 -92
- package/src/games/search-grid/SearchGridConstants.ts +0 -178
- package/src/games/search-grid/SearchGridGame.ts +0 -209
- package/src/games/search-grid/SearchGridScene.ts +0 -301
- package/src/games/shared/BackdropCard.tsx +0 -54
- package/src/games/shared/EngineBackdrop.ts +0 -300
- package/src/games/shared/EngineBlasts.ts +0 -136
- package/src/games/shared/EngineBlocks.ts +0 -91
- package/src/games/shared/EngineControlText.ts +0 -17
- package/src/games/shared/EngineDice.ts +0 -250
- package/src/games/shared/EngineFootprint.ts +0 -35
- package/src/games/shared/EngineFruits.ts +0 -1435
- package/src/games/shared/EngineGameLoader.tsx +0 -88
- package/src/games/shared/EngineGameScreen.tsx +0 -325
- package/src/games/shared/EngineGameWidth.ts +0 -3
- package/src/games/shared/EngineGameWidth.web.ts +0 -3
- package/src/games/shared/EngineGlyphs.ts +0 -178
- package/src/games/shared/EngineHud.ts +0 -815
- package/src/games/shared/EngineLoading.ts +0 -477
- package/src/games/shared/EngineMeadow.ts +0 -725
- package/src/games/shared/EngineMeshCache.ts +0 -15
- package/src/games/shared/EngineMeshes.ts +0 -10
- package/src/games/shared/EngineRacingChase.ts +0 -21
- package/src/games/shared/EngineRacingHandling.ts +0 -48
- package/src/games/shared/EngineReadyContext.ts +0 -4
- package/src/games/shared/EngineTilt.ts +0 -44
- package/src/games/shared/EngineTouchSurface.tsx +0 -103
- package/src/games/shared/EngineUtils.ts +0 -52
- package/src/games/shared/GameActivity.ts +0 -13
- package/src/games/shared/GameLoading.tsx +0 -202
- package/src/games/shared/GameLoadingTransition.tsx +0 -61
- package/src/games/shared/ProceduralCacheVersion.ts +0 -2
- package/src/games/shared/useEngineGame.ts +0 -240
- package/src/games/shared/useGameResource.ts +0 -21
- package/src/games/shared/useLiveState.ts +0 -58
- package/src/games/sliding-numbers/SlidingNumbers.tsx +0 -71
- package/src/games/sliding-numbers/SlidingNumbersConstants.ts +0 -65
- package/src/games/sliding-numbers/SlidingNumbersGame.ts +0 -192
- package/src/games/sliding-numbers/SlidingNumbersRules.ts +0 -79
- package/src/games/sliding-numbers/SlidingNumbersScene.ts +0 -193
- package/src/games/snake-3d/Snake3D.tsx +0 -76
- package/src/games/snake-3d/Snake3DConstants.ts +0 -61
- package/src/games/snake-3d/Snake3DGame.ts +0 -192
- package/src/games/snake-3d/Snake3DMotion.ts +0 -22
- package/src/games/snake-3d/Snake3DRules.ts +0 -116
- package/src/games/snake-3d/Snake3DScene.ts +0 -322
- package/src/games/snakes-and-ladders/SnakesAndLadders.tsx +0 -87
- package/src/games/snakes-and-ladders/SnakesAndLaddersConstants.ts +0 -136
- package/src/games/snakes-and-ladders/SnakesAndLaddersGame.ts +0 -310
- package/src/games/snakes-and-ladders/SnakesAndLaddersScene.ts +0 -515
- package/src/games/space-fighter/SpaceFighter.tsx +0 -74
- package/src/games/space-fighter/SpaceFighterConstants.ts +0 -86
- package/src/games/space-fighter/SpaceFighterGame.ts +0 -292
- package/src/games/space-fighter/SpaceFighterScene.ts +0 -550
- package/src/games/spider-solitaire/SpiderSolitaire.tsx +0 -80
- package/src/games/spider-solitaire/SpiderSolitaireConstants.ts +0 -107
- package/src/games/spider-solitaire/SpiderSolitaireGame.ts +0 -387
- package/src/games/spider-solitaire/SpiderSolitaireRules.ts +0 -123
- package/src/games/spider-solitaire/SpiderSolitaireScene.ts +0 -352
- package/src/games/stack-tower/StackTower.tsx +0 -76
- package/src/games/stack-tower/StackTowerConstants.ts +0 -74
- package/src/games/stack-tower/StackTowerGame.ts +0 -236
- package/src/games/stack-tower/StackTowerScene.ts +0 -186
- package/src/games/sudoku/Sudoku.tsx +0 -73
- package/src/games/sudoku/SudokuConstants.ts +0 -127
- package/src/games/sudoku/SudokuGame.ts +0 -250
- package/src/games/sudoku/SudokuRules.ts +0 -125
- package/src/games/sudoku/SudokuScene.ts +0 -304
- package/src/games/tangram/Tangram.tsx +0 -79
- package/src/games/tangram/TangramConstants.ts +0 -64
- package/src/games/tangram/TangramGame.ts +0 -356
- package/src/games/tangram/TangramRules.ts +0 -409
- package/src/games/tangram/TangramScene.ts +0 -203
- package/src/games/tank-1990/Tank1990.tsx +0 -78
- package/src/games/tank-1990/Tank1990Constants.ts +0 -81
- package/src/games/tank-1990/Tank1990Game.ts +0 -331
- package/src/games/tank-1990/Tank1990Rules.ts +0 -390
- package/src/games/tank-1990/Tank1990Scene.ts +0 -434
- package/src/games/tic-tac-toe/TicTacToe.tsx +0 -98
- package/src/games/tic-tac-toe/TicTacToeConstants.ts +0 -69
- package/src/games/tic-tac-toe/TicTacToeGame.ts +0 -200
- package/src/games/tic-tac-toe/TicTacToeRules.ts +0 -103
- package/src/games/tic-tac-toe/TicTacToeScene.ts +0 -245
- package/src/games/tile-home/TileHome.tsx +0 -92
- package/src/games/tile-home/TileHomeConstants.ts +0 -139
- package/src/games/tile-home/TileHomeGame.ts +0 -435
- package/src/games/tile-home/TileHomeScene.ts +0 -154
- package/src/games/treasure-hunt/TreasureHunt.tsx +0 -206
- package/src/games/treasure-hunt/TreasureHuntConstants.ts +0 -266
- package/src/games/treasure-hunt/TreasureHuntControls.ts +0 -280
- package/src/games/treasure-hunt/TreasureHuntGame.ts +0 -402
- package/src/games/treasure-hunt/TreasureHuntMeshes.ts +0 -422
- package/src/games/treasure-hunt/TreasureHuntModel.ts +0 -506
- package/src/games/treasure-hunt/TreasureHuntRules.ts +0 -1210
- package/src/games/treasure-hunt/TreasureHuntScene.ts +0 -586
- package/src/games/whack-a-mole/WhackAMole.tsx +0 -79
- package/src/games/whack-a-mole/WhackAMoleConstants.ts +0 -94
- package/src/games/whack-a-mole/WhackAMoleGame.ts +0 -233
- package/src/games/whack-a-mole/WhackAMoleScene.ts +0 -349
- package/src/games/word-search/WordSearch.tsx +0 -18
- package/src/games/word-search/WordSearchWords.ts +0 -1642
- package/src/helpers/GamePatternData.ts +0 -120
- package/src/helpers/GameSettingsModal.tsx +0 -384
- package/src/helpers/GameTheme.tsx +0 -37
- package/src/helpers/IconPaths.ts +0 -6
- package/src/helpers/index.ts +0 -2
- package/src/index.tsx +0 -60
- package/src/services/GameAssetLoader.ts +0 -111
- package/src/services/GameAssets.ts +0 -149
- package/src/services/GameLoaders.ts +0 -93
- package/src/services/GamesConstants.ts +0 -193
- package/src/services/GamesMetadata.ts +0 -711
- package/src/services/GamesService.ts +0 -116
- package/src/services/HapticsService.ts +0 -48
- package/src/services/ScoringService.ts +0 -19
- package/src/services/SfxSources.ts +0 -81
- package/src/services/SoundsService.ts +0 -582
- package/src/services/ThemeService.ts +0 -281
- package/src/services/UtilsService.ts +0 -134
- 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
|
-
});
|