@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,630 +0,0 @@
|
|
|
1
|
-
// Everything Flappy Bird flies through, in front of its 3D meadow (EngineMeadow). Positions come in
|
|
2
|
-
// screen points (y down) and land on the play plane ahead of the camera, where the original game drew them;
|
|
3
|
-
// sizes are scaled to metres there. The bird is a chubby 3D bird (egg body, belly, cheek, eye, beak,
|
|
4
|
-
// crest, tail, feet) with two flapping wings, a blinking eyelid and a squash on every flap; pipes are glossy green tubes with lipped caps; the walls are
|
|
5
|
-
// laid brick by brick over mortar. Each is a root turned to face the camera, so its parts are placed in
|
|
6
|
-
// screen-like local axes. Every part is a shared mesh: mesh ids are app-wide and limited.
|
|
7
|
-
import {
|
|
8
|
-
type Color,
|
|
9
|
-
effects,
|
|
10
|
-
type Entity,
|
|
11
|
-
extrude,
|
|
12
|
-
type Geometry,
|
|
13
|
-
lathe,
|
|
14
|
-
merge,
|
|
15
|
-
type Model,
|
|
16
|
-
type MutableQuat,
|
|
17
|
-
Path,
|
|
18
|
-
quat,
|
|
19
|
-
recolor,
|
|
20
|
-
shapeGeometry,
|
|
21
|
-
type TransformBatch,
|
|
22
|
-
tube,
|
|
23
|
-
type Vec3,
|
|
24
|
-
type World
|
|
25
|
-
} from '@nayan-ui/engine';
|
|
26
|
-
import { at, facing, pointSize, type View3D } from '../shared/EngineMeadow';
|
|
27
|
-
import { cacheGameAsset, createGameMesh as createShape } from '../shared/EngineMeshes';
|
|
28
|
-
import { toColor } from '../shared/EngineUtils';
|
|
29
|
-
import { BIRD_SIZE, BRICK_HEIGHT, BRICK_WIDTH, type Layout, PIPE_WIDTH } from './FlappyBirdConstants';
|
|
30
|
-
|
|
31
|
-
// ── Meshes ────────────────────────────────────────────────────────────
|
|
32
|
-
|
|
33
|
-
const meshes = new Map<string, Model>();
|
|
34
|
-
const cached = (key: string, build: () => Model) => {
|
|
35
|
-
let m = meshes.get(key);
|
|
36
|
-
if (!m) {
|
|
37
|
-
m = cacheGameAsset('flappy-bird/FlappyBirdScene:' + key, build);
|
|
38
|
-
meshes.set(key, m);
|
|
39
|
-
}
|
|
40
|
-
return m;
|
|
41
|
-
};
|
|
42
|
-
type RGB = [number, number, number];
|
|
43
|
-
const rgb = (css: string): RGB => {
|
|
44
|
-
const [r, g, b] = toColor(css);
|
|
45
|
-
return [r, g, b];
|
|
46
|
-
};
|
|
47
|
-
const mix = (a: RGB, b: RGB, t: number): RGB => [a[0] + (b[0] - a[0]) * t, a[1] + (b[1] - a[1]) * t, a[2] + (b[2] - a[2]) * t];
|
|
48
|
-
const sphere = () => shapeGeometry('sphere');
|
|
49
|
-
/** A cone along +x (the beak), from a lathe around y turned a quarter. */
|
|
50
|
-
const beakPart = (length: number, radius: number, color: RGB, position: Vec3, tilt: number) => ({
|
|
51
|
-
geometry: lathe(
|
|
52
|
-
[
|
|
53
|
-
[radius, 0],
|
|
54
|
-
[radius * 0.6, length * 0.5],
|
|
55
|
-
[0.001, length]
|
|
56
|
-
],
|
|
57
|
-
{ segments: 12, color }
|
|
58
|
-
),
|
|
59
|
-
position,
|
|
60
|
-
rotation: quat.multiply(quat.z(tilt), quat.z(-Math.PI / 2))
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
const clamp01 = (x: number) => Math.max(0, Math.min(1, x));
|
|
64
|
-
const smoothstep = (x: number) => {
|
|
65
|
-
const t = clamp01(x);
|
|
66
|
-
return t * t * (3 - 2 * t);
|
|
67
|
-
};
|
|
68
|
-
const BODY_TOP = rgb('#FFE14D');
|
|
69
|
-
const BODY_BOTTOM = rgb('#FFAA1F');
|
|
70
|
-
const BELLY = rgb('#FFF4CC');
|
|
71
|
-
const BLUSH = rgb('#FF8C9A');
|
|
72
|
-
const FEATHER = rgb('#F08A12');
|
|
73
|
-
|
|
74
|
-
/** A tapered feather along `points`, flattened into a blade. */
|
|
75
|
-
const feather = (points: Vec3[], radius: number, color: RGB) =>
|
|
76
|
-
tube(points, {
|
|
77
|
-
radius: (t) => radius * Math.max(0.08, 1 - t * 0.85),
|
|
78
|
-
shape: (a) => 0.35 + 0.65 * Math.abs(Math.cos(a * Math.PI * 2)),
|
|
79
|
-
sides: 8,
|
|
80
|
-
smoothness: 5,
|
|
81
|
-
color: [...color, 1] as Color
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* The bird's body (without its wings, eyelid or squash), one unit long, facing +x (right), its front
|
|
86
|
-
* toward +z (the camera): a chubby egg, yellow fading to orange below, a cream belly and pink cheek,
|
|
87
|
-
* a big eye, a two-part beak, curling crest feathers, a fanned tail and tucked feet.
|
|
88
|
-
*/
|
|
89
|
-
const birdMesh = () =>
|
|
90
|
-
cached('fb-bird', () => {
|
|
91
|
-
// The egg: round at the head (+x), a little narrower at the tail
|
|
92
|
-
const profile: [number, number][] = Array.from({ length: 17 }, (_, i) => {
|
|
93
|
-
const t = i / 16;
|
|
94
|
-
return [Math.max(0.001, 0.47 * Math.sin(Math.PI * t) ** 0.75 * (1 - 0.16 * t)), 0.5 - t];
|
|
95
|
-
});
|
|
96
|
-
const egg = merge([{ geometry: lathe(profile, { segments: 28 }), rotation: quat.z(-Math.PI / 2), scale: [1, 0.92, 0.86] }]);
|
|
97
|
-
const body = recolor(egg, ({ position: [x, y, z] }) => {
|
|
98
|
-
let c = mix(BODY_BOTTOM, BODY_TOP, clamp01(0.5 + y * 1.3 + x * 0.25));
|
|
99
|
-
// Cream belly on the front and underside
|
|
100
|
-
c = mix(c, BELLY, smoothstep((0.06 - y) * 4) * smoothstep(z * 3 + 0.3) * smoothstep((x + 0.32) * 3) * 0.95);
|
|
101
|
-
// A pink cheek under the eye
|
|
102
|
-
c = mix(c, BLUSH, smoothstep(1 - Math.hypot(x - 0.2, y + 0.06, z - 0.33) / 0.11) * 0.8);
|
|
103
|
-
return [...c, 1] as Color;
|
|
104
|
-
});
|
|
105
|
-
return createShape(
|
|
106
|
-
merge([
|
|
107
|
-
{ geometry: body },
|
|
108
|
-
// Eye: white, a black pupil looking ahead, a glint
|
|
109
|
-
{ geometry: sphere(), position: [0.22, 0.15, 0.26], scale: 0.32, color: [1, 1, 1] },
|
|
110
|
-
{ geometry: sphere(), position: [0.3, 0.16, 0.38], scale: 0.15, color: rgb('#151515') },
|
|
111
|
-
{ geometry: sphere(), position: [0.33, 0.2, 0.445], scale: 0.05, color: [1, 1, 1] },
|
|
112
|
-
// Beak: upper and lower halves
|
|
113
|
-
beakPart(0.3, 0.1, rgb('#FF7B3A'), [0.4, 0.0, 0.06], 0.12),
|
|
114
|
-
beakPart(0.24, 0.08, rgb('#D9531A'), [0.39, -0.07, 0.06], -0.2),
|
|
115
|
-
// Crest: three curling feathers
|
|
116
|
-
{
|
|
117
|
-
geometry: feather(
|
|
118
|
-
[
|
|
119
|
-
[0.02, 0.36, 0],
|
|
120
|
-
[0.0, 0.52, 0],
|
|
121
|
-
[-0.1, 0.6, 0]
|
|
122
|
-
],
|
|
123
|
-
0.07,
|
|
124
|
-
rgb('#FF9500')
|
|
125
|
-
)
|
|
126
|
-
},
|
|
127
|
-
{
|
|
128
|
-
geometry: feather(
|
|
129
|
-
[
|
|
130
|
-
[0.1, 0.36, 0.02],
|
|
131
|
-
[0.12, 0.5, 0.02],
|
|
132
|
-
[0.06, 0.6, 0.02]
|
|
133
|
-
],
|
|
134
|
-
0.06,
|
|
135
|
-
rgb('#FFB300')
|
|
136
|
-
)
|
|
137
|
-
},
|
|
138
|
-
{
|
|
139
|
-
geometry: feather(
|
|
140
|
-
[
|
|
141
|
-
[-0.06, 0.34, -0.02],
|
|
142
|
-
[-0.14, 0.46, -0.02],
|
|
143
|
-
[-0.24, 0.5, -0.02]
|
|
144
|
-
],
|
|
145
|
-
0.055,
|
|
146
|
-
FEATHER
|
|
147
|
-
)
|
|
148
|
-
},
|
|
149
|
-
// Tail: three broad, round-tipped feathers fanned back
|
|
150
|
-
...[0.2, 0.02, -0.16].map((tilt, i) => ({
|
|
151
|
-
geometry: tube(
|
|
152
|
-
[
|
|
153
|
-
[-0.34, 0.02, 0],
|
|
154
|
-
[-0.52, 0.04 + tilt * 0.6, 0],
|
|
155
|
-
[-0.68, 0.06 + tilt, 0]
|
|
156
|
-
],
|
|
157
|
-
{
|
|
158
|
-
radius: (t) => 0.13 * (0.55 + 0.45 * Math.sin(Math.PI * (0.25 + t * 0.6))),
|
|
159
|
-
shape: (a) => 0.45 + 0.55 * Math.abs(Math.cos(a * Math.PI * 2)),
|
|
160
|
-
sides: 10,
|
|
161
|
-
smoothness: 5,
|
|
162
|
-
color: [...mix(FEATHER, rgb('#C2600A'), i * 0.35), 1] as Color
|
|
163
|
-
}
|
|
164
|
-
)
|
|
165
|
-
})),
|
|
166
|
-
// Feet tucked under
|
|
167
|
-
...[0.12, -0.12].map((z) => ({
|
|
168
|
-
geometry: feather(
|
|
169
|
-
[
|
|
170
|
-
[0.02, -0.36, z],
|
|
171
|
-
[-0.08, -0.46, z],
|
|
172
|
-
[-0.2, -0.48, z]
|
|
173
|
-
],
|
|
174
|
-
0.035,
|
|
175
|
-
rgb('#FF7B3A')
|
|
176
|
-
)
|
|
177
|
-
}))
|
|
178
|
-
]),
|
|
179
|
-
{ center: false, shine: 0.35 }
|
|
180
|
-
);
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
/** A wing, pivoting at its root (the origin) and reaching back (-x): a rounded feather paddle with a scalloped trailing edge. */
|
|
184
|
-
const wingMesh = (far: boolean) =>
|
|
185
|
-
cached(`fb-wing:${far}`, () => {
|
|
186
|
-
// Points in world-up y (the path's y runs down)
|
|
187
|
-
const pts: [number, number][] = [
|
|
188
|
-
[0.06, 0.06],
|
|
189
|
-
[-0.12, 0.14],
|
|
190
|
-
[-0.34, 0.12],
|
|
191
|
-
[-0.56, 0.02],
|
|
192
|
-
[-0.5, -0.04],
|
|
193
|
-
[-0.55, -0.09],
|
|
194
|
-
[-0.44, -0.11],
|
|
195
|
-
[-0.47, -0.17],
|
|
196
|
-
[-0.34, -0.17],
|
|
197
|
-
[-0.12, -0.12],
|
|
198
|
-
[0.06, -0.05]
|
|
199
|
-
];
|
|
200
|
-
const path = new Path().moveTo(pts[0]![0], -pts[0]![1]);
|
|
201
|
-
for (const [x, y] of pts.slice(1)) path.lineTo(x, -y);
|
|
202
|
-
path.close();
|
|
203
|
-
const [root, tip] = far ? [rgb('#B86A08'), rgb('#D9901F')] : [rgb('#F59E0B'), rgb('#FFD35C')];
|
|
204
|
-
return createShape(
|
|
205
|
-
recolor(extrude(path, { depth: 0.07 }), ({ position: [x] }) => [...mix(root, tip, clamp01(-x / 0.55)), 1] as Color),
|
|
206
|
-
{ center: false, shine: 0.25 }
|
|
207
|
-
);
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
/** The eyelid: a ball in the body's color over the eye, shown only while blinking. */
|
|
211
|
-
const lidMesh = () => cached('fb-lid', () => createShape(merge([{ geometry: sphere(), color: BODY_TOP }]), { shine: 0.35 }));
|
|
212
|
-
|
|
213
|
-
/** A unit pipe body: an open tube one unit across and tall, centred, with vertical shading baked in. */
|
|
214
|
-
const pipeMesh = () =>
|
|
215
|
-
cached('fb-pipe', () =>
|
|
216
|
-
createShape(
|
|
217
|
-
lathe(
|
|
218
|
-
[
|
|
219
|
-
[0.5, -0.5],
|
|
220
|
-
[0.5, 0.5]
|
|
221
|
-
],
|
|
222
|
-
{ segments: 24, color: rgb('#4CA840') }
|
|
223
|
-
),
|
|
224
|
-
{ center: false, shine: 0.55 }
|
|
225
|
-
)
|
|
226
|
-
);
|
|
227
|
-
/** The cap: a wider, short lipped ring, closed at the end facing the gap (+y), one unit tall, centred. */
|
|
228
|
-
const capMesh = () =>
|
|
229
|
-
cached('fb-cap', () =>
|
|
230
|
-
createShape(
|
|
231
|
-
merge([
|
|
232
|
-
{
|
|
233
|
-
geometry: lathe(
|
|
234
|
-
[
|
|
235
|
-
[0.001, 0.5],
|
|
236
|
-
[0.5, 0.5],
|
|
237
|
-
[0.52, 0.42],
|
|
238
|
-
[0.52, -0.42],
|
|
239
|
-
[0.5, -0.5]
|
|
240
|
-
],
|
|
241
|
-
{ segments: 24, color: rgb('#3A8A2A') }
|
|
242
|
-
)
|
|
243
|
-
},
|
|
244
|
-
// A dark opening, so the pipe reads as hollow
|
|
245
|
-
{ geometry: sphere(), position: [0, 0.5, 0], scale: [0.78, 0.02, 0.78], color: rgb('#123d10') }
|
|
246
|
-
]),
|
|
247
|
-
{ center: false, shine: 0.6 }
|
|
248
|
-
)
|
|
249
|
-
);
|
|
250
|
-
|
|
251
|
-
/** Bricks along a row repeat their shades every this many, so the scrolling walls can wrap seamlessly. */
|
|
252
|
-
const SHADE_PERIOD = 12;
|
|
253
|
-
/** A brick's shade, from its row and its column (wrapped to the period): the same brick always looks the same. */
|
|
254
|
-
function brickShade(row: number, col: number): RGB {
|
|
255
|
-
const c = ((col % SHADE_PERIOD) + SHADE_PERIOD) % SHADE_PERIOD;
|
|
256
|
-
const n = Math.sin(row * 127.1 + c * 311.7) * 43758.5453;
|
|
257
|
-
const t = n - Math.floor(n);
|
|
258
|
-
const base = rgb('#9E5428');
|
|
259
|
-
return t < 0.5 ? mix(rgb('#6E3412'), base, t * 2) : mix(base, rgb('#B8693A'), (t - 0.5) * 2);
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
/**
|
|
263
|
-
* A wall block in its own frame: x across (centred), y running into the wall away from the play area,
|
|
264
|
-
* z toward the camera (the back face at 0, the front at `thickness`). `w` and `h` are screen points at
|
|
265
|
-
* `k` metres per point. A stone coping runs along the edge facing the play area; above it, bricks in
|
|
266
|
-
* running bond, each a slightly different shade, face the front over a mortar core.
|
|
267
|
-
*/
|
|
268
|
-
function wallGeometry(w: number, h: number, k: number, thickness: number): Geometry {
|
|
269
|
-
const bw = BRICK_WIDTH * k;
|
|
270
|
-
const bh = BRICK_HEIGHT * k;
|
|
271
|
-
const width = w * k;
|
|
272
|
-
const height = h * k;
|
|
273
|
-
const coping = COPING * k;
|
|
274
|
-
const relief = bh * 0.35; // how far a brick stands proud of the mortar
|
|
275
|
-
const mortar = 0.12 * bh;
|
|
276
|
-
const parts: { geometry: Geometry; position: Vec3; scale: Vec3; color: RGB }[] = [];
|
|
277
|
-
const box = (x0: number, x1: number, y0: number, y1: number, z0: number, z1: number, color: RGB) =>
|
|
278
|
-
parts.push({
|
|
279
|
-
geometry: shapeGeometry('cube'),
|
|
280
|
-
position: [(x0 + x1) / 2, (y0 + y1) / 2, (z0 + z1) / 2],
|
|
281
|
-
scale: [x1 - x0, y1 - y0, z1 - z0],
|
|
282
|
-
color
|
|
283
|
-
});
|
|
284
|
-
// The mortar core, the full depth of the wall (it hides the pipes' ends inside it)
|
|
285
|
-
box(-width / 2, width / 2, coping, height, 0, thickness, rgb('#3a1d0c'));
|
|
286
|
-
// The coping: a pale stone ledge, overhanging the face a little
|
|
287
|
-
box(-width / 2, width / 2, 0, coping, -0.01, thickness + relief + 0.025, rgb('#c8b896'));
|
|
288
|
-
box(-width / 2, width / 2, coping * 0.78, coping, thickness + relief + 0.005, thickness + relief + 0.03, rgb('#a9987a'));
|
|
289
|
-
const rows = Math.ceil((height - coping) / bh);
|
|
290
|
-
for (let r = 0; r < rows; r++) {
|
|
291
|
-
const y0 = coping + r * bh;
|
|
292
|
-
const y1 = Math.min(height, y0 + bh);
|
|
293
|
-
const shift = r % 2 ? bw / 2 : 0;
|
|
294
|
-
for (let c = 0, x = -width / 2 - shift; x < width / 2; c++, x += bw) {
|
|
295
|
-
// Clip the end bricks to the wall's edges (they're off screen)
|
|
296
|
-
const x0 = Math.max(x, -width / 2);
|
|
297
|
-
const x1 = Math.min(x + bw, width / 2);
|
|
298
|
-
if (x1 - x0 <= mortar || y1 - y0 <= mortar) continue;
|
|
299
|
-
box(x0 + mortar / 2, x1 - mortar / 2, y0 + mortar / 2, y1 - mortar / 2, thickness - 0.01, thickness + relief, brickShade(r, c));
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
return merge(parts);
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
// ── Placement ─────────────────────────────────────────────────────────
|
|
306
|
-
|
|
307
|
-
/** Local offset (metres) of screen point (x, y) from the root's screen point, in the root's facing axes. */
|
|
308
|
-
const local = (k: number, dx: number, dy: number, dz = 0): Vec3 => [dx * k, -dy * k, dz];
|
|
309
|
-
|
|
310
|
-
// ── Walls ─────────────────────────────────────────────────────────────
|
|
311
|
-
|
|
312
|
-
const CAP_HEIGHT = 26;
|
|
313
|
-
const CAP_OVER = 5;
|
|
314
|
-
const COPING = 12; // points
|
|
315
|
-
/** Points the walls reach past the screen's edge (the perspective shows a little more of a near face). */
|
|
316
|
-
const WALL_MARGIN = 160;
|
|
317
|
-
/** Points the pipes run on into the walls, so where they meet is inside the brickwork. */
|
|
318
|
-
const PIPE_INTO_WALL = 220;
|
|
319
|
-
|
|
320
|
-
/** The bottom wall's depth: its back face just behind the pipes, its front just ahead, so a pipe passes through it. */
|
|
321
|
-
const wallDepth = (v: View3D) => {
|
|
322
|
-
const pipeRadius = ((PIPE_WIDTH + CAP_OVER * 2 * (PIPE_WIDTH / 60)) / 2) * pointSize(v);
|
|
323
|
-
return { back: v.playDepth + pipeRadius + 0.04, thickness: pipeRadius * 2 + 0.08, front: v.playDepth - pipeRadius - 0.04 };
|
|
324
|
-
};
|
|
325
|
-
|
|
326
|
-
/**
|
|
327
|
-
* A prism: the convex outline `profile` ((z, y) points, z toward the camera) swept along x from `x0` to
|
|
328
|
-
* `x1`, with flat faces turned outward. For shapes the cubes can't make: the top wall's sloped underside.
|
|
329
|
-
*/
|
|
330
|
-
function prism(profile: [number, number][], x0: number, x1: number, color: RGB): Geometry {
|
|
331
|
-
const vertices: number[] = [];
|
|
332
|
-
const indices: number[] = [];
|
|
333
|
-
const cz = profile.reduce((a, p) => a + p[0], 0) / profile.length;
|
|
334
|
-
const cy = profile.reduce((a, p) => a + p[1], 0) / profile.length;
|
|
335
|
-
const centre: Vec3 = [(x0 + x1) / 2, cy, cz];
|
|
336
|
-
const face = (pts: Vec3[]) => {
|
|
337
|
-
const [a, b, c] = pts as [Vec3, Vec3, Vec3];
|
|
338
|
-
const u: Vec3 = [b[0] - a[0], b[1] - a[1], b[2] - a[2]];
|
|
339
|
-
const w: Vec3 = [c[0] - a[0], c[1] - a[1], c[2] - a[2]];
|
|
340
|
-
let n: Vec3 = [u[1] * w[2] - u[2] * w[1], u[2] * w[0] - u[0] * w[2], u[0] * w[1] - u[1] * w[0]];
|
|
341
|
-
const mid = pts.reduce<Vec3>((m, p) => [m[0] + p[0] / pts.length, m[1] + p[1] / pts.length, m[2] + p[2] / pts.length], [0, 0, 0]);
|
|
342
|
-
if (n[0] * (mid[0] - centre[0]) + n[1] * (mid[1] - centre[1]) + n[2] * (mid[2] - centre[2]) < 0) {
|
|
343
|
-
pts = [...pts].reverse();
|
|
344
|
-
n = [-n[0], -n[1], -n[2]];
|
|
345
|
-
}
|
|
346
|
-
const len = Math.hypot(n[0], n[1], n[2]) || 1;
|
|
347
|
-
const first = vertices.length / 11;
|
|
348
|
-
for (const p of pts) vertices.push(p[0], p[1], p[2], n[0] / len, n[1] / len, n[2] / len, color[0], color[1], color[2], 0, 0);
|
|
349
|
-
for (let i = 1; i + 1 < pts.length; i++) indices.push(first, first + i, first + i + 1);
|
|
350
|
-
};
|
|
351
|
-
face(profile.map(([z, y]) => [x0, y, z] as Vec3));
|
|
352
|
-
face(profile.map(([z, y]) => [x1, y, z] as Vec3));
|
|
353
|
-
profile.forEach(([z, y], i) => {
|
|
354
|
-
const [z2, y2] = profile[(i + 1) % profile.length]!;
|
|
355
|
-
face([
|
|
356
|
-
[x0, y, z],
|
|
357
|
-
[x1, y, z],
|
|
358
|
-
[x1, y2, z2],
|
|
359
|
-
[x0, y2, z2]
|
|
360
|
-
]);
|
|
361
|
-
});
|
|
362
|
-
return { vertices: new Float32Array(vertices), indices: new Uint32Array(indices) };
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
/**
|
|
366
|
-
* The top wall, in its own frame (x across, y up, z toward the camera, the origin on its front edge).
|
|
367
|
-
* The camera looks up at it, so a flat underside would show as a dark band below the bricks. Instead
|
|
368
|
-
* the underside rises toward the back along the camera's line of sight through the edge (`slope`
|
|
369
|
-
* metres up per metre back), so it's never seen: the stone coping's front comes right down to the line
|
|
370
|
-
* and the pipes run straight up into it, as they rise out of the bottom wall's ledge.
|
|
371
|
-
*/
|
|
372
|
-
function topWallGeometry(w: number, h: number, k: number, slope: number): Geometry {
|
|
373
|
-
const bw = BRICK_WIDTH * k;
|
|
374
|
-
const bh = BRICK_HEIGHT * k;
|
|
375
|
-
const width = w * k;
|
|
376
|
-
const height = h * k;
|
|
377
|
-
const coping = COPING * k;
|
|
378
|
-
const relief = bh * 0.35;
|
|
379
|
-
const lip = relief + 0.025; // the coping stands this far proud of the core, the bricks a little less
|
|
380
|
-
const depth = 0.25;
|
|
381
|
-
const mortar = 0.12 * bh;
|
|
382
|
-
const s = slope * 1.05; // a hair steeper than the sight line, so the underside is always hidden
|
|
383
|
-
const x0 = -width / 2;
|
|
384
|
-
const x1 = width / 2;
|
|
385
|
-
const parts: { geometry: Geometry; position?: Vec3; scale?: Vec3; color?: RGB }[] = [
|
|
386
|
-
// The mortar core behind the bricks
|
|
387
|
-
{
|
|
388
|
-
geometry: prism(
|
|
389
|
-
[
|
|
390
|
-
[-lip, s * lip],
|
|
391
|
-
[-lip, height],
|
|
392
|
-
[-depth, height],
|
|
393
|
-
[-depth, s * depth]
|
|
394
|
-
],
|
|
395
|
-
x0,
|
|
396
|
-
x1,
|
|
397
|
-
rgb('#3a1d0c')
|
|
398
|
-
)
|
|
399
|
-
},
|
|
400
|
-
// The stone coping along the edge, with a darker drip line on its face
|
|
401
|
-
{
|
|
402
|
-
geometry: prism(
|
|
403
|
-
[
|
|
404
|
-
[0, 0],
|
|
405
|
-
[0, coping],
|
|
406
|
-
[-lip, coping],
|
|
407
|
-
[-lip, s * lip]
|
|
408
|
-
],
|
|
409
|
-
x0,
|
|
410
|
-
x1,
|
|
411
|
-
rgb('#c8b896')
|
|
412
|
-
)
|
|
413
|
-
},
|
|
414
|
-
{ geometry: shapeGeometry('cube'), position: [0, coping * 0.11, 0.004], scale: [width, coping * 0.22, 0.008], color: rgb('#a9987a') }
|
|
415
|
-
];
|
|
416
|
-
const rows = Math.ceil((height - coping) / bh);
|
|
417
|
-
for (let r = 0; r < rows; r++) {
|
|
418
|
-
const y0 = coping + r * bh;
|
|
419
|
-
const y1 = Math.min(height, y0 + bh);
|
|
420
|
-
const shift = r % 2 ? bw / 2 : 0;
|
|
421
|
-
for (let c = 0, x = x0 - shift; x < x1; c++, x += bw) {
|
|
422
|
-
const bx0 = Math.max(x, x0);
|
|
423
|
-
const bx1 = Math.min(x + bw, x1);
|
|
424
|
-
if (bx1 - bx0 <= mortar || y1 - y0 <= mortar) continue;
|
|
425
|
-
parts.push({
|
|
426
|
-
geometry: shapeGeometry('cube'),
|
|
427
|
-
position: [(bx0 + bx1) / 2, (y0 + y1) / 2, -lip + relief / 2],
|
|
428
|
-
scale: [bx1 - bx0 - mortar, y1 - y0 - mortar, relief + 0.01],
|
|
429
|
-
color: brickShade(r + 7, c)
|
|
430
|
-
});
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
return merge(parts);
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
export type Walls = { top: Entity; bottom: Entity };
|
|
437
|
-
|
|
438
|
-
export function spawnWalls(world: World, v: View3D, l: Layout): Walls {
|
|
439
|
-
const { back, front, thickness } = wallDepth(v);
|
|
440
|
-
const kb = pointSize(v, back);
|
|
441
|
-
const kf = pointSize(v, front);
|
|
442
|
-
// How steeply the sight line through the top wall's edge climbs, per metre away from the camera
|
|
443
|
-
const slope = ((l.height / 2 - l.topWall) / (l.height / 2)) * v.tanHalf;
|
|
444
|
-
// Wide enough to cover the screen at any point of a wrap: the screen, one shade period, and a margin
|
|
445
|
-
const width = l.width + SHADE_PERIOD * BRICK_WIDTH + BRICK_WIDTH * 4;
|
|
446
|
-
const top = cached(`fb-top-wall:${Math.round(l.width)}x${Math.round(l.topWall)}:${kf.toFixed(6)}:${slope.toFixed(5)}`, () =>
|
|
447
|
-
createShape(topWallGeometry(width, l.topWall + WALL_MARGIN, kf, slope), { center: false, shine: 0.05 })
|
|
448
|
-
);
|
|
449
|
-
const bottomHeight = l.height - l.bottomWallTop;
|
|
450
|
-
const bottom = cached(`fb-wall:${Math.round(l.width)}x${Math.round(bottomHeight)}:${kb.toFixed(6)}:${thickness.toFixed(4)}`, () =>
|
|
451
|
-
createShape(wallGeometry(width, bottomHeight + WALL_MARGIN, kb, thickness), { center: false, shine: 0.05 })
|
|
452
|
-
);
|
|
453
|
-
const walls = {
|
|
454
|
-
top: world.spawn({ mesh: top, color: [1, 1, 1, 1], pickable: false }),
|
|
455
|
-
// The bottom wall is the block turned over: it runs down from its line, its ledge facing up
|
|
456
|
-
bottom: world.spawn({ mesh: bottom, color: [1, 1, 1, 1], pickable: false })
|
|
457
|
-
};
|
|
458
|
-
placeWalls(world, v, l, walls, 0);
|
|
459
|
-
return walls;
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
/**
|
|
463
|
-
* Scrolls the walls with the pipes. They move at the pipes' speed in the world (the pipes pass through
|
|
464
|
-
* them, so they stay put against the bricks), which on screen is a touch slower for the deeper bottom
|
|
465
|
-
* wall: real parallax. Each wraps by a whole shade period, where its bricks look exactly the same.
|
|
466
|
-
*/
|
|
467
|
-
export function placeWalls(world: World, v: View3D, l: Layout, walls: Walls, scroll: number) {
|
|
468
|
-
const { back, front } = wallDepth(v);
|
|
469
|
-
const travelled = scroll * pointSize(v); // metres the pipes have moved
|
|
470
|
-
const place = (wall: Entity, line: number, depth: number, turn: number) => {
|
|
471
|
-
const period = SHADE_PERIOD * BRICK_WIDTH * pointSize(v, depth);
|
|
472
|
-
const centre = at(v, l.width / 2 + (SHADE_PERIOD * BRICK_WIDTH) / 2, line, depth);
|
|
473
|
-
world.set(wall, { position: [centre[0] - (travelled % period), centre[1], centre[2]], rotation: facing(v, turn) });
|
|
474
|
-
};
|
|
475
|
-
// The top wall's front edge, the bottom wall's back edge, sit on their collision lines
|
|
476
|
-
place(walls.top, l.topWall, front, 0);
|
|
477
|
-
place(walls.bottom, l.bottomWallTop, back, Math.PI);
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
// ── Pipes ─────────────────────────────────────────────────────────────
|
|
481
|
-
|
|
482
|
-
/** A pair of pipes: the top one comes out of the top wall down to the gap, the bottom one up out of the bottom wall. */
|
|
483
|
-
export function spawnPipe(world: World, v: View3D, l: Layout, x: number, gapTop: number, gapBottom: number): Entity {
|
|
484
|
-
const k = pointSize(v);
|
|
485
|
-
const s = PIPE_WIDTH / 60;
|
|
486
|
-
const capH = CAP_HEIGHT * s;
|
|
487
|
-
const capW = PIPE_WIDTH + CAP_OVER * 2 * s;
|
|
488
|
-
const cx = x + PIPE_WIDTH / 2;
|
|
489
|
-
const root = world.spawn({ mesh: 'none', position: at(v, cx, 0), rotation: facing(v), pickable: false });
|
|
490
|
-
const add = (mesh: Model, y: number, height: number, width: number, flip = false) =>
|
|
491
|
-
world.spawn({
|
|
492
|
-
mesh,
|
|
493
|
-
parent: root,
|
|
494
|
-
position: local(k, 0, y),
|
|
495
|
-
scale: [width * k, height * k, width * k],
|
|
496
|
-
...(flip ? { rotation: quat.z(Math.PI) } : {}),
|
|
497
|
-
color: [1, 1, 1, 1],
|
|
498
|
-
pickable: false
|
|
499
|
-
});
|
|
500
|
-
const topEnd = Math.max(l.topWall, Math.min(gapTop, l.bottomWallTop));
|
|
501
|
-
const bottomStart = Math.max(l.topWall, Math.min(gapBottom, l.bottomWallTop));
|
|
502
|
-
const topStart = l.topWall - PIPE_INTO_WALL;
|
|
503
|
-
const bottomEnd = l.bottomWallTop + PIPE_INTO_WALL;
|
|
504
|
-
if (topEnd - l.topWall > 0.5) {
|
|
505
|
-
add(pipeMesh(), (topStart + topEnd) / 2, topEnd - topStart, PIPE_WIDTH);
|
|
506
|
-
add(capMesh(), topEnd - capH / 2, capH, capW, true); // its open end faces down into the gap
|
|
507
|
-
}
|
|
508
|
-
if (l.bottomWallTop - bottomStart > 0.5) {
|
|
509
|
-
add(pipeMesh(), (bottomStart + bottomEnd) / 2, bottomEnd - bottomStart, PIPE_WIDTH);
|
|
510
|
-
add(capMesh(), bottomStart + capH / 2, capH, capW);
|
|
511
|
-
}
|
|
512
|
-
return root;
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
export function placePipe(world: World, v: View3D, root: Entity, x: number, updates?: TransformBatch) {
|
|
516
|
-
const position = at(v, x + PIPE_WIDTH / 2, 0);
|
|
517
|
-
if (updates) updates.position(root, position[0], position[1], position[2]);
|
|
518
|
-
else world.set(root, { position });
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
// ── The bird ──────────────────────────────────────────────────────────
|
|
522
|
-
|
|
523
|
-
export type BirdView = { root: Entity; body: Entity; wing: Entity; farWing: Entity; lid: Entity; size: number };
|
|
524
|
-
|
|
525
|
-
/** Where the eye sits on the body, and its size (body units). */
|
|
526
|
-
const EYE: Vec3 = [0.22, 0.15, 0.27];
|
|
527
|
-
const EYE_SIZE = 0.34;
|
|
528
|
-
|
|
529
|
-
/** The bird, its body centred on screen point (x, y). In the ready state it hovers, bobbing gently. */
|
|
530
|
-
export function spawnBird(world: World, v: View3D, x: number, y: number): BirdView {
|
|
531
|
-
const size = BIRD_SIZE * pointSize(v);
|
|
532
|
-
const root = world.spawn({ mesh: 'none', position: at(v, x, y), rotation: facing(v), pickable: false });
|
|
533
|
-
// The far wing behind the body (it peeks out on the upstroke), the near one in front
|
|
534
|
-
const farWing = world.spawn({
|
|
535
|
-
mesh: wingMesh(true),
|
|
536
|
-
parent: root,
|
|
537
|
-
position: [-size * 0.04, size * 0.04, -size * 0.3],
|
|
538
|
-
scale: size,
|
|
539
|
-
color: [1, 1, 1, 1],
|
|
540
|
-
pickable: false
|
|
541
|
-
});
|
|
542
|
-
const body = world.spawn({ mesh: birdMesh(), parent: root, scale: size, color: [1, 1, 1, 1], pickable: false });
|
|
543
|
-
const lid = world.spawn({
|
|
544
|
-
mesh: lidMesh(),
|
|
545
|
-
parent: root,
|
|
546
|
-
position: [EYE[0] * size, EYE[1] * size, EYE[2] * size],
|
|
547
|
-
scale: 0,
|
|
548
|
-
color: [1, 1, 1, 1],
|
|
549
|
-
pickable: false
|
|
550
|
-
});
|
|
551
|
-
const wing = world.spawn({
|
|
552
|
-
mesh: wingMesh(false),
|
|
553
|
-
parent: root,
|
|
554
|
-
position: [-size * 0.02, -size * 0.04, size * 0.38],
|
|
555
|
-
scale: size,
|
|
556
|
-
color: [1, 1, 1, 1],
|
|
557
|
-
pickable: false
|
|
558
|
-
});
|
|
559
|
-
return { root, body, wing, farWing, lid, size };
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
const NEAR_WING_TILT = quat.x(-0.25);
|
|
563
|
-
const FAR_WING_TILT = quat.x(0.25);
|
|
564
|
-
const wingTurn: MutableQuat = [0, 0, 0, 1];
|
|
565
|
-
|
|
566
|
-
/** Moves the bird: leaning by `tilt`, the wings lifted by `lift` (radians: up positive), the far one a beat behind. */
|
|
567
|
-
export function placeBird(world: World, v: View3D, b: BirdView, x: number, y: number, tilt: number, lift: number, farLift = lift) {
|
|
568
|
-
world.set(b.root, { position: at(v, x, y), rotation: facing(v, -tilt) });
|
|
569
|
-
world.set(b.wing, { rotation: quat.multiply(NEAR_WING_TILT, quat.z(-lift, wingTurn), wingTurn) });
|
|
570
|
-
world.set(b.farWing, { rotation: quat.multiply(FAR_WING_TILT, quat.z(-farLift, wingTurn), wingTurn) });
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
/** The squash and stretch of a flap: the body stretches up as it pushes off, then settles. */
|
|
574
|
-
export function flapPop(world: World, b: BirdView) {
|
|
575
|
-
const s = b.size;
|
|
576
|
-
world.stopAnimation(b.body);
|
|
577
|
-
world.animate(b.body, [{ scale: [s * 0.86, s * 1.16, s], at: 0.3 }, { scale: [s * 1.05, s * 0.96, s], at: 0.65 }, { scale: s }], {
|
|
578
|
-
duration: 0.26,
|
|
579
|
-
easing: 'easeOut'
|
|
580
|
-
});
|
|
581
|
-
}
|
|
582
|
-
|
|
583
|
-
/** A blink: the lid closes over the eye and opens again. */
|
|
584
|
-
export function blink(world: World, b: BirdView) {
|
|
585
|
-
const s = b.size * EYE_SIZE;
|
|
586
|
-
world.animate(b.lid, [{ scale: [s, s, s], at: 0.4 }, { scale: [s, s, s], at: 0.6 }, { scale: 0 }], { duration: 0.16, easing: 'linear' });
|
|
587
|
-
}
|
|
588
|
-
|
|
589
|
-
/** Knocked silly by a crash: a shake, eyes half shut, wings drooping. */
|
|
590
|
-
export function dazeBird(world: World, b: BirdView) {
|
|
591
|
-
const s = b.size * EYE_SIZE;
|
|
592
|
-
world.stopAnimation(b.lid);
|
|
593
|
-
world.set(b.lid, { scale: [s, s * 0.55, s], position: [EYE[0] * b.size, (EYE[1] + 0.06) * b.size, EYE[2] * b.size] });
|
|
594
|
-
world.animate(b.root, { shake: b.size * 0.12 }, { duration: 0.35 });
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
/** Back to normal after a crash (a new run). */
|
|
598
|
-
export function wakeBird(world: World, b: BirdView) {
|
|
599
|
-
world.stopAnimation(b.lid);
|
|
600
|
-
world.set(b.lid, { scale: 0, position: [EYE[0] * b.size, EYE[1] * b.size, EYE[2] * b.size] });
|
|
601
|
-
}
|
|
602
|
-
|
|
603
|
-
/** A gentle hover while waiting to start (none while flying). */
|
|
604
|
-
export function hoverBird(world: World, b: BirdView, on: boolean, v: View3D) {
|
|
605
|
-
const amplitude = BIRD_SIZE * pointSize(v) * 0.12;
|
|
606
|
-
world.set(b.root, { bob: on ? { amplitude: [0, amplitude, 0], speed: 3.2 } : null });
|
|
607
|
-
}
|
|
608
|
-
|
|
609
|
-
// ── The crash ─────────────────────────────────────────────────────────
|
|
610
|
-
|
|
611
|
-
const FEATHERS: Color[] = ['#FFD700', '#FF8C00', '#FFE850', '#FFFFFF', '#A0522D'].map((c) => toColor(c));
|
|
612
|
-
|
|
613
|
-
/** Feathers fly and a puff of dust where the bird hit. */
|
|
614
|
-
export function crashBurst(world: World, v: View3D, x: number, y: number) {
|
|
615
|
-
const k = pointSize(v);
|
|
616
|
-
const size = BIRD_SIZE * k;
|
|
617
|
-
const where = at(v, x, y, v.playDepth - size * 0.6);
|
|
618
|
-
effects.shatter(world, {
|
|
619
|
-
position: where,
|
|
620
|
-
count: 16,
|
|
621
|
-
mesh: 'sphere',
|
|
622
|
-
size: size * 0.12,
|
|
623
|
-
speed: size * 7,
|
|
624
|
-
lifetime: 0.7,
|
|
625
|
-
gravity: -size * 18,
|
|
626
|
-
colors: FEATHERS,
|
|
627
|
-
dust: false
|
|
628
|
-
});
|
|
629
|
-
effects.dust(world, { position: where, count: 5, size: size * 0.9, speed: size * 2, lifetime: 0.5, color: [1, 1, 1, 0.75] });
|
|
630
|
-
}
|