react-native-games 1.3.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (195) hide show
  1. package/lib/module/games/balloon-blaster/BalloonBlaster.js +1 -1
  2. package/lib/module/games/balloon-blaster/BalloonBlasterConstants.js +1 -1
  3. package/lib/module/games/balloon-blaster/BalloonBlasterService.js +1 -1
  4. package/lib/module/games/balloon-blaster/BalloonBlasterStore.js +1 -1
  5. package/lib/module/games/balloon-blaster/components/BalloonComponent.js +1 -1
  6. package/lib/module/games/balloon-blaster/components/GameArea.js +1 -1
  7. package/lib/module/games/balloon-blaster/components/GameBackground.js +1 -1
  8. package/lib/module/games/balloon-blaster/components/ScoreBoard.js +1 -1
  9. package/lib/module/games/balloon-blaster/components/index.js +1 -1
  10. package/lib/module/games/bike-racing/BikeRacing.js +1 -1
  11. package/lib/module/games/bike-racing/BikeRacingConstants.js +1 -1
  12. package/lib/module/games/bike-racing/BikeRacingService.js +1 -1
  13. package/lib/module/games/bike-racing/BikeRacingStore.js +1 -1
  14. package/lib/module/games/bike-racing/components/BikeComponent.js +1 -1
  15. package/lib/module/games/bike-racing/components/GameBackground.js +1 -1
  16. package/lib/module/games/bike-racing/components/ScoreBoard.js +1 -1
  17. package/lib/module/games/bike-racing/components/index.js +1 -1
  18. package/lib/module/games/bike-racing/index.js +1 -1
  19. package/lib/module/games/block-blast/BlockBlast.js +1 -1
  20. package/lib/module/games/block-blast/BlockBlastConstants.js +1 -1
  21. package/lib/module/games/block-blast/BlockBlastService.js +1 -1
  22. package/lib/module/games/block-blast/BlockBlastStore.js +1 -1
  23. package/lib/module/games/block-blast/components/BlockPieceComponent.js +1 -1
  24. package/lib/module/games/block-blast/components/GameArea.js +1 -1
  25. package/lib/module/games/block-blast/components/GameBackground.js +1 -1
  26. package/lib/module/games/block-blast/components/GridComponent.js +1 -1
  27. package/lib/module/games/block-blast/components/ScoreBoard.js +1 -1
  28. package/lib/module/games/block-blast/components/index.js +1 -1
  29. package/lib/module/games/block-blast/index.js +1 -1
  30. package/lib/module/games/bubble-shooter/BubbleShooter.js +1 -1
  31. package/lib/module/games/bubble-shooter/BubbleShooterConstants.js +1 -1
  32. package/lib/module/games/bubble-shooter/BubbleShooterService.js +1 -1
  33. package/lib/module/games/bubble-shooter/BubbleShooterStore.js +1 -1
  34. package/lib/module/games/bubble-shooter/components/GameArea.js +1 -1
  35. package/lib/module/games/bubble-shooter/components/GameBackground.js +1 -1
  36. package/lib/module/games/bubble-shooter/components/ScoreBoard.js +1 -1
  37. package/lib/module/games/bubble-shooter/components/index.js +1 -1
  38. package/lib/module/games/bubble-shooter/index.js +1 -1
  39. package/lib/module/games/candy-crush/CandyCrush.js +1 -1
  40. package/lib/module/games/candy-crush/CandyCrushConstants.js +1 -1
  41. package/lib/module/games/candy-crush/CandyCrushService.js +1 -1
  42. package/lib/module/games/candy-crush/CandyCrushStore.js +1 -1
  43. package/lib/module/games/candy-crush/components/CandyItem.js +1 -1
  44. package/lib/module/games/candy-crush/components/GameBackground.js +1 -1
  45. package/lib/module/games/candy-crush/components/GameGrid.js +1 -1
  46. package/lib/module/games/candy-crush/components/ScoreBoard.js +1 -1
  47. package/lib/module/games/candy-crush/components/index.js +1 -1
  48. package/lib/module/games/candy-crush/index.js +1 -1
  49. package/lib/module/games/car-racing/CarRacing.js +1 -1
  50. package/lib/module/games/car-racing/CarRacingConstants.js +1 -1
  51. package/lib/module/games/car-racing/CarRacingService.js +1 -1
  52. package/lib/module/games/car-racing/CarRacingStore.js +1 -1
  53. package/lib/module/games/car-racing/components/CarComponent.js +1 -1
  54. package/lib/module/games/car-racing/components/GameBackground.js +1 -1
  55. package/lib/module/games/car-racing/components/ScoreBoard.js +1 -1
  56. package/lib/module/games/car-racing/components/index.js +1 -1
  57. package/lib/module/games/colors-sort/ColorsSort.js +1 -1
  58. package/lib/module/games/colors-sort/ColorsSortConstants.js +1 -1
  59. package/lib/module/games/colors-sort/ColorsSortService.js +1 -1
  60. package/lib/module/games/colors-sort/ColorsSortStore.js +1 -1
  61. package/lib/module/games/colors-sort/components/ColorContainer.js +1 -1
  62. package/lib/module/games/colors-sort/components/GameBackground.js +1 -1
  63. package/lib/module/games/colors-sort/components/ScoreBoard.js +1 -1
  64. package/lib/module/games/colors-sort/components/index.js +1 -1
  65. package/lib/module/games/dino-jump/DinoJump.js +1 -1
  66. package/lib/module/games/dino-jump/DinoJumpConstants.js +1 -1
  67. package/lib/module/games/dino-jump/DinoJumpService.js +1 -1
  68. package/lib/module/games/dino-jump/DinoJumpStore.js +1 -1
  69. package/lib/module/games/dino-jump/components/DinoSprite.js +1 -1
  70. package/lib/module/games/dino-jump/components/GameArea.js +1 -1
  71. package/lib/module/games/dino-jump/components/GameBackground.js +1 -1
  72. package/lib/module/games/dino-jump/components/ObstacleSprite.js +1 -1
  73. package/lib/module/games/dino-jump/components/ScoreBoard.js +1 -1
  74. package/lib/module/games/dino-jump/components/StarSprite.js +1 -1
  75. package/lib/module/games/dino-jump/components/index.js +1 -1
  76. package/lib/module/games/flappy-bird/FlappyBird.js +1 -1
  77. package/lib/module/games/flappy-bird/FlappyBirdConstants.js +1 -1
  78. package/lib/module/games/flappy-bird/FlappyBirdStore.js +1 -1
  79. package/lib/module/games/flappy-bird/components/Bird.js +1 -1
  80. package/lib/module/games/flappy-bird/components/GameArea.js +1 -1
  81. package/lib/module/games/flappy-bird/components/GameBackground.js +1 -1
  82. package/lib/module/games/flappy-bird/components/Pipes.js +1 -1
  83. package/lib/module/games/flappy-bird/components/ScoreBoard.js +1 -1
  84. package/lib/module/games/flappy-bird/components/index.js +1 -1
  85. package/lib/module/games/fruit-merger/FruitMerger.js +1 -1
  86. package/lib/module/games/fruit-merger/FruitMergerConstants.js +1 -1
  87. package/lib/module/games/fruit-merger/FruitMergerService.js +1 -1
  88. package/lib/module/games/fruit-merger/FruitMergerStore.js +1 -1
  89. package/lib/module/games/fruit-merger/components/FruitItem.js +1 -1
  90. package/lib/module/games/fruit-merger/components/GameArea.js +1 -1
  91. package/lib/module/games/fruit-merger/components/GameBackground.js +1 -1
  92. package/lib/module/games/fruit-merger/components/ScoreBoard.js +1 -1
  93. package/lib/module/games/fruit-merger/components/index.js +1 -1
  94. package/lib/module/games/fruit-ninja/FruitNinja.js +1 -1
  95. package/lib/module/games/fruit-ninja/FruitNinjaConstants.js +1 -1
  96. package/lib/module/games/fruit-ninja/FruitNinjaService.js +1 -1
  97. package/lib/module/games/fruit-ninja/FruitNinjaStore.js +1 -1
  98. package/lib/module/games/fruit-ninja/components/FruitComponent.js +1 -1
  99. package/lib/module/games/fruit-ninja/components/GameArea.js +1 -1
  100. package/lib/module/games/fruit-ninja/components/GameBackground.js +1 -1
  101. package/lib/module/games/fruit-ninja/components/ScoreBoard.js +1 -1
  102. package/lib/module/games/fruit-ninja/components/index.js +1 -1
  103. package/lib/module/games/game-2048/Game2048.js +1 -1
  104. package/lib/module/games/game-2048/Game2048Constants.js +1 -1
  105. package/lib/module/games/game-2048/Game2048Service.js +1 -1
  106. package/lib/module/games/game-2048/Game2048Store.js +1 -1
  107. package/lib/module/games/game-2048/components/GameBackground.js +1 -1
  108. package/lib/module/games/game-2048/components/GameGrid.js +1 -1
  109. package/lib/module/games/game-2048/components/GameTile.js +1 -1
  110. package/lib/module/games/game-2048/components/ScoreBoard.js +1 -1
  111. package/lib/module/games/game-2048/components/index.js +1 -1
  112. package/lib/module/games/maze-runner/MazeRunner.js +1 -1
  113. package/lib/module/games/maze-runner/MazeRunnerConstants.js +1 -1
  114. package/lib/module/games/maze-runner/MazeRunnerService.js +1 -1
  115. package/lib/module/games/maze-runner/components/EnhancedBallComponent.js +1 -1
  116. package/lib/module/games/maze-runner/components/EnhancedGameArea.js +1 -1
  117. package/lib/module/games/maze-runner/components/GameBackground.js +1 -1
  118. package/lib/module/games/maze-runner/components/ScoreBoard.js +1 -1
  119. package/lib/module/games/maze-runner/components/SkiaPipeComponent.js +1 -1
  120. package/lib/module/games/maze-runner/components/StaticGameBackground.js +1 -1
  121. package/lib/module/games/maze-runner/components/WallComponent.js +1 -1
  122. package/lib/module/games/maze-runner/components/index.js +1 -1
  123. package/lib/module/games/perfect-circle/PerfectCircle.js +1 -1
  124. package/lib/module/games/perfect-circle/PerfectCircleConstants.js +1 -1
  125. package/lib/module/games/perfect-circle/PerfectCircleService.js +1 -1
  126. package/lib/module/games/perfect-circle/PerfectCircleStore.js +1 -1
  127. package/lib/module/games/perfect-circle/components/DrawingCanvas.js +1 -1
  128. package/lib/module/games/perfect-circle/components/GameBackground.js +1 -1
  129. package/lib/module/games/perfect-circle/components/ScoreBoard.js +1 -1
  130. package/lib/module/games/perfect-circle/index.js +1 -1
  131. package/lib/module/games/popit-fidget/PopitFidget.js +1 -1
  132. package/lib/module/games/popit-fidget/PopitFidgetConstants.js +1 -1
  133. package/lib/module/games/popit-fidget/PopitFidgetService.js +1 -1
  134. package/lib/module/games/popit-fidget/PopitFidgetStore.js +1 -1
  135. package/lib/module/games/popit-fidget/components/BubbleComponent.js +1 -1
  136. package/lib/module/games/popit-fidget/components/FidgetGrid.js +1 -1
  137. package/lib/module/games/popit-fidget/components/GameBackground.js +1 -1
  138. package/lib/module/games/popit-fidget/components/ScoreBoard.js +1 -1
  139. package/lib/module/games/popit-fidget/components/index.js +1 -1
  140. package/lib/module/games/sliding-numbers/SlidingNumbers.js +1 -1
  141. package/lib/module/games/sliding-numbers/SlidingNumbersConstants.js +1 -1
  142. package/lib/module/games/sliding-numbers/SlidingNumbersService.js +1 -1
  143. package/lib/module/games/sliding-numbers/SlidingNumbersStore.js +1 -1
  144. package/lib/module/games/sliding-numbers/components/GameBackground.js +1 -1
  145. package/lib/module/games/sliding-numbers/components/NumbersGrid.js +1 -1
  146. package/lib/module/games/sliding-numbers/components/NumbersTile.js +1 -1
  147. package/lib/module/games/sliding-numbers/components/ScoreBoard.js +1 -1
  148. package/lib/module/games/sliding-numbers/components/index.js +1 -1
  149. package/lib/module/games/snake/Snake.js +1 -1
  150. package/lib/module/games/snake/SnakeConstants.js +1 -1
  151. package/lib/module/games/snake/SnakeService.js +1 -1
  152. package/lib/module/games/snake/SnakeStore.js +1 -1
  153. package/lib/module/games/snake/components/GameBackground.js +1 -1
  154. package/lib/module/games/snake/components/GameGrid.js +1 -1
  155. package/lib/module/games/snake/components/ScoreBoard.js +1 -1
  156. package/lib/module/games/snake/components/index.js +1 -1
  157. package/lib/module/games/snake/index.js +1 -1
  158. package/lib/module/games/space-fighter/SpaceFighter.js +1 -1
  159. package/lib/module/games/space-fighter/SpaceFighterConstants.js +1 -1
  160. package/lib/module/games/space-fighter/SpaceFighterService.js +1 -1
  161. package/lib/module/games/space-fighter/SpaceFighterStore.js +1 -1
  162. package/lib/module/games/space-fighter/components/AsteroidComponent.js +1 -1
  163. package/lib/module/games/space-fighter/components/GameArea.js +1 -1
  164. package/lib/module/games/space-fighter/components/GameBackground.js +1 -1
  165. package/lib/module/games/space-fighter/components/ScoreBoard.js +1 -1
  166. package/lib/module/games/space-fighter/components/Spacecraft3D.js +1 -1
  167. package/lib/module/games/space-fighter/components/SpacecraftPath.js +1 -1
  168. package/lib/module/games/space-fighter/components/index.js +1 -1
  169. package/lib/module/games/whack-a-mole/WhackAMole.js +1 -1
  170. package/lib/module/games/whack-a-mole/WhackAMoleConstants.js +1 -1
  171. package/lib/module/games/whack-a-mole/WhackAMoleService.js +1 -1
  172. package/lib/module/games/whack-a-mole/WhackAMoleStore.js +1 -1
  173. package/lib/module/games/whack-a-mole/components/GameBackground.js +1 -1
  174. package/lib/module/games/whack-a-mole/components/GameGrid.js +1 -1
  175. package/lib/module/games/whack-a-mole/components/GameHole.js +1 -1
  176. package/lib/module/games/whack-a-mole/components/MoleCharacter.js +1 -1
  177. package/lib/module/games/whack-a-mole/components/ScoreBoard.js +1 -1
  178. package/lib/module/games/whack-a-mole/components/index.js +1 -1
  179. package/lib/module/helpers/AnimationFrame.js +1 -1
  180. package/lib/module/helpers/AnimationTracker.js +1 -1
  181. package/lib/module/helpers/ErrorHandler.js +1 -1
  182. package/lib/module/helpers/GameControlButton.js +1 -1
  183. package/lib/module/helpers/GameOverModal.js +1 -1
  184. package/lib/module/helpers/GameSettingsModal.js +1 -1
  185. package/lib/module/helpers/ParticleBlast.js +1 -1
  186. package/lib/module/helpers/ScoreBoardContainer.js +1 -1
  187. package/lib/module/helpers/index.js +1 -1
  188. package/lib/module/index.js +1 -1
  189. package/lib/module/services/GamesConstants.js +1 -1
  190. package/lib/module/services/GamesService.js +1 -1
  191. package/lib/module/services/HapticsService.js +1 -1
  192. package/lib/module/services/ScoringService.js +1 -1
  193. package/lib/module/services/SoundsService.js +1 -1
  194. package/lib/module/services/UtilsService.js +1 -1
  195. package/package.json +5 -2
@@ -1 +1 @@
1
- "use strict";import React from 'react';import{View}from 'react-native';import{jsx as _jsx,jsxs as _jsxs}from "react/jsx-runtime";export const AsteroidComponent = React.memo(({asteroid})=>{return _jsxs(View,{style:{position:'absolute',left:asteroid.x,top:asteroid.y,width:asteroid.width,height:asteroid.height,backgroundColor:'#6B4423',borderRadius:15,shadowColor:'#2F1B14',shadowOffset:{width:3,height:4},shadowOpacity:0.7,shadowRadius:10,borderWidth:1,borderColor:'rgba(139,69,19,0.8)'},children:[_jsx(View,{style:{position:'absolute',left:2,top:2,width:asteroid.width - 4,height:Math.max(0,asteroid.height - 4),backgroundColor:'rgba(160,82,45,0.4)',borderRadius:12}}),_jsx(View,{style:{position:'absolute',left:asteroid.width * 0.25,top:asteroid.height * 0.3,width:12,height:8,backgroundColor:'rgba(47,27,20,0.8)',borderRadius:6}}),_jsx(View,{style:{position:'absolute',left:asteroid.width * 0.65,top:asteroid.height * 0.6,width:8,height:6,backgroundColor:'rgba(47,27,20,0.9)',borderRadius:4}}),_jsx(View,{style:{position:'absolute',left:asteroid.width * 0.15,top:asteroid.height * 0.7,width:5,height:4,backgroundColor:'rgba(47,27,20,0.7)',borderRadius:2}}),_jsx(View,{style:{position:'absolute',left:asteroid.width * 0.45,top:asteroid.height * 0.2,width:4,height:4,backgroundColor:'rgba(101,67,33,0.8)',borderRadius:2}}),_jsx(View,{style:{position:'absolute',left:asteroid.width * 0.8,top:asteroid.height * 0.4,width:3,height:3,backgroundColor:'rgba(139,69,19,0.9)',borderRadius:1.5}}),_jsx(View,{style:{position:'absolute',left:asteroid.width * 0.1,top:asteroid.height * 0.1,width:asteroid.width * 0.3,height:asteroid.height * 0.2,backgroundColor:'rgba(205,133,63,0.3)',borderRadius:8}})]});},(prevProps,nextProps)=>{const prev = prevProps.asteroid;const next = nextProps.asteroid;return prev.id === next.id && prev.x === next.x && prev.y === next.y && prev.width === next.width && prev.height === next.height;});
1
+ "use strict";import o from"react";import{View as t}from"react-native";import{jsx as r,jsxs as e}from"react/jsx-runtime";export const AsteroidComponent=o.memo(({asteroid:o})=>e(t,{style:{position:"absolute",left:o.x,top:o.y,width:o.width,height:o.height,backgroundColor:"#6B4423",borderRadius:15,shadowColor:"#2F1B14",shadowOffset:{width:3,height:4},shadowOpacity:.7,shadowRadius:10,borderWidth:1,borderColor:"rgba(139, 69, 19, 0.8)"},children:[r(t,{style:{position:"absolute",left:2,top:2,width:o.width-4,height:Math.max(0,o.height-4),backgroundColor:"rgba(160, 82, 45, 0.4)",borderRadius:12}}),r(t,{style:{position:"absolute",left:.25*o.width,top:.3*o.height,width:12,height:8,backgroundColor:"rgba(47, 27, 20, 0.8)",borderRadius:6}}),r(t,{style:{position:"absolute",left:.65*o.width,top:.6*o.height,width:8,height:6,backgroundColor:"rgba(47, 27, 20, 0.9)",borderRadius:4}}),r(t,{style:{position:"absolute",left:.15*o.width,top:.7*o.height,width:5,height:4,backgroundColor:"rgba(47, 27, 20, 0.7)",borderRadius:2}}),r(t,{style:{position:"absolute",left:.45*o.width,top:.2*o.height,width:4,height:4,backgroundColor:"rgba(101, 67, 33, 0.8)",borderRadius:2}}),r(t,{style:{position:"absolute",left:.8*o.width,top:.4*o.height,width:3,height:3,backgroundColor:"rgba(139, 69, 19, 0.9)",borderRadius:1.5}}),r(t,{style:{position:"absolute",left:.1*o.width,top:.1*o.height,width:.3*o.width,height:.2*o.height,backgroundColor:"rgba(205, 133, 63, 0.3)",borderRadius:8}})]}),(o,t)=>{const r=o.asteroid,e=t.asteroid;return r.id===e.id&&r.x===e.x&&r.y===e.y&&r.width===e.width&&r.height===e.height});
@@ -1 +1 @@
1
- "use strict";import React,{useRef,useEffect,useCallback,useState,useMemo}from 'react';import{View,Text,StyleSheet,Dimensions}from 'react-native';import{Gesture,GestureDetector}from 'react-native-gesture-handler';import{useSpaceFighterStore}from "../SpaceFighterStore.js";import{createSpaceFighterService}from "../SpaceFighterService.js";import{playSound,GAME_SOUNDS}from "../../../services/SoundsService.js";import{playHaptic,HapticType}from "../../../services/HapticsService.js";import{ParticleBlast}from "../../../helpers/index.js";import{AsteroidComponent}from "./AsteroidComponent.js";import{Spacecraft3D}from "./Spacecraft3D.js";import{SpacecraftPath}from "./SpacecraftPath.js";import{jsx as _jsx,jsxs as _jsxs}from "react/jsx-runtime";const{width,height}= Dimensions.get('window');export const GameArea = React.memo(()=>{const asteroids = useSpaceFighterStore(state => state.asteroids);const spacecraft = useSpaceFighterStore(state => state.spacecraft);const spacecraftPath = useSpaceFighterStore(state => state.spacecraftPath);const isControllingSpacecraft = useSpaceFighterStore(state => state.isControllingSpacecraft);const isPlaying = useSpaceFighterStore(state => state.isPlaying);const updateSpacecraft = useSpaceFighterStore(state => state.updateSpacecraft);const setSpacecraftPath = useSpaceFighterStore(state => state.setSpacecraftPath);const setIsControllingSpacecraft = useSpaceFighterStore(state => state.setIsControllingSpacecraft);const markAsteroidPassed = useSpaceFighterStore(state => state.markAsteroidPassed);const loseLife = useSpaceFighterStore(state => state.loseLife);const gameService = useRef(createSpaceFighterService(width,height)).current;const currentSpacecraftPath = useRef([]);const initialSpacecraftPosition = useRef(null);const initialTouchPosition = useRef(null);const pendingSpacecraftUpdate = useRef(null);const animationFrameId = useRef(null);const lastCollisionTime = useRef(0);const [activeBlasts,setActiveBlasts] = useState([]);const particleColors = useMemo(()=> ['#ff6b6b','#ff8e53','#ff6b35'],[]);const playSuccessSound = useCallback(()=>{playSound(GAME_SOUNDS.SPACE_FIGHTER.SUCCESS,true);playHaptic(HapticType.LIGHT,true);},[]);const playCollisionSound = useCallback(()=>{playSound(GAME_SOUNDS.SPACE_FIGHTER.COLLISION,true);playHaptic(HapticType.HEAVY,true);},[]);const handleSpacecraftControlStart = useCallback((x,y)=>{const currentSpacecraft = useSpaceFighterStore.getState().spacecraft;const controlledSpacecraft = gameService.controlSpacecraft({...currentSpacecraft},x,y);updateSpacecraft(controlledSpacecraft);setIsControllingSpacecraft(true);currentSpacecraftPath.current = [{x,y}];setSpacecraftPath([{x,y}]);},[gameService,updateSpacecraft,setIsControllingSpacecraft,setSpacecraftPath]);const processPendingSpacecraftUpdate = useCallback(()=>{if(pendingSpacecraftUpdate.current){const{x,y}= pendingSpacecraftUpdate.current;const currentSpacecraft = useSpaceFighterStore.getState().spacecraft;const controlledSpacecraft = gameService.controlSpacecraft({...currentSpacecraft},x,y);updateSpacecraft(controlledSpacecraft);currentSpacecraftPath.current.push({x,y});if(currentSpacecraftPath.current.length > 8){currentSpacecraftPath.current.shift();}if(currentSpacecraftPath.current.length % 3 === 0){setSpacecraftPath([...currentSpacecraftPath.current]);}pendingSpacecraftUpdate.current = null;}animationFrameId.current = null;},[gameService,updateSpacecraft,setSpacecraftPath]);const handleSpacecraftControlMove = useCallback((x,y)=>{pendingSpacecraftUpdate.current ={x,y};if(animationFrameId.current === null){animationFrameId.current = requestAnimationFrame(processPendingSpacecraftUpdate);}},[processPendingSpacecraftUpdate]);const handleSpacecraftControlEnd = useCallback(()=>{if(animationFrameId.current !== null){cancelAnimationFrame(animationFrameId.current);animationFrameId.current = null;}if(pendingSpacecraftUpdate.current){processPendingSpacecraftUpdate();}const currentSpacecraft = useSpaceFighterStore.getState().spacecraft;const releasedSpacecraft = gameService.releaseSpacecraft({...currentSpacecraft});updateSpacecraft(releasedSpacecraft);setIsControllingSpacecraft(false);setTimeout(()=>{currentSpacecraftPath.current = [];setSpacecraftPath([]);},300);},[gameService,updateSpacecraft,setIsControllingSpacecraft,setSpacecraftPath,processPendingSpacecraftUpdate]);useEffect(()=>{if(!isPlaying)return;const interval = setInterval(()=>{const state = useSpaceFighterStore.getState();const currentSpacecraft = state.spacecraft;const currentAsteroids = state.asteroids;if(currentAsteroids.length === 0)return;const collision = gameService.checkCollision(currentSpacecraft,currentAsteroids);const now = Date.now();if(collision.collision && now - lastCollisionTime.current > 1000){lastCollisionTime.current = now;playCollisionSound();const blastId = `blast-${now}`;setActiveBlasts(prev => [...prev,{id:blastId,x:currentSpacecraft.x,y:currentSpacecraft.y}]);setTimeout(()=>{setActiveBlasts(prev => prev.filter(blast => blast.id !== blastId));},800);loseLife();return;}const passedAsteroids = gameService.checkAsteroidPass(currentSpacecraft,currentAsteroids);if(passedAsteroids.length > 0){passedAsteroids.forEach(pairId =>{markAsteroidPassed(pairId);playSuccessSound();});}},100);return()=> clearInterval(interval);},[isPlaying,gameService,playCollisionSound,loseLife,updateSpacecraft,markAsteroidPassed,playSuccessSound]);const panGesture = useMemo(()=> Gesture.Pan().onStart(event =>{const currentSpacecraft = useSpaceFighterStore.getState().spacecraft;initialSpacecraftPosition.current ={x:currentSpacecraft.x,y:currentSpacecraft.y};initialTouchPosition.current ={x:event.absoluteX,y:event.absoluteY};handleSpacecraftControlStart(currentSpacecraft.x,currentSpacecraft.y);}).onUpdate(event =>{if(!initialSpacecraftPosition.current || !initialTouchPosition.current){return;}const dx = event.absoluteX - initialTouchPosition.current.x;const newX = initialSpacecraftPosition.current.x + dx;const newY = initialSpacecraftPosition.current.y;handleSpacecraftControlMove(newX,newY);}).onEnd(()=>{initialTouchPosition.current = null;handleSpacecraftControlEnd();}).onFinalize(()=>{initialTouchPosition.current = null;handleSpacecraftControlEnd();}).runOnJS(true),[handleSpacecraftControlStart,handleSpacecraftControlMove,handleSpacecraftControlEnd]);return _jsxs(View,{style:[styles.gameArea],children:[_jsx(SpacecraftPath,{path:spacecraftPath}),asteroids.map(asteroid => _jsx(AsteroidComponent,{asteroid:asteroid},asteroid.id)),activeBlasts.map(blast => _jsx(ParticleBlast,{x:blast.x,y:blast.y,colors:particleColors,particleCount:12,duration:800},blast.id)),_jsx(Spacecraft3D,{spacecraft:spacecraft,isControlled:isControllingSpacecraft}),_jsx(GestureDetector,{gesture:panGesture,children:_jsx(View,{style:styles.gestureOverlay})}),asteroids.length === 0 && _jsxs(View,{style:styles.instructionsContainer,children:[_jsx(Text,{style:styles.instructionsEmoji,children:"\uD83D\uDE80"}),_jsx(Text,{style:styles.instructionsTitle,children:"Navigate your spacecraft through the space!"}),_jsx(Text,{style:styles.instructionsSubtitle,children:"Touch and drag to control your spacecraft"})]})]});});const styles = StyleSheet.create({gameArea:{flex:1,position:'relative'},gestureOverlay:{position:'absolute',top:0,left:0,right:0,bottom:0,backgroundColor:'transparent',zIndex:10},instructionsContainer:{position:'absolute',top:'33%',left:0,right:0,opacity:0.6,alignItems:'center',justifyContent:'center'},instructionsEmoji:{textAlign:'center',fontSize:24,marginBottom:12},instructionsTitle:{color:'#ffffff',textAlign:'center',fontSize:18,fontWeight:'bold',marginBottom:8},instructionsSubtitle:{color:'#ffffff',textAlign:'center',marginTop:8}});
1
+ "use strict";import t,{useRef as e,useEffect as r,useCallback as o,useState as n,useMemo as i}from"react";import{View as s,Text as c,StyleSheet as l,Dimensions as a}from"react-native";import{Gesture as f,GestureDetector as m}from"react-native-gesture-handler";import{useSpaceFighterStore as u}from"../SpaceFighterStore.js";import{createSpaceFighterService as p}from"../SpaceFighterService.js";import{playSound as d,GAME_SOUNDS as h}from"../../../services/SoundsService.js";import{playHaptic as g,HapticType as y}from"../../../services/HapticsService.js";import{ParticleBlast as x}from"../../../helpers/index.js";import{AsteroidComponent as j}from"./AsteroidComponent.js";import{Spacecraft3D as v}from"./Spacecraft3D.js";import{SpacecraftPath as S}from"./SpacecraftPath.js";import{jsx as b,jsxs as A}from"react/jsx-runtime";const{width:C,height:T}=a.get("window");export const GameArea=t.memo(()=>{const t=u(t=>t.asteroids),l=u(t=>t.spacecraft),a=u(t=>t.spacecraftPath),I=u(t=>t.isControllingSpacecraft),w=u(t=>t.isPlaying),z=u(t=>t.updateSpacecraft),B=u(t=>t.setSpacecraftPath),D=u(t=>t.setIsControllingSpacecraft),k=u(t=>t.markAsteroidPassed),q=u(t=>t.loseLife),E=e(p(C,T)).current,G=e([]),H=e(null),N=e(null),O=e(null),P=e(null),W=e(0),[J,K]=n([]),L=i(()=>["#ff6b6b","#ff8e53","#ff6b35"],[]),M=o(()=>{d(h.SPACE_FIGHTER.SUCCESS,!0),g(y.LIGHT,!0)},[]),Q=o(()=>{d(h.SPACE_FIGHTER.COLLISION,!0),g(y.HEAVY,!0)},[]),R=o((t,e)=>{const r=u.getState().spacecraft,o=E.controlSpacecraft({...r},t,e);z(o),D(!0),G.current=[{x:t,y:e}],B([{x:t,y:e}])},[E,z,D,B]),U=o(()=>{if(O.current){const{x:t,y:e}=O.current,r=u.getState().spacecraft,o=E.controlSpacecraft({...r},t,e);z(o),G.current.push({x:t,y:e}),G.current.length>8&&G.current.shift(),G.current.length%3==0&&B([...G.current]),O.current=null}P.current=null},[E,z,B]),V=o((t,e)=>{O.current={x:t,y:e},null===P.current&&(P.current=requestAnimationFrame(U))},[U]),X=o(()=>{null!==P.current&&(cancelAnimationFrame(P.current),P.current=null),O.current&&U();const t=u.getState().spacecraft,e=E.releaseSpacecraft({...t});z(e),D(!1),setTimeout(()=>{G.current=[],B([])},300)},[E,z,D,B,U]);r(()=>{if(!w)return;const t=setInterval(()=>{const t=u.getState(),e=t.spacecraft,r=t.asteroids;if(0===r.length)return;const o=E.checkCollision(e,r),n=Date.now();if(o.collision&&n-W.current>1e3){W.current=n,Q();const t="blast-"+n;return K(r=>[...r,{id:t,x:e.x,y:e.y}]),setTimeout(()=>{K(e=>e.filter(e=>e.id!==t))},800),void q()}const i=E.checkAsteroidPass(e,r);i.length>0&&i.forEach(t=>{k(t),M()})},100);return()=>clearInterval(t)},[w,E,Q,q,z,k,M]);const Y=i(()=>f.Pan().onStart(t=>{const e=u.getState().spacecraft;H.current={x:e.x,y:e.y},N.current={x:t.absoluteX,y:t.absoluteY},R(e.x,e.y)}).onUpdate(t=>{if(!H.current||!N.current)return;const e=t.absoluteX-N.current.x,r=H.current.x+e,o=H.current.y;V(r,o)}).onEnd(()=>{N.current=null,X()}).onFinalize(()=>{N.current=null,X()}).runOnJS(!0),[R,V,X]);return A(s,{style:[F.gameArea],children:[b(S,{path:a}),t.map(t=>b(j,{asteroid:t},t.id)),J.map(t=>b(x,{x:t.x,y:t.y,colors:L,particleCount:12,duration:800},t.id)),b(v,{spacecraft:l,isControlled:I}),b(m,{gesture:Y,children:b(s,{style:F.gestureOverlay})}),0===t.length&&A(s,{style:F.instructionsContainer,children:[b(c,{style:F.instructionsEmoji,children:"\ud83d\ude80"}),b(c,{style:F.instructionsTitle,children:"Navigate your spacecraft through the space!"}),b(c,{style:F.instructionsSubtitle,children:"Touch and drag to control your spacecraft"})]})]})});const F=l.create({gameArea:{flex:1,position:"relative"},gestureOverlay:{position:"absolute",top:0,left:0,right:0,bottom:0,backgroundColor:"transparent",zIndex:10},instructionsContainer:{position:"absolute",top:"33%",left:0,right:0,opacity:.6,alignItems:"center",justifyContent:"center"},instructionsEmoji:{textAlign:"center",fontSize:24,marginBottom:12},instructionsTitle:{color:"#ffffff",textAlign:"center",fontSize:18,fontWeight:"bold",marginBottom:8},instructionsSubtitle:{color:"#ffffff",textAlign:"center",marginTop:8}});
@@ -1 +1 @@
1
- "use strict";import React from 'react';import{View,Dimensions}from 'react-native';import{Canvas,LinearGradient,Rect,Circle,Group,Shadow,vec}from '@shopify/react-native-skia';import{jsx as _jsx,jsxs as _jsxs}from "react/jsx-runtime";const{width,height}= Dimensions.get('window');export const GameBackground = React.memo(({children})=>{return _jsxs(View,{style:{flex:1},children:[_jsxs(Canvas,{style:{position:'absolute',top:0,left:0,right:0,bottom:0,width,height},children:[_jsx(Rect,{x:0,y:0,width:width,height:height,children:_jsx(LinearGradient,{start:vec(0,0),end:vec(0,height),colors:['#0c0a1f','#1a1b3a','#2d1b69','#1e1b4b','#0c0a1f']})}),_jsx(Group,{children:Array.from({length:40},(_,i)=>{const x = width / 8 *(i % 8)+ i % 5 * 25;const y = height / 5 * Math.floor(i / 8)+ i % 3 * 40;const size = 1 + i % 3 * 0.4;return _jsx(Circle,{cx:x,cy:y,r:size,color:"#ffffff",opacity:0.6},`star-${i}`);})}),_jsx(Group,{children:Array.from({length:8},(_,i)=>{const positions = [{x:width * 0.15,y:height * 0.2},{x:width * 0.8,y:height * 0.3},{x:width * 0.3,y:height * 0.5},{x:width * 0.7,y:height * 0.6},{x:width * 0.2,y:height * 0.7},{x:width * 0.85,y:height * 0.8},{x:width * 0.5,y:height * 0.15},{x:width * 0.6,y:height * 0.85}];const pos = positions[i];if(!pos)return null;const size = 2.5 + i % 2 * 0.5;return _jsx(Group,{children:_jsx(Circle,{cx:pos.x,cy:pos.y,r:size,color:"#ffffff",opacity:0.8,children:_jsx(Shadow,{dx:0,dy:0,blur:10,color:"#ffffff"})})},`bright-star-${i}`);})}),_jsxs(Group,{children:[_jsx(Circle,{cx:width * 0.85,cy:height * 0.2,r:32,color:"#4c1d95",opacity:0.8,children:_jsx(Shadow,{dx:-2,dy:2,blur:8,color:"rgba(0,0,0,0.5)"})}),_jsx(Circle,{cx:width * 0.85 - 6,cy:height * 0.2 - 4,r:10,color:"#5b21b6",opacity:0.6}),_jsx(Circle,{cx:width * 0.85 + 4,cy:height * 0.2 + 6,r:6,color:"#6d28d9",opacity:0.5}),_jsx(Circle,{cx:width * 0.85 - 8,cy:height * 0.2 - 8,r:6,color:"#a855f7",opacity:0.3})]}),_jsxs(Group,{children:[_jsxs(Group,{children:[_jsx(Circle,{cx:width * 0.2,cy:height * 0.6,r:40,color:"#7c3aed",opacity:0.12,children:_jsx(Shadow,{dx:0,dy:0,blur:15,color:"#7c3aed"})}),_jsx(Circle,{cx:width * 0.24,cy:height * 0.58,r:28,color:"#a855f7",opacity:0.1})]}),_jsxs(Group,{children:[_jsx(Circle,{cx:width * 0.7,cy:height * 0.4,r:30,color:"#3b82f6",opacity:0.1,children:_jsx(Shadow,{dx:0,dy:0,blur:12,color:"#3b82f6"})}),_jsx(Circle,{cx:width * 0.72,cy:height * 0.38,r:20,color:"#60a5fa",opacity:0.08})]})]}),_jsx(Group,{children:Array.from({length:5},(_,i)=>{const positions = [{x:width * 0.15,y:height * 0.3},{x:width * 0.85,y:height * 0.5},{x:width * 0.3,y:height * 0.75},{x:width * 0.75,y:height * 0.2},{x:width * 0.5,y:height * 0.85}];const pos = positions[i];if(!pos)return null;const size = 3 + i % 3;return _jsxs(Group,{children:[_jsx(Circle,{cx:pos.x,cy:pos.y,r:size,color:"#6b7280",opacity:0.5,children:_jsx(Shadow,{dx:1,dy:1,blur:2,color:"rgba(0,0,0,0.3)"})}),_jsx(Circle,{cx:pos.x - size * 0.25,cy:pos.y - size * 0.25,r:size * 0.3,color:"#9ca3af",opacity:0.3})]},`asteroid-${i}`);})}),_jsx(Group,{children:Array.from({length:15},(_,i)=>{const x = width / 5 *(i % 5)+ i % 3 * 20;const y = height / 3 * Math.floor(i / 5)+ i % 4 * 30;const size = 0.5 + i % 2 * 0.2;return _jsx(Circle,{cx:x,cy:y,r:size,color:"#e5e7eb",opacity:0.25},`dust-${i}`);})})]}),children]});});
1
+ "use strict";import r from"react";import{View as c,Dimensions as o}from"react-native";import{Canvas as t,LinearGradient as i,Rect as l,Circle as e,Group as y,Shadow as a,vec as d}from"@shopify/react-native-skia";import{jsx as n,jsxs as h}from"react/jsx-runtime";const{width:x,height:f}=o.get("window");export const GameBackground=r.memo(({children:r})=>h(c,{style:{flex:1},children:[h(t,{style:{position:"absolute",top:0,left:0,right:0,bottom:0,width:x,height:f},children:[n(l,{x:0,y:0,width:x,height:f,children:n(i,{start:d(0,0),end:d(0,f),colors:["#0c0a1f","#1a1b3a","#2d1b69","#1e1b4b","#0c0a1f"]})}),n(y,{children:Array.from({length:40},(r,c)=>n(e,{cx:x/8*(c%8)+c%5*25,cy:f/5*Math.floor(c/8)+c%3*40,r:1+c%3*.4,color:"#ffffff",opacity:.6},"star-"+c))}),n(y,{children:Array.from({length:8},(r,c)=>{const o=[{x:.15*x,y:.2*f},{x:.8*x,y:.3*f},{x:.3*x,y:.5*f},{x:.7*x,y:.6*f},{x:.2*x,y:.7*f},{x:.85*x,y:.8*f},{x:.5*x,y:.15*f},{x:.6*x,y:.85*f}][c];if(!o)return null;const t=2.5+c%2*.5;return n(y,{children:n(e,{cx:o.x,cy:o.y,r:t,color:"#ffffff",opacity:.8,children:n(a,{dx:0,dy:0,blur:10,color:"#ffffff"})})},"bright-star-"+c)})}),h(y,{children:[n(e,{cx:.85*x,cy:.2*f,r:32,color:"#4c1d95",opacity:.8,children:n(a,{dx:-2,dy:2,blur:8,color:"rgba(0,0,0,0.5)"})}),n(e,{cx:.85*x-6,cy:.2*f-4,r:10,color:"#5b21b6",opacity:.6}),n(e,{cx:.85*x+4,cy:.2*f+6,r:6,color:"#6d28d9",opacity:.5}),n(e,{cx:.85*x-8,cy:.2*f-8,r:6,color:"#a855f7",opacity:.3})]}),h(y,{children:[h(y,{children:[n(e,{cx:.2*x,cy:.6*f,r:40,color:"#7c3aed",opacity:.12,children:n(a,{dx:0,dy:0,blur:15,color:"#7c3aed"})}),n(e,{cx:.24*x,cy:.58*f,r:28,color:"#a855f7",opacity:.1})]}),h(y,{children:[n(e,{cx:.7*x,cy:.4*f,r:30,color:"#3b82f6",opacity:.1,children:n(a,{dx:0,dy:0,blur:12,color:"#3b82f6"})}),n(e,{cx:.72*x,cy:.38*f,r:20,color:"#60a5fa",opacity:.08})]})]}),n(y,{children:Array.from({length:5},(r,c)=>{const o=[{x:.15*x,y:.3*f},{x:.85*x,y:.5*f},{x:.3*x,y:.75*f},{x:.75*x,y:.2*f},{x:.5*x,y:.85*f}][c];if(!o)return null;const t=3+c%3;return h(y,{children:[n(e,{cx:o.x,cy:o.y,r:t,color:"#6b7280",opacity:.5,children:n(a,{dx:1,dy:1,blur:2,color:"rgba(0,0,0,0.3)"})}),n(e,{cx:o.x-.25*t,cy:o.y-.25*t,r:.3*t,color:"#9ca3af",opacity:.3})]},"asteroid-"+c)})}),n(y,{children:Array.from({length:15},(r,c)=>n(e,{cx:x/5*(c%5)+c%3*20,cy:f/3*Math.floor(c/5)+c%4*30,r:.5+c%2*.2,color:"#e5e7eb",opacity:.25},"dust-"+c))})]}),r]}));
@@ -1 +1 @@
1
- "use strict";import React from 'react';import{View,Text,StyleSheet}from 'react-native';import{useSpaceFighterStore}from "../SpaceFighterStore.js";import{ScoreBoardContainer}from "../../../helpers/index.js";import{jsx as _jsx,jsxs as _jsxs}from "react/jsx-runtime";export const ScoreBoard = React.memo(({offset = 0})=>{const score = useSpaceFighterStore(state => state.score);const timeLeft = useSpaceFighterStore(state => state.timeLeft);const currentLives = useSpaceFighterStore(state => state.lives);const maxLives = 3;return _jsx(ScoreBoardContainer,{offset:offset,backgroundColor:"rgba(147,112,219,0.4)",borderColor:"rgba(139,92,246,0.3)",children:_jsxs(View,{style:styles.scoreBoard,children:[_jsxs(View,{style:styles.scoreItem,children:[_jsx(Text,{style:styles.scoreLabel,children:"Score"}),_jsx(Text,{style:styles.scoreValue,children:score})]}),_jsxs(View,{style:styles.scoreItem,children:[_jsx(Text,{style:styles.scoreLabel,children:"Time"}),_jsx(Text,{style:styles.timeValue,children:timeLeft})]}),_jsxs(View,{style:styles.scoreItem,children:[_jsx(Text,{style:styles.scoreLabel,children:"Lives"}),_jsx(View,{style:styles.livesContainer,children:Array.from({length:maxLives},(_,i)=> _jsx(Text,{style:[styles.lifeIcon,i < currentLives ? styles.lifeActive:styles.lifeInactive],children:i < currentLives ? '❤️':'🖤'},i))})]})]})});});const styles = StyleSheet.create({scoreBoard:{flexDirection:'row',justifyContent:'space-between',alignItems:'center'},scoreItem:{alignItems:'center',flex:1},scoreLabel:{fontSize:16,fontWeight:'bold',color:'#e2e8f0',marginBottom:6,textShadowColor:'rgba(0,0,0,0.5)',textShadowOffset:{width:1,height:1},textShadowRadius:2},scoreValue:{fontSize:25,fontWeight:'bold',color:'#fbbf24',textShadowColor:'rgba(0,0,0,0.5)',textShadowOffset:{width:1,height:1},textShadowRadius:2},timeValue:{fontSize:25,fontWeight:'bold',color:'#34d399',textShadowColor:'rgba(0,0,0,0.5)',textShadowOffset:{width:1,height:1},textShadowRadius:2},livesContainer:{flexDirection:'row',justifyContent:'center'},lifeIcon:{fontSize:22,marginHorizontal:2},lifeActive:{color:'#ef4444',textShadowColor:'rgba(0,0,0,0.5)',textShadowOffset:{width:1,height:1},textShadowRadius:2},lifeInactive:{color:'#374151',textShadowColor:'rgba(255,255,255,0.2)',textShadowOffset:{width:1,height:1},textShadowRadius:1}});
1
+ "use strict";import e from"react";import{View as t,Text as o,StyleSheet as r}from"react-native";import{useSpaceFighterStore as i}from"../SpaceFighterStore.js";import{ScoreBoardContainer as l}from"../../../helpers/index.js";import{jsx as a,jsxs as h}from"react/jsx-runtime";export const ScoreBoard=e.memo(({offset:e=0})=>{const r=i(e=>e.score),n=i(e=>e.timeLeft),d=i(e=>e.lives);return a(l,{offset:e,backgroundColor:"rgba(147, 112, 219, 0.4)",borderColor:"rgba(139, 92, 246, 0.3)",children:h(t,{style:s.scoreBoard,children:[h(t,{style:s.scoreItem,children:[a(o,{style:s.scoreLabel,children:"Score"}),a(o,{style:s.scoreValue,children:r})]}),h(t,{style:s.scoreItem,children:[a(o,{style:s.scoreLabel,children:"Time"}),a(o,{style:s.timeValue,children:n})]}),h(t,{style:s.scoreItem,children:[a(o,{style:s.scoreLabel,children:"Lives"}),a(t,{style:s.livesContainer,children:Array.from({length:3},(e,t)=>a(o,{style:[s.lifeIcon,d>t?s.lifeActive:s.lifeInactive],children:d>t?"\u2764\ufe0f":"\ud83d\udda4"},t))})]})]})})});const s=r.create({scoreBoard:{flexDirection:"row",justifyContent:"space-between",alignItems:"center"},scoreItem:{alignItems:"center",flex:1},scoreLabel:{fontSize:16,fontWeight:"bold",color:"#e2e8f0",marginBottom:6,textShadowColor:"rgba(0,0,0,0.5)",textShadowOffset:{width:1,height:1},textShadowRadius:2},scoreValue:{fontSize:25,fontWeight:"bold",color:"#fbbf24",textShadowColor:"rgba(0,0,0,0.5)",textShadowOffset:{width:1,height:1},textShadowRadius:2},timeValue:{fontSize:25,fontWeight:"bold",color:"#34d399",textShadowColor:"rgba(0,0,0,0.5)",textShadowOffset:{width:1,height:1},textShadowRadius:2},livesContainer:{flexDirection:"row",justifyContent:"center"},lifeIcon:{fontSize:22,marginHorizontal:2},lifeActive:{color:"#ef4444",textShadowColor:"rgba(0,0,0,0.5)",textShadowOffset:{width:1,height:1},textShadowRadius:2},lifeInactive:{color:"#374151",textShadowColor:"rgba(255,255,255,0.2)",textShadowOffset:{width:1,height:1},textShadowRadius:1}});
@@ -1 +1 @@
1
- "use strict";import React,{useMemo}from 'react';import{Canvas,Circle,Path,Skia,vec,Group,LinearGradient,RadialGradient}from '@shopify/react-native-skia';import{View}from 'react-native';import{jsx as _jsx,jsxs as _jsxs}from "react/jsx-runtime";export const Spacecraft3D = React.memo(({spacecraft,isControlled})=>{const size = spacecraft.size;const canvasSize = size * 2;const spacecraftPaths = useMemo(()=>{const centerX = canvasSize / 2;const centerY = canvasSize / 2;const bodyPath = Skia.Path.Make();const bodyWidth = size * 0.8;const bodyHeight = size * 1.2;bodyPath.addOval({x:centerX - bodyWidth / 2,y:centerY - bodyHeight / 2,width:bodyWidth,height:bodyHeight});const leftWing = Skia.Path.Make();const rightWing = Skia.Path.Make();const wingWidth = size * 0.6;const wingHeight = size * 0.3;leftWing.moveTo(centerX - size * 0.3,centerY);leftWing.lineTo(centerX - size * 0.3 - wingWidth,centerY - wingHeight / 2);leftWing.lineTo(centerX - size * 0.3 - wingWidth * 0.8,centerY + wingHeight / 2);leftWing.close();rightWing.moveTo(centerX + size * 0.3,centerY);rightWing.lineTo(centerX + size * 0.3 + wingWidth,centerY - wingHeight / 2);rightWing.lineTo(centerX + size * 0.3 + wingWidth * 0.8,centerY + wingHeight / 2);rightWing.close();const cockpitPath = Skia.Path.Make();const cockpitSize = size * 0.4;cockpitPath.addOval({x:centerX - cockpitSize / 2,y:centerY - size * 0.4 - cockpitSize / 2,width:cockpitSize,height:cockpitSize * 0.8});const leftFlame = Skia.Path.Make();const rightFlame = Skia.Path.Make();const flameLength = size * 0.4;leftFlame.moveTo(centerX - size * 0.15,centerY + size * 0.5);leftFlame.lineTo(centerX - size * 0.1,centerY + size * 0.5 + flameLength);leftFlame.lineTo(centerX - size * 0.2,centerY + size * 0.5 + flameLength);leftFlame.close();rightFlame.moveTo(centerX + size * 0.15,centerY + size * 0.5);rightFlame.lineTo(centerX + size * 0.2,centerY + size * 0.5 + flameLength);rightFlame.lineTo(centerX + size * 0.1,centerY + size * 0.5 + flameLength);rightFlame.close();return{bodyPath,leftWing,rightWing,cockpitPath,leftFlame,rightFlame,centerX,centerY};},[canvasSize,size]);const{bodyPath,leftWing,rightWing,cockpitPath,leftFlame,rightFlame,centerX,centerY}= spacecraftPaths;return _jsx(View,{style:{position:'absolute',left:spacecraft.x - canvasSize / 2,top:spacecraft.y - canvasSize / 2,width:canvasSize,height:canvasSize,transform:[{scale:isControlled ? 1.05:1}]},children:_jsx(Canvas,{style:{width:canvasSize,height:canvasSize},children:_jsxs(Group,{children:[_jsx(Path,{path:leftFlame,children:_jsx(LinearGradient,{start:vec(centerX - size * 0.15,centerY + size * 0.5),end:vec(centerX - size * 0.15,centerY + size * 0.9),colors:isControlled ? ['#ffffff','#ffff00','#ff6600','#ff0000']:['#ffaa00','#ff6600','#cc4400','#990000']})}),_jsx(Path,{path:rightFlame,children:_jsx(LinearGradient,{start:vec(centerX + size * 0.15,centerY + size * 0.5),end:vec(centerX + size * 0.15,centerY + size * 0.9),colors:isControlled ? ['#ffffff','#ffff00','#ff6600','#ff0000']:['#ffaa00','#ff6600','#cc4400','#990000']})}),_jsx(Path,{path:leftWing,children:_jsx(LinearGradient,{start:vec(centerX - size * 0.8,centerY - size * 0.2),end:vec(centerX - size * 0.2,centerY + size * 0.2),colors:isControlled ? ['#00ccff','#0099cc','#006699','#003366']:['#0099cc','#006699','#003366','#001133']})}),_jsx(Path,{path:rightWing,children:_jsx(LinearGradient,{start:vec(centerX + size * 0.2,centerY - size * 0.2),end:vec(centerX + size * 0.8,centerY + size * 0.2),colors:isControlled ? ['#00ccff','#0099cc','#006699','#003366']:['#0099cc','#006699','#003366','#001133']})}),_jsx(Path,{path:bodyPath,children:_jsx(LinearGradient,{start:vec(centerX - size * 0.4,centerY - size * 0.6),end:vec(centerX + size * 0.4,centerY + size * 0.6),colors:isControlled ? ['#00ffff','#00d4ff','#0099ff','#0066cc','#003399']:['#00d4ff','#0099ff','#0066cc','#003399','#001166']})}),_jsx(Path,{path:cockpitPath,children:_jsx(RadialGradient,{c:vec(centerX,centerY - size * 0.4),r:size * 0.3,colors:['rgba(255,255,255,0.8)','rgba(100,200,255,0.6)','rgba(0,100,200,0.8)']})}),_jsx(Circle,{cx:centerX - size * 0.15,cy:centerY + size * 0.5,r:size * 0.08,children:_jsx(RadialGradient,{c:vec(centerX - size * 0.15,centerY + size * 0.5),r:size * 0.08,colors:['#ffffff','#ffff00','#ff6600','#ff0000']})}),_jsx(Circle,{cx:centerX + size * 0.15,cy:centerY + size * 0.5,r:size * 0.08,children:_jsx(RadialGradient,{c:vec(centerX + size * 0.15,centerY + size * 0.5),r:size * 0.08,colors:['#ffffff','#ffff00','#ff6600','#ff0000']})}),_jsx(Circle,{cx:centerX - size * 0.8,cy:centerY,r:size * 0.06,color:isControlled ? '#00ff00':'#00cc00'}),_jsx(Circle,{cx:centerX + size * 0.8,cy:centerY,r:size * 0.06,color:isControlled ? '#ff0000':'#cc0000'}),_jsx(Circle,{cx:centerX,cy:centerY,r:size * 0.08,children:_jsx(RadialGradient,{c:vec(centerX,centerY),r:size * 0.08,colors:isControlled ? ['#ffffff','#00ffff','#0099ff']:['#cccccc','#0099ff','#006699']})}),_jsx(Circle,{cx:centerX - size * 0.1,cy:centerY - size * 0.45,r:size * 0.08,color:"rgba(255,255,255,0.8)"})]})})});});
1
+ "use strict";import f,{useMemo as c}from"react";import{Canvas as r,Circle as t,Path as e,Skia as o,vec as a,Group as i,LinearGradient as h,RadialGradient as l}from"@shopify/react-native-skia";import{View as n}from"react-native";import{jsx as s,jsxs as d}from"react/jsx-runtime";export const Spacecraft3D=f.memo(({spacecraft:f,isControlled:p})=>{const g=f.size,m=2*g,y=c(()=>{const f=m/2,c=m/2,r=o.Path.Make(),t=.8*g,e=1.2*g;r.addOval({x:f-t/2,y:c-e/2,width:t,height:e});const a=o.Path.Make(),i=o.Path.Make(),h=.6*g,l=.3*g;a.moveTo(f-.3*g,c),a.lineTo(f-.3*g-h,c-l/2),a.lineTo(f-.3*g-.8*h,c+l/2),a.close(),i.moveTo(f+.3*g,c),i.lineTo(f+.3*g+h,c-l/2),i.lineTo(f+.3*g+.8*h,c+l/2),i.close();const n=o.Path.Make(),s=.4*g;n.addOval({x:f-s/2,y:c-.4*g-s/2,width:s,height:.8*s});const d=o.Path.Make(),p=o.Path.Make(),y=.4*g;return d.moveTo(f-.15*g,c+.5*g),d.lineTo(f-.1*g,c+.5*g+y),d.lineTo(f-.2*g,c+.5*g+y),d.close(),p.moveTo(f+.15*g,c+.5*g),p.lineTo(f+.2*g,c+.5*g+y),p.lineTo(f+.1*g,c+.5*g+y),p.close(),{bodyPath:r,leftWing:a,rightWing:i,cockpitPath:n,leftFlame:d,rightFlame:p,centerX:f,centerY:c}},[m,g]),{bodyPath:x,leftWing:b,rightWing:u,cockpitPath:w,leftFlame:F,rightFlame:P,centerX:W,centerY:j}=y;return s(n,{style:{position:"absolute",left:f.x-m/2,top:f.y-m/2,width:m,height:m,transform:[{scale:p?1.05:1}]},children:s(r,{style:{width:m,height:m},children:d(i,{children:[s(e,{path:F,children:s(h,{start:a(W-.15*g,j+.5*g),end:a(W-.15*g,j+.9*g),colors:p?["#ffffff","#ffff00","#ff6600","#ff0000"]:["#ffaa00","#ff6600","#cc4400","#990000"]})}),s(e,{path:P,children:s(h,{start:a(W+.15*g,j+.5*g),end:a(W+.15*g,j+.9*g),colors:p?["#ffffff","#ffff00","#ff6600","#ff0000"]:["#ffaa00","#ff6600","#cc4400","#990000"]})}),s(e,{path:b,children:s(h,{start:a(W-.8*g,j-.2*g),end:a(W-.2*g,j+.2*g),colors:p?["#00ccff","#0099cc","#006699","#003366"]:["#0099cc","#006699","#003366","#001133"]})}),s(e,{path:u,children:s(h,{start:a(W+.2*g,j-.2*g),end:a(W+.8*g,j+.2*g),colors:p?["#00ccff","#0099cc","#006699","#003366"]:["#0099cc","#006699","#003366","#001133"]})}),s(e,{path:x,children:s(h,{start:a(W-.4*g,j-.6*g),end:a(W+.4*g,j+.6*g),colors:p?["#00ffff","#00d4ff","#0099ff","#0066cc","#003399"]:["#00d4ff","#0099ff","#0066cc","#003399","#001166"]})}),s(e,{path:w,children:s(l,{c:a(W,j-.4*g),r:.3*g,colors:["rgba(255,255,255,0.8)","rgba(100,200,255,0.6)","rgba(0,100,200,0.8)"]})}),s(t,{cx:W-.15*g,cy:j+.5*g,r:.08*g,children:s(l,{c:a(W-.15*g,j+.5*g),r:.08*g,colors:["#ffffff","#ffff00","#ff6600","#ff0000"]})}),s(t,{cx:W+.15*g,cy:j+.5*g,r:.08*g,children:s(l,{c:a(W+.15*g,j+.5*g),r:.08*g,colors:["#ffffff","#ffff00","#ff6600","#ff0000"]})}),s(t,{cx:W-.8*g,cy:j,r:.06*g,color:p?"#00ff00":"#00cc00"}),s(t,{cx:W+.8*g,cy:j,r:.06*g,color:p?"#ff0000":"#cc0000"}),s(t,{cx:W,cy:j,r:.08*g,children:s(l,{c:a(W,j),r:.08*g,colors:p?["#ffffff","#00ffff","#0099ff"]:["#cccccc","#0099ff","#006699"]})}),s(t,{cx:W-.1*g,cy:j-.45*g,r:.08*g,color:"rgba(255,255,255,0.8)"})]})})})});
@@ -1 +1 @@
1
- "use strict";import React,{useMemo}from 'react';import{View,StyleSheet}from 'react-native';import{COLORS}from "../SpaceFighterService.js";import{jsx as _jsx}from "react/jsx-runtime";export const SpacecraftPath = React.memo(({path})=>{if(path.length < 2)return null;const pathPoints = useMemo(()=>{return path.slice(1).map((point,index)=>({key:`path-${index}`,x:point.x - 2,y:point.y - 2,opacity:(index + 1)/ path.length * 0.5}));},[path]);return _jsx(View,{style:styles.container,children:pathPoints.map(point => _jsx(View,{style:[styles.pathPoint,{left:point.x,top:point.y,opacity:point.opacity}]},point.key))});});const styles = StyleSheet.create({container:{position:'absolute',top:0,left:0,right:0,bottom:0},pathPoint:{position:'absolute',width:4,height:4,borderRadius:2,backgroundColor:COLORS.SPACECRAFT}});
1
+ "use strict";import t,{useMemo as o}from"react";import{View as r,StyleSheet as e}from"react-native";import{COLORS as i}from"../SpaceFighterService.js";import{jsx as a}from"react/jsx-runtime";export const SpacecraftPath=t.memo(({path:t})=>{if(2>t.length)return null;const e=o(()=>t.slice(1).map((o,r)=>({key:"path-"+r,x:o.x-2,y:o.y-2,opacity:(r+1)/t.length*.5})),[t]);return a(r,{style:c.container,children:e.map(t=>a(r,{style:[c.pathPoint,{left:t.x,top:t.y,opacity:t.opacity}]},t.key))})});const c=e.create({container:{position:"absolute",top:0,left:0,right:0,bottom:0},pathPoint:{position:"absolute",width:4,height:4,borderRadius:2,backgroundColor:i.SPACECRAFT}});
@@ -1 +1 @@
1
- "use strict";export{ScoreBoard}from "./ScoreBoard.js";export{AsteroidComponent}from "./AsteroidComponent.js";export{Spacecraft3D}from "./Spacecraft3D.js";export{SpacecraftPath}from "./SpacecraftPath.js";export{GameArea}from "./GameArea.js";export{GameBackground}from "./GameBackground.js";
1
+ "use strict";export{ScoreBoard}from"./ScoreBoard.js";export{AsteroidComponent}from"./AsteroidComponent.js";export{Spacecraft3D}from"./Spacecraft3D.js";export{SpacecraftPath}from"./SpacecraftPath.js";export{GameArea}from"./GameArea.js";export{GameBackground}from"./GameBackground.js";
@@ -1 +1 @@
1
- "use strict";import React,{useEffect,useRef,useCallback,useMemo}from 'react';import{View,StyleSheet}from 'react-native';import{useSharedValue,withSpring,withTiming}from 'react-native-reanimated';import{playSound,GAME_SOUNDS}from "../../services/SoundsService.js";import{useWhackAMoleStore}from "./WhackAMoleStore.js";import{createWhackAMoleService,ANIMATION_CONFIG,GAME_CONFIG}from "./WhackAMoleService.js";import{ScoreBoard,GameGrid,GameBackground}from "./components/index.js";import{GameControlButton,GameOverModal}from "../../helpers/index.js";import{GameSettingsModal}from "../../helpers/GameSettingsModal.js";import{WHACK_A_MOLE_CONSTANTS}from "./WhackAMoleConstants.js";import{GAME_IDS,DEFAULT_GAME_SETTINGS}from "../../services/UtilsService.js";import{jsx as _jsx,jsxs as _jsxs}from "react/jsx-runtime";export const WhackAMole =({settings = DEFAULT_GAME_SETTINGS,onSettingsChange,onEndGame})=>{const{score,timeLeft,isPlaying,gameOver,holes,startGame,stopGame,resetGame,whackMole,decrementTime,activateHole,deactivateHole,setHoles}= useWhackAMoleStore();const gameReportedRef = useRef(false);const reportGameEnd = useCallback(status =>{if(onEndGame && !gameReportedRef.current){const currentState = useWhackAMoleStore.getState();onEndGame({status,score:currentState.score.toString()});gameReportedRef.current = true;}},[onEndGame]);const{difficulty = 'medium',enableSounds = true}= settings ||{};const gameDuration = GAME_CONFIG.GAME_DURATION;const gameConstants = React.useMemo(()=>({moleSpawnInterval:WHACK_A_MOLE_CONSTANTS.moleSpawnInterval[difficulty],moleVisibleDuration:WHACK_A_MOLE_CONSTANTS.moleVisibleDuration[difficulty],gridSize:WHACK_A_MOLE_CONSTANTS.gridSize[difficulty],pointsPerMole:WHACK_A_MOLE_CONSTANTS.pointsPerMole[difficulty]}),[difficulty]);const{moleSpawnInterval,moleVisibleDuration,gridSize,pointsPerMole}= gameConstants;const createHolesForGrid = useCallback(size =>{const totalHoles = size * size;return Array.from({length:totalHoles},(_,i)=>({id:i,isActive:false,position:{x:(i % size - 1)*(GAME_CONFIG.HOLE_SIZE + 20),y:Math.floor(i / size - 1)*(GAME_CONFIG.HOLE_SIZE + 20),z:0}}));},[]);const prevDifficultyRef = React.useRef(difficulty);useEffect(()=>{if(!isPlaying && !gameOver){const newHoles = createHolesForGrid(gridSize);setHoles(newHoles);}},[gridSize,isPlaying,gameOver,setHoles]);const maxHoles = 16;const moleAnimations = useRef(Array.from({length:maxHoles},()=> useSharedValue(0))).current;const hitAnimations = useRef(Array.from({length:maxHoles},()=> useSharedValue(0))).current;const gameService = useMemo(()=> createWhackAMoleService(moleAnimations,hitAnimations),[moleAnimations,hitAnimations]);const playHitSound = useCallback(()=>{playSound(GAME_SOUNDS.WHACK_A_MOLE.HIT,enableSounds);},[enableSounds]);const playMissSound = useCallback(()=>{playSound(GAME_SOUNDS.WHACK_A_MOLE.MISS,enableSounds);},[enableSounds]);const spawnMole = useCallback(()=>{const currentHoles = useWhackAMoleStore.getState().holes;const availableHoles = [];for(let i = 0;i < currentHoles.length;i++){if(currentHoles[i] && !currentHoles[i]?.isActive){availableHoles.push(i);}}gameService.spawnRandomMole(availableHoles,holeId =>{if(moleAnimations[holeId]){moleAnimations[holeId].value = withSpring(1,ANIMATION_CONFIG.MOLE_SPRING);activateHole(holeId);}},holeId =>{const currentState = useWhackAMoleStore.getState();if(holeId < currentState.holes.length && currentState.holes[holeId] && currentState.holes[holeId].isActive && moleAnimations[holeId]){playMissSound();moleAnimations[holeId].value = withSpring(0,ANIMATION_CONFIG.MOLE_SPRING);deactivateHole(holeId);}},moleVisibleDuration);},[playMissSound,activateHole,deactivateHole,moleVisibleDuration]);const handleStartGame = useCallback(()=>{gameReportedRef.current = false;startGame(gameDuration,gridSize);gameService.resetAnimations();gameService.startGameTimer(decrementTime);gameService.startMoleSpawning(spawnMole,moleSpawnInterval);},[gameDuration,gridSize,decrementTime,moleSpawnInterval,spawnMole]);const handleStopGame = useCallback(()=>{reportGameEnd('cancel');stopGame();gameService.cleanup();gameService.resetAnimations();},[stopGame,reportGameEnd]);const handleWhackMole = useCallback(holeId =>{const currentState = useWhackAMoleStore.getState();if(!currentState.isPlaying)return;if(holeId < 0 || holeId >= currentState.holes.length || !currentState.holes[holeId] || !currentState.holes[holeId].isActive)return;gameService.whackMole(holeId,()=>{playHitSound();whackMole(holeId,pointsPerMole);if(moleAnimations[holeId]){moleAnimations[holeId].value = withSpring(0,ANIMATION_CONFIG.MOLE_SPRING);}if(hitAnimations[holeId]){hitAnimations[holeId].value = withTiming(1,ANIMATION_CONFIG.HIT_TIMING,finished =>{if(finished && hitAnimations[holeId]){hitAnimations[holeId].value = withTiming(0,ANIMATION_CONFIG.HIT_TIMING);}});}});},[playHitSound,whackMole,pointsPerMole]);const handleResetGame = useCallback(()=>{gameService.cleanup();resetGame();gameService.resetAnimations();},[resetGame]);useEffect(()=>{if(gameOver && !gameReportedRef.current){reportGameEnd('win');}if(!gameOver){gameReportedRef.current = false;}},[gameOver,reportGameEnd]);useEffect(()=>{if(gameOver || !isPlaying){gameService.cleanup();}},[gameOver,isPlaying]);useEffect(()=>{return()=>{handleResetGame();};},[handleResetGame]);const gameControlButtonProps = useMemo(()=>({isPlaying,gameOver,onStartGame:handleStartGame,onStopGame:handleStopGame,startButtonText:"START WHACKING",stopButtonText:"STOP GAME",startButtonSubtext:"Whack moles to score!",stopButtonSubtext:"End current game",startButtonColor:"#10b981",stopButtonColor:"#dc2626",startButtonBorderColor:"#34d399",stopButtonBorderColor:"#f87171"}),[isPlaying,gameOver,handleStartGame,handleStopGame]);const gameOverModalProps = useMemo(()=>({isVisible:gameOver,score,onPlayAgain:handleResetGame,buttonText:"Whack Again!",primaryColor:"rgba(16,185,129,0.5)",borderColor:"rgba(16,185,129,0.5)",buttonColor:"#ffffff",buttonBorderColor:"#ffffff",buttonTextColor:"#10b981"}),[gameOver,score,handleResetGame]);React.useEffect(()=>{if(isPlaying && prevDifficultyRef.current !== difficulty){stopGame();gameService.cleanup();gameService.resetAnimations();requestAnimationFrame(()=>{startGame(gameDuration,gridSize);gameService.resetAnimations();gameService.startGameTimer(decrementTime);gameService.startMoleSpawning(spawnMole,moleSpawnInterval);});}prevDifficultyRef.current = difficulty;},[difficulty,isPlaying,gameDuration,gridSize,moleSpawnInterval,startGame,stopGame,decrementTime,spawnMole]);const offset = settings?.offset ?? 0;return _jsx(GameBackground,{offset:offset,children:_jsxs(View,{style:[styles.container,{paddingTop:offset}],children:[_jsx(ScoreBoard,{score:score,timeLeft:timeLeft,offset:offset}),_jsx(GameGrid,{holes:holes,moleAnimations:moleAnimations,hitAnimations:hitAnimations,onHolePress:handleWhackMole,gridSize:gridSize}),_jsx(GameControlButton,{...gameControlButtonProps}),_jsx(GameOverModal,{...gameOverModalProps}),_jsx(GameSettingsModal,{gameId:GAME_IDS.WHACK_A_MOLE,settings:settings || DEFAULT_GAME_SETTINGS,onSettingsChange:onSettingsChange})]})});};const styles = StyleSheet.create({container:{flex:1,backgroundColor:'transparent',paddingTop:0,paddingHorizontal:20,paddingBottom:0}});
1
+ "use strict";import t,{useEffect as o,useRef as e,useCallback as r,useMemo as n}from"react";import{View as s,StyleSheet as i}from"react-native";import{useSharedValue as a,withSpring as m,withTiming as l}from"react-native-reanimated";import{playSound as c,GAME_SOUNDS as f}from"../../services/SoundsService.js";import{useWhackAMoleStore as p}from"./WhackAMoleStore.js";import{createWhackAMoleService as d,ANIMATION_CONFIG as g,GAME_CONFIG as u}from"./WhackAMoleService.js";import{ScoreBoard as h,GameGrid as S,GameBackground as b}from"./components/index.js";import{GameControlButton as A,GameOverModal as v}from"../../helpers/index.js";import{GameSettingsModal as x}from"../../helpers/GameSettingsModal.js";import{WHACK_A_MOLE_CONSTANTS as C}from"./WhackAMoleConstants.js";import{GAME_IDS as B,DEFAULT_GAME_SETTINGS as j}from"../../services/UtilsService.js";import{jsx as y,jsxs as M}from"react/jsx-runtime";export const WhackAMole=({settings:i=j,onSettingsChange:G,onEndGame:k})=>{const{score:P,timeLeft:W,isPlaying:H,gameOver:z,holes:w,startGame:I,stopGame:E,resetGame:O,whackMole:V,decrementTime:D,activateHole:L,deactivateHole:q,setHoles:F}=p(),K=e(!1),N=r(t=>{if(k&&!K.current){const o=p.getState();k({status:t,score:o.score.toString()}),K.current=!0}},[k]),{difficulty:R="medium",enableSounds:U=!0}=i||{},J=u.GAME_DURATION,Q=t.useMemo(()=>({moleSpawnInterval:C.moleSpawnInterval[R],moleVisibleDuration:C.moleVisibleDuration[R],gridSize:C.gridSize[R],pointsPerMole:C.pointsPerMole[R]}),[R]),{moleSpawnInterval:X,moleVisibleDuration:Y,gridSize:Z,pointsPerMole:$}=Q,_=r(t=>Array.from({length:t*t},(o,e)=>({id:e,isActive:!1,position:{x:(e%t-1)*(u.HOLE_SIZE+20),y:Math.floor(e/t-1)*(u.HOLE_SIZE+20),z:0}})),[]),tt=t.useRef(R);o(()=>{if(!H&&!z){const t=_(Z);F(t)}},[Z,H,z,F]);const ot=e(Array.from({length:16},()=>a(0))).current,et=e(Array.from({length:16},()=>a(0))).current,rt=n(()=>d(ot,et),[ot,et]),nt=r(()=>{c(f.WHACK_A_MOLE.HIT,U)},[U]),st=r(()=>{c(f.WHACK_A_MOLE.MISS,U)},[U]),it=r(()=>{const t=p.getState().holes,o=[];for(let e=0;e<t.length;e++)t[e]&&!t[e]?.isActive&&o.push(e);rt.spawnRandomMole(o,t=>{ot[t]&&(ot[t].value=m(1,g.MOLE_SPRING),L(t))},t=>{const o=p.getState();t<o.holes.length&&o.holes[t]&&o.holes[t].isActive&&ot[t]&&(st(),ot[t].value=m(0,g.MOLE_SPRING),q(t))},Y)},[st,L,q,Y]),at=r(()=>{K.current=!1,I(J,Z),rt.resetAnimations(),rt.startGameTimer(D),rt.startMoleSpawning(it,X)},[J,Z,D,X,it]),mt=r(()=>{N("cancel"),E(),rt.cleanup(),rt.resetAnimations()},[E,N]),lt=r(t=>{const o=p.getState();o.isPlaying&&t>=0&&t<o.holes.length&&o.holes[t]&&o.holes[t].isActive&&rt.whackMole(t,()=>{nt(),V(t,$),ot[t]&&(ot[t].value=m(0,g.MOLE_SPRING)),et[t]&&(et[t].value=l(1,g.HIT_TIMING,o=>{o&&et[t]&&(et[t].value=l(0,g.HIT_TIMING))}))})},[nt,V,$]),ct=r(()=>{rt.cleanup(),O(),rt.resetAnimations()},[O]);o(()=>{z&&!K.current&&N("win"),z||(K.current=!1)},[z,N]),o(()=>{!z&&H||rt.cleanup()},[z,H]),o(()=>()=>{ct()},[ct]);const ft=n(()=>({isPlaying:H,gameOver:z,onStartGame:at,onStopGame:mt,startButtonText:"START WHACKING",stopButtonText:"STOP GAME",startButtonSubtext:"Whack moles to score!",stopButtonSubtext:"End current game",startButtonColor:"#10b981",stopButtonColor:"#dc2626",startButtonBorderColor:"#34d399",stopButtonBorderColor:"#f87171"}),[H,z,at,mt]),pt=n(()=>({isVisible:z,score:P,onPlayAgain:ct,buttonText:"Whack Again!",primaryColor:"rgba(16, 185, 129, 0.5)",borderColor:"rgba(16, 185, 129, 0.5)",buttonColor:"#ffffff",buttonBorderColor:"#ffffff",buttonTextColor:"#10b981"}),[z,P,ct]);t.useEffect(()=>{H&&tt.current!==R&&(E(),rt.cleanup(),rt.resetAnimations(),requestAnimationFrame(()=>{I(J,Z),rt.resetAnimations(),rt.startGameTimer(D),rt.startMoleSpawning(it,X)})),tt.current=R},[R,H,J,Z,X,I,E,D,it]);const dt=i?.offset??0;return y(b,{offset:dt,children:M(s,{style:[T.container,{paddingTop:dt}],children:[y(h,{score:P,timeLeft:W,offset:dt}),y(S,{holes:w,moleAnimations:ot,hitAnimations:et,onHolePress:lt,gridSize:Z}),y(A,{...ft}),y(v,{...pt}),y(x,{gameId:B.WHACK_A_MOLE,settings:i||j,onSettingsChange:G})]})})};const T=i.create({container:{flex:1,backgroundColor:"transparent",paddingTop:0,paddingHorizontal:20,paddingBottom:0}});
@@ -1 +1 @@
1
- "use strict";import{Dimensions}from 'react-native';const{width}= Dimensions.get('window');export const WHACK_A_MOLE_CONSTANTS ={moleSpawnInterval:{easy:2000,medium:1500,hard:1000},moleAppearDuration:{easy:2500,medium:2000,hard:1500},moleVisibleDuration:{easy:2500,medium:2000,hard:1500},gridSize:{easy:3,medium:3,hard:4},pointsPerMole:{easy:10,medium:15,hard:20}};export const WHACK_A_MOLE_GAME_CONFIG ={GRID_SIZE:3,HOLE_SIZE:width * 0.25,MOLE_APPEAR_DURATION:1500,MOLE_DISAPPEAR_DURATION:500,GAME_DURATION:120,INITIAL_SPAWN_DELAY:1000,MAX_SPAWN_INTERVAL:2000};export const WHACK_A_MOLE_ANIMATION_CONFIG ={MOLE_SPRING:{damping:15,stiffness:200},HOLE_SPRING:{damping:20,stiffness:300},HIT_TIMING:{duration:300}};export const WHACK_A_MOLE_COLORS ={BACKGROUND:'#2E7D32',SCORE_BOARD:'#1B5E20',HOLE:'#3E2723',HOLE_BORDER:'#5D4037',HOLE_SHADOW:'#2E2E2E',MOLE_SHADOW:'rgba(0,0,0,0.3)',SCORE:'#FFEB3B',SCORE_TEXT:'#FFD700',TIMER_TEXT:'#FF5722',UI:'#4CAF50',BUTTON_ACTIVE:'#66BB6A',BUTTON_INACTIVE:'#A5D6A7',TEXT_PRIMARY:'#FFFFFF',TEXT_SECONDARY:'#E8F5E8',WHITE:'#FFFFFF',START_BUTTON:'#4CAF50',HIT_EFFECT_OUTER:'#FFD700',HIT_EFFECT_INNER:'#FFA500',GAME_OVER_OVERLAY:'rgba(0,0,0,0.85)',BUTTON_BORDER:'#66BB6A'};export const WHACK_A_MOLE_THEME ={backgroundColor:'rgba(0,0,0,0.7)',headerBackgroundColor:'#10b981',headerTextColor:'#ffffff',sectionBackgroundColor:'rgba(16,185,129,0.15)',sectionTitleColor:'#10b981',buttonSelectedColor:'#10b981',buttonUnselectedColor:'rgba(255,255,255,0.2)',buttonSelectedTextColor:'#ffffff',buttonUnselectedTextColor:'rgba(255,255,255,0.7)',switchTrackColorFalse:'rgba(16,185,129,0.3)',switchTrackColorTrue:'#10b981',switchThumbColor:'#ffffff',infoTextColor:'rgba(255,255,255,0.9)'};export const WHACK_A_MOLE_DIFFICULTY_DESCRIPTIONS ={easy:'Moles appear slower and stay longer',medium:'Balanced mole speed and timing',hard:'Fast moles,quick reflexes needed!'};
1
+ "use strict";import{Dimensions as e}from"react-native";const{width:o}=e.get("window");export const WHACK_A_MOLE_CONSTANTS={moleSpawnInterval:{easy:2e3,medium:1500,hard:1e3},moleAppearDuration:{easy:2500,medium:2e3,hard:1500},moleVisibleDuration:{easy:2500,medium:2e3,hard:1500},gridSize:{easy:3,medium:3,hard:4},pointsPerMole:{easy:10,medium:15,hard:20}};export const WHACK_A_MOLE_GAME_CONFIG={GRID_SIZE:3,HOLE_SIZE:.25*o,MOLE_APPEAR_DURATION:1500,MOLE_DISAPPEAR_DURATION:500,GAME_DURATION:120,INITIAL_SPAWN_DELAY:1e3,MAX_SPAWN_INTERVAL:2e3};export const WHACK_A_MOLE_ANIMATION_CONFIG={MOLE_SPRING:{damping:15,stiffness:200},HOLE_SPRING:{damping:20,stiffness:300},HIT_TIMING:{duration:300}};export const WHACK_A_MOLE_COLORS={BACKGROUND:"#2E7D32",SCORE_BOARD:"#1B5E20",HOLE:"#3E2723",HOLE_BORDER:"#5D4037",HOLE_SHADOW:"#2E2E2E",MOLE_SHADOW:"rgba(0,0,0,0.3)",SCORE:"#FFEB3B",SCORE_TEXT:"#FFD700",TIMER_TEXT:"#FF5722",UI:"#4CAF50",BUTTON_ACTIVE:"#66BB6A",BUTTON_INACTIVE:"#A5D6A7",TEXT_PRIMARY:"#FFFFFF",TEXT_SECONDARY:"#E8F5E8",WHITE:"#FFFFFF",START_BUTTON:"#4CAF50",HIT_EFFECT_OUTER:"#FFD700",HIT_EFFECT_INNER:"#FFA500",GAME_OVER_OVERLAY:"rgba(0, 0, 0, 0.85)",BUTTON_BORDER:"#66BB6A"};export const WHACK_A_MOLE_THEME={backgroundColor:"rgba(0, 0, 0, 0.7)",headerBackgroundColor:"#10b981",headerTextColor:"#ffffff",sectionBackgroundColor:"rgba(16, 185, 129, 0.15)",sectionTitleColor:"#10b981",buttonSelectedColor:"#10b981",buttonUnselectedColor:"rgba(255, 255, 255, 0.2)",buttonSelectedTextColor:"#ffffff",buttonUnselectedTextColor:"rgba(255, 255, 255, 0.7)",switchTrackColorFalse:"rgba(16, 185, 129, 0.3)",switchTrackColorTrue:"#10b981",switchThumbColor:"#ffffff",infoTextColor:"rgba(255, 255, 255, 0.9)"};export const WHACK_A_MOLE_DIFFICULTY_DESCRIPTIONS={easy:"Moles appear slower and stay longer",medium:"Balanced mole speed and timing",hard:"Fast moles, quick reflexes needed!"};
@@ -1 +1 @@
1
- "use strict";import{WHACK_A_MOLE_GAME_CONFIG as GAME_CONFIG,WHACK_A_MOLE_ANIMATION_CONFIG as ANIMATION_CONFIG,WHACK_A_MOLE_COLORS as COLORS}from "./WhackAMoleConstants.js";export{GAME_CONFIG,ANIMATION_CONFIG,COLORS};export class WhackAMoleService{gameTimerRef = null;moleTimerRef = null;activeMoleTimers = new Map();constructor(moleAnimations,hitAnimations){this.moleAnimations = moleAnimations;this.hitAnimations = hitAnimations;}fastRandom(max){return Math.floor(Math.random()* max);}selectRandomHole(availableHoles){if(availableHoles.length === 0)return -1;if(availableHoles.length === 1)return availableHoles[0];const randomIndex = this.fastRandom(availableHoles.length);return availableHoles[randomIndex];}startGameTimer(onTick){this.clearGameTimer();this.gameTimerRef = setInterval(onTick,1000);}startMoleSpawning(spawnMole,customSpawnInterval){this.clearMoleTimer();const baseInterval = customSpawnInterval || GAME_CONFIG.MAX_SPAWN_INTERVAL;const minInterval = Math.max(500,baseInterval * 0.7);const maxInterval = baseInterval;const spawnLoop =()=>{spawnMole();const nextSpawnTime = Math.random()*(maxInterval - minInterval)+ minInterval;this.moleTimerRef = setTimeout(spawnLoop,nextSpawnTime);};this.moleTimerRef = setTimeout(spawnLoop,GAME_CONFIG.INITIAL_SPAWN_DELAY);}spawnRandomMole(availableHoles,onMoleSpawned,onMoleHidden,customVisibleDuration){if(availableHoles.length === 0)return;const randomHoleId = this.selectRandomHole(availableHoles);if(randomHoleId === -1)return;const existingTimer = this.activeMoleTimers.get(randomHoleId);if(existingTimer){clearTimeout(existingTimer);this.activeMoleTimers.delete(randomHoleId);}onMoleSpawned(randomHoleId);const visibleDuration = customVisibleDuration || GAME_CONFIG.MOLE_APPEAR_DURATION;const deactivationTimer = setTimeout(()=>{onMoleHidden(randomHoleId);this.activeMoleTimers.delete(randomHoleId);},visibleDuration);this.activeMoleTimers.set(randomHoleId,deactivationTimer);}whackMole(holeId,onWhacked){const timer = this.activeMoleTimers.get(holeId);if(timer){clearTimeout(timer);this.activeMoleTimers.delete(holeId);}onWhacked();}resetAnimations(){this.moleAnimations.forEach(anim =>{anim.value = 0;});this.hitAnimations.forEach(anim =>{anim.value = 0;});}cleanup(){this.clearGameTimer();this.clearMoleTimer();this.clearAllMoleHideTimeouts();}clearGameTimer(){if(this.gameTimerRef){clearInterval(this.gameTimerRef);this.gameTimerRef = null;}}clearMoleTimer(){if(this.moleTimerRef){clearTimeout(this.moleTimerRef);this.moleTimerRef = null;}}clearAllMoleHideTimeouts(){this.activeMoleTimers.forEach(timer => clearTimeout(timer));this.activeMoleTimers.clear();}}export const createWhackAMoleService =(moleAnimations,hitAnimations)=>{return new WhackAMoleService(moleAnimations,hitAnimations);};
1
+ "use strict";import{WHACK_A_MOLE_GAME_CONFIG as t,WHACK_A_MOLE_ANIMATION_CONFIG as e,WHACK_A_MOLE_COLORS as s}from"./WhackAMoleConstants.js";export{t as GAME_CONFIG,e as ANIMATION_CONFIG,s as COLORS};export class WhackAMoleService{gameTimerRef=null;moleTimerRef=null;activeMoleTimers=new Map;constructor(t,e){this.moleAnimations=t,this.hitAnimations=e}fastRandom(t){return Math.floor(Math.random()*t)}selectRandomHole(t){return 0===t.length?-1:1===t.length?t[0]:t[this.fastRandom(t.length)]}startGameTimer(t){this.clearGameTimer(),this.gameTimerRef=setInterval(t,1e3)}startMoleSpawning(e,s){this.clearMoleTimer();const i=s||t.MAX_SPAWN_INTERVAL,a=Math.max(500,.7*i),o=i,r=()=>{e();const t=Math.random()*(o-a)+a;this.moleTimerRef=setTimeout(r,t)};this.moleTimerRef=setTimeout(r,t.INITIAL_SPAWN_DELAY)}spawnRandomMole(e,s,i,a){if(0===e.length)return;const o=this.selectRandomHole(e);if(-1===o)return;const r=this.activeMoleTimers.get(o);r&&(clearTimeout(r),this.activeMoleTimers.delete(o)),s(o);const h=a||t.MOLE_APPEAR_DURATION,l=setTimeout(()=>{i(o),this.activeMoleTimers.delete(o)},h);this.activeMoleTimers.set(o,l)}whackMole(t,e){const s=this.activeMoleTimers.get(t);s&&(clearTimeout(s),this.activeMoleTimers.delete(t)),e()}resetAnimations(){this.moleAnimations.forEach(t=>{t.value=0}),this.hitAnimations.forEach(t=>{t.value=0})}cleanup(){this.clearGameTimer(),this.clearMoleTimer(),this.clearAllMoleHideTimeouts()}clearGameTimer(){this.gameTimerRef&&(clearInterval(this.gameTimerRef),this.gameTimerRef=null)}clearMoleTimer(){this.moleTimerRef&&(clearTimeout(this.moleTimerRef),this.moleTimerRef=null)}clearAllMoleHideTimeouts(){this.activeMoleTimers.forEach(t=>clearTimeout(t)),this.activeMoleTimers.clear()}}export const createWhackAMoleService=(t,e)=>new WhackAMoleService(t,e);
@@ -1 +1 @@
1
- "use strict";import{create}from 'zustand';import{subscribeWithSelector}from 'zustand/middleware';import{GAME_CONFIG}from "./WhackAMoleService.js";import{immerMiddleware}from "../../services/UtilsService.js";const createInitialHoles =(gridSize = GAME_CONFIG.GRID_SIZE)=>{const totalHoles = gridSize * gridSize;return Array.from({length:totalHoles},(_,i)=>({id:i,isActive:false,position:{x:(i % gridSize - 1)*(GAME_CONFIG.HOLE_SIZE + 20),y:Math.floor(i / gridSize - 1)*(GAME_CONFIG.HOLE_SIZE + 20),z:0}}));};export const useWhackAMoleStore = create()(subscribeWithSelector(immerMiddleware((set,get)=>({score:0,timeLeft:GAME_CONFIG.GAME_DURATION,isPlaying:false,gameOver:false,holes:createInitialHoles(),startGame:(_gameDuration,gridSize)=>{const duration = GAME_CONFIG.GAME_DURATION;const grid = gridSize || GAME_CONFIG.GRID_SIZE;set(draft =>{draft.score = 0;draft.timeLeft = duration;draft.isPlaying = true;draft.gameOver = false;draft.holes = createInitialHoles(grid);});},stopGame:()=>{set(draft =>{draft.score = 0;draft.timeLeft = GAME_CONFIG.GAME_DURATION;draft.isPlaying = false;draft.gameOver = false;});},resetGame:()=>{set(draft =>{draft.score = 0;draft.timeLeft = GAME_CONFIG.GAME_DURATION;draft.isPlaying = false;draft.gameOver = false;draft.holes = createInitialHoles();});},whackMole:(holeId,points = 1)=>{const{holes,isPlaying}= get();if(!isPlaying)return;if(holeId < 0 || holeId >= holes.length || !holes[holeId] || !holes[holeId].isActive)return;set(draft =>{draft.score = draft.score + points;if(draft.holes[holeId]){draft.holes[holeId].isActive = false;}});},updateScore:points =>{set(draft =>{draft.score = draft.score + points;});},decrementTime:()=>{const currentState = get();if(currentState.timeLeft <= 1){set(draft =>{draft.timeLeft = 0;draft.isPlaying = false;draft.gameOver = true;draft.holes.forEach(hole =>{hole.isActive = false;});});}else{set(draft =>{draft.timeLeft = currentState.timeLeft - 1;});}},setHoles:holes =>{set(draft =>{draft.holes = holes;});},activateHole:holeId =>{const state = get();if(holeId >= 0 && holeId < state.holes.length && !state.holes[holeId].isActive){set(draft =>{if(draft.holes[holeId]){draft.holes[holeId].isActive = true;}});}},deactivateHole:holeId =>{const state = get();if(holeId >= 0 && holeId < state.holes.length && state.holes[holeId].isActive){set(draft =>{if(draft.holes[holeId]){draft.holes[holeId].isActive = false;}});}},batchUpdateHoles:updates =>{const state = get();const hasChanges = updates.some(update => update.holeId >= 0 && update.holeId < state.holes.length && state.holes[update.holeId].isActive !== update.isActive);if(hasChanges){set(draft =>{updates.forEach(({holeId,isActive})=>{if(holeId >= 0 && holeId < draft.holes.length){if(draft.holes[holeId]){draft.holes[holeId].isActive = isActive;}}});});}}}))));export const useGameState =()=> useWhackAMoleStore(state =>({isPlaying:state.isPlaying,gameOver:state.gameOver}));export const useScore =()=> useWhackAMoleStore(state => state.score);export const useTimeLeft =()=> useWhackAMoleStore(state => state.timeLeft);export const useActiveHoles =()=> useWhackAMoleStore(state =>{const activeHoles = [];for(let i = 0;i < state.holes.length;i++){if(state.holes[i] && state.holes[i].isActive){activeHoles.push(state.holes[i]);}}return activeHoles;});export const useHoleById = holeId => useWhackAMoleStore(state => holeId >= 0 && holeId < state.holes.length ? state.holes[holeId]:undefined);
1
+ "use strict";import{create as e}from"zustand";import{subscribeWithSelector as t}from"zustand/middleware";import{GAME_CONFIG as o}from"./WhackAMoleService.js";import{immerMiddleware as s}from"../../services/UtilsService.js";const r=(e=o.GRID_SIZE)=>Array.from({length:e*e},(t,s)=>({id:s,isActive:!1,position:{x:(s%e-1)*(o.HOLE_SIZE+20),y:Math.floor(s/e-1)*(o.HOLE_SIZE+20),z:0}}));export const useWhackAMoleStore=e()(t(s((e,t)=>({score:0,timeLeft:o.GAME_DURATION,isPlaying:!1,gameOver:!1,holes:r(),startGame:(t,s)=>{const c=o.GAME_DURATION,a=s||o.GRID_SIZE;e(e=>{e.score=0,e.timeLeft=c,e.isPlaying=!0,e.gameOver=!1,e.holes=r(a)})},stopGame:()=>{e(e=>{e.score=0,e.timeLeft=o.GAME_DURATION,e.isPlaying=!1,e.gameOver=!1})},resetGame:()=>{e(e=>{e.score=0,e.timeLeft=o.GAME_DURATION,e.isPlaying=!1,e.gameOver=!1,e.holes=r()})},whackMole:(o,s=1)=>{const{holes:r,isPlaying:c}=t();c&&o>=0&&o<r.length&&r[o]&&r[o].isActive&&e(e=>{e.score=e.score+s,e.holes[o]&&(e.holes[o].isActive=!1)})},updateScore:t=>{e(e=>{e.score=e.score+t})},decrementTime:()=>{const o=t();o.timeLeft>1?e(e=>{e.timeLeft=o.timeLeft-1}):e(e=>{e.timeLeft=0,e.isPlaying=!1,e.gameOver=!0,e.holes.forEach(e=>{e.isActive=!1})})},setHoles:t=>{e(e=>{e.holes=t})},activateHole:o=>{const s=t();0>o||o>=s.holes.length||s.holes[o].isActive||e(e=>{e.holes[o]&&(e.holes[o].isActive=!0)})},deactivateHole:o=>{const s=t();o>=0&&o<s.holes.length&&s.holes[o].isActive&&e(e=>{e.holes[o]&&(e.holes[o].isActive=!1)})},batchUpdateHoles:o=>{const s=t();o.some(e=>e.holeId>=0&&e.holeId<s.holes.length&&s.holes[e.holeId].isActive!==e.isActive)&&e(e=>{o.forEach(({holeId:t,isActive:o})=>{t>=0&&t<e.holes.length&&e.holes[t]&&(e.holes[t].isActive=o)})})}}))));export const useGameState=()=>useWhackAMoleStore(e=>({isPlaying:e.isPlaying,gameOver:e.gameOver}));export const useScore=()=>useWhackAMoleStore(e=>e.score);export const useTimeLeft=()=>useWhackAMoleStore(e=>e.timeLeft);export const useActiveHoles=()=>useWhackAMoleStore(e=>{const t=[];for(let o=0;o<e.holes.length;o++)e.holes[o]&&e.holes[o].isActive&&t.push(e.holes[o]);return t});export const useHoleById=e=>useWhackAMoleStore(t=>e>=0&&e<t.holes.length?t.holes[e]:void 0);
@@ -1 +1 @@
1
- "use strict";import React from 'react';import{View,Dimensions}from 'react-native';import{Canvas,LinearGradient,Rect,Circle,Path,Skia,vec,Group,Shadow}from '@shopify/react-native-skia';import{jsx as _jsx,jsxs as _jsxs}from "react/jsx-runtime";const{width,height}= Dimensions.get('window');export const GameBackground = React.memo(({children,offset = 0})=>{const sunY = height * 0.15 + offset * 0.9;const cloud1Y = height * 0.24 + offset * 0.8;const cloud2Y = height * 0.27 + offset * 0.8;const cloud3Y = height * 0.19 + offset * 0.8;const buttonAreaHeight = offset > 0 ? 150:250;const grassStartY = height - buttonAreaHeight;const createGrassPath =(startX,segments = 8)=>{const path = Skia.Path.Make();const segmentWidth = width / segments;path.moveTo(startX,grassStartY);for(let i = 0;i < segments;i++){const x = startX + i * segmentWidth;const y = grassStartY + Math.sin(i * 0.5)* 8;const controlX = x + segmentWidth / 2;const controlY = y + Math.cos(i * 0.3)* 6;path.quadTo(controlX,controlY,x + segmentWidth,y);}path.lineTo(width,height);path.lineTo(startX,height);path.close();return path;};const grassPath = createGrassPath(0);return _jsxs(View,{style:{flex:1},children:[_jsxs(Canvas,{style:{position:'absolute',width,height},children:[_jsx(Rect,{x:0,y:0,width:width,height:grassStartY,children:_jsx(LinearGradient,{start:vec(0,0),end:vec(0,grassStartY),colors:['#87CEEB','#98D8E8','#B0E0E6']})}),_jsxs(Group,{children:[_jsxs(Circle,{cx:width * 0.8,cy:sunY,r:40,children:[_jsx(LinearGradient,{start:vec(-40,-40),end:vec(40,40),colors:['#FFFF99','#FFD700','#FFA500','#FF8C00']}),_jsx(Shadow,{dx:0,dy:0,blur:30,color:"#FFD700"})]}),_jsx(Circle,{cx:width * 0.8 - 8,cy:sunY - 8,r:15,children:_jsx(LinearGradient,{start:vec(-15,-15),end:vec(15,15),colors:['#FFFFFF','#FFFF99']})}),Array.from({length:16},(_,index)=>{const angle = 360 / 16 * index;const radian = angle * Math.PI / 180;const isLongRay = index % 2 === 0;const rayLength = isLongRay ? 25:15;const rayWidth = isLongRay ? 4:2;const startDistance = 45;const startX = width * 0.8 + Math.cos(radian)* startDistance;const startY = sunY + Math.sin(radian)* startDistance;const endX = width * 0.8 + Math.cos(radian)*(startDistance + rayLength);const endY = sunY + Math.sin(radian)*(startDistance + rayLength);const rayPath = Skia.Path.Make();rayPath.moveTo(startX,startY);rayPath.lineTo(endX,endY);return _jsx(Path,{path:rayPath,style:"stroke",strokeWidth:rayWidth,color:"#FFD700",opacity:0.7},index);}),_jsx(Circle,{cx:width * 0.8,cy:sunY,r:60,opacity:0.1,children:_jsx(LinearGradient,{start:vec(-60,-60),end:vec(60,60),colors:['#FFD700','transparent']})})]}),_jsxs(Group,{children:[_jsxs(Group,{children:[_jsx(Circle,{cx:width * 0.12,cy:cloud1Y,r:16,color:"#F0F8FF",opacity:0.35,children:_jsx(Shadow,{dx:1,dy:2,blur:12,color:"rgba(0,0,0,0.05)"})}),_jsx(Circle,{cx:width * 0.18,cy:cloud1Y -(height * 0.24 - height * 0.21),r:22,color:"#FFFFFF",opacity:0.45,children:_jsx(Shadow,{dx:1,dy:2,blur:12,color:"rgba(0,0,0,0.05)"})}),_jsx(Circle,{cx:width * 0.25,cy:cloud1Y -(height * 0.24 - height * 0.19),r:26,color:"#F8F8FF",opacity:0.55,children:_jsx(Shadow,{dx:2,dy:3,blur:12,color:"rgba(0,0,0,0.06)"})}),_jsx(Circle,{cx:width * 0.32,cy:cloud1Y -(height * 0.24 - height * 0.21),r:20,color:"#FFFFFF",opacity:0.50,children:_jsx(Shadow,{dx:1,dy:2,blur:12,color:"rgba(0,0,0,0.05)"})}),_jsx(Circle,{cx:width * 0.37,cy:cloud1Y,r:14,color:"#F0F8FF",opacity:0.40,children:_jsx(Shadow,{dx:1,dy:2,blur:12,color:"rgba(0,0,0,0.04)"})}),_jsx(Circle,{cx:width * 0.15,cy:cloud1Y +(height * 0.26 - height * 0.24),r:8,color:"#F8F8FF",opacity:0.25}),_jsx(Circle,{cx:width * 0.35,cy:cloud1Y -(height * 0.24 - height * 0.18),r:6,color:"#FFFFFF",opacity:0.30}),_jsx(Circle,{cx:width * 0.40,cy:cloud1Y -(height * 0.24 - height * 0.22),r:5,color:"#F0F8FF",opacity:0.20}),_jsx(Circle,{cx:width * 0.22,cy:cloud1Y -(height * 0.24 - height * 0.18),r:7,color:"#FFFFFF",opacity:0.35}),_jsx(Circle,{cx:width * 0.28,cy:cloud1Y -(height * 0.24 - height * 0.20),r:5,color:"#FFFFFF",opacity:0.25})]}),_jsxs(Group,{children:[_jsx(Circle,{cx:width * 0.62,cy:cloud2Y,r:15,color:"#F0F8FF",opacity:0.40,children:_jsx(Shadow,{dx:1,dy:2,blur:10,color:"rgba(0,0,0,0.04)"})}),_jsx(Circle,{cx:width * 0.69,cy:cloud2Y -(height * 0.27 - height * 0.24),r:19,color:"#FFFFFF",opacity:0.50,children:_jsx(Shadow,{dx:1,dy:2,blur:10,color:"rgba(0,0,0,0.05)"})}),_jsx(Circle,{cx:width * 0.76,cy:cloud2Y -(height * 0.27 - height * 0.26),r:13,color:"#F8F8FF",opacity:0.45,children:_jsx(Shadow,{dx:1,dy:2,blur:10,color:"rgba(0,0,0,0.04)"})}),_jsx(Circle,{cx:width * 0.81,cy:cloud2Y +(height * 0.28 - height * 0.27),r:9,color:"#F0F8FF",opacity:0.35,children:_jsx(Shadow,{dx:1,dy:1,blur:8,color:"rgba(0,0,0,0.03)"})}),_jsx(Circle,{cx:width * 0.65,cy:cloud2Y +(height * 0.29 - height * 0.27),r:6,color:"#F8F8FF",opacity:0.20}),_jsx(Circle,{cx:width * 0.78,cy:cloud2Y -(height * 0.27 - height * 0.23),r:4,color:"#FFFFFF",opacity:0.25}),_jsx(Circle,{cx:width * 0.67,cy:cloud2Y -(height * 0.27 - height * 0.23),r:5,color:"#FFFFFF",opacity:0.30})]}),_jsxs(Group,{children:[_jsx(Circle,{cx:width * 0.84,cy:cloud3Y,r:10,color:"#F0F8FF",opacity:0.35,children:_jsx(Shadow,{dx:0,dy:1,blur:6,color:"rgba(0,0,0,0.03)"})}),_jsx(Circle,{cx:width * 0.89,cy:cloud3Y -(height * 0.19 - height * 0.17),r:12,color:"#FFFFFF",opacity:0.40,children:_jsx(Shadow,{dx:0,dy:1,blur:6,color:"rgba(0,0,0,0.03)"})}),_jsx(Circle,{cx:width * 0.93,cy:cloud3Y,r:8,color:"#F8F8FF",opacity:0.30,children:_jsx(Shadow,{dx:0,dy:1,blur:6,color:"rgba(0,0,0,0.02)"})}),_jsx(Circle,{cx:width * 0.96,cy:cloud3Y -(height * 0.19 - height * 0.18),r:4,color:"#F0F8FF",opacity:0.15}),_jsx(Circle,{cx:width * 0.86,cy:cloud3Y +(height * 0.21 - height * 0.19),r:3,color:"#FFFFFF",opacity:0.20})]}),_jsxs(Group,{children:[_jsx(Circle,{cx:width * 0.45,cy:height * 0.15,r:8,color:"#F8F8FF",opacity:0.25,children:_jsx(Shadow,{dx:0,dy:1,blur:4,color:"rgba(0,0,0,0.02)"})}),_jsx(Circle,{cx:width * 0.50,cy:height * 0.13,r:10,color:"#FFFFFF",opacity:0.30,children:_jsx(Shadow,{dx:0,dy:1,blur:4,color:"rgba(0,0,0,0.02)"})}),_jsx(Circle,{cx:width * 0.54,cy:height * 0.15,r:6,color:"#F0F8FF",opacity:0.20,children:_jsx(Shadow,{dx:0,dy:1,blur:4,color:"rgba(0,0,0,0.01)"})})]})]}),_jsx(Rect,{x:0,y:grassStartY,width:width,height:buttonAreaHeight,children:_jsx(LinearGradient,{start:vec(0,grassStartY),end:vec(0,height),colors:['#8B4513','#A0522D','#654321']})}),_jsxs(Path,{path:grassPath,children:[_jsx(LinearGradient,{start:vec(0,grassStartY - 20),end:vec(0,grassStartY + 20),colors:['#32CD32','#228B22','#006400']}),_jsx(Shadow,{dx:0,dy:-2,blur:4,color:"rgba(0,0,0,0.2)"})]}),Array.from({length:50},(_,i)=>{const x = width / 50 * i + Math.random()* 15;const grassHeight = 12 + Math.random()* 18;const grassType = Math.random();const bladePath = Skia.Path.Make();bladePath.moveTo(x,grassStartY);if(grassType < 0.4){bladePath.quadTo(x + 1,grassStartY - grassHeight * 0.6,x + Math.random()* 2 - 1,grassStartY - grassHeight);return _jsx(Path,{path:bladePath,style:"stroke",strokeWidth:1.5,color:"#16a34a",opacity:0.8 + Math.random()* 0.2},`grass-${i}`);}else if(grassType < 0.7){bladePath.quadTo(x + 2,grassStartY - grassHeight * 0.4,x + 3,grassStartY - grassHeight);return _jsx(Path,{path:bladePath,style:"stroke",strokeWidth:2,color:"#15803d",opacity:0.7 + Math.random()* 0.3},`grass-${i}`);}else{const midHeight = grassHeight * 0.5;bladePath.quadTo(x + 1,grassStartY - midHeight,x + 2,grassStartY - grassHeight);return _jsxs(Group,{children:[_jsx(Path,{path:bladePath,style:"stroke",strokeWidth:2.5,color:"#166534",opacity:0.6 + Math.random()* 0.4}),Math.random()< 0.3 && _jsx(Circle,{cx:x + 2,cy:grassStartY - grassHeight,r:0.8,color:"#22c55e",opacity:0.8})]},`grass-group-${i}`);}}),Array.from({length:30},(_,i)=>{const x = Math.random()* width;const y = grassStartY - 10 + Math.random()* 20;const grassClusterHeight = 8 + Math.random()* 6;const clusterPath = Skia.Path.Make();clusterPath.moveTo(x,y);clusterPath.lineTo(x + Math.random()* 2 - 1,y - grassClusterHeight);clusterPath.moveTo(x + 2,y);clusterPath.lineTo(x + 2 + Math.random()* 2 - 1,y - grassClusterHeight * 0.8);clusterPath.moveTo(x + 4,y);clusterPath.lineTo(x + 4 + Math.random()* 2 - 1,y - grassClusterHeight * 0.6);return _jsx(Path,{path:clusterPath,style:"stroke",strokeWidth:1,color:"#22c55e",opacity:0.4},`cluster-${i}`);}),Array.from({length:15},(_,i)=>{const x = Math.random()* width;const y = grassStartY + 20 + Math.random()*(buttonAreaHeight - 40);const size = 2 + Math.random()* 3;return _jsx(Circle,{cx:x,cy:y,r:size,color:"#8B4513",opacity:0.6},i);})]}),children]});});
1
+ "use strict";import r from"react";import{View as c,Dimensions as o}from"react-native";import{Canvas as t,LinearGradient as F,Rect as l,Circle as a,Path as y,Skia as i,vec as e,Group as d,Shadow as h}from"@shopify/react-native-skia";import{jsx as n,jsxs as s}from"react/jsx-runtime";const{width:x,height:p}=o.get("window");export const GameBackground=r.memo(({children:r,offset:o=0})=>{const b=.15*p+.9*o,u=.24*p+.8*o,g=.27*p+.8*o,M=.19*p+.8*o,k=o>0?150:250,f=p-k,m=((r,c=8)=>{const o=i.Path.Make(),t=x/c;o.moveTo(r,f);for(let F=0;c>F;F++){const c=r+F*t,l=f+8*Math.sin(.5*F),a=c+t/2,y=l+6*Math.cos(.3*F);o.quadTo(a,y,c+t,l)}return o.lineTo(x,p),o.lineTo(r,p),o.close(),o})(0);return s(c,{style:{flex:1},children:[s(t,{style:{position:"absolute",width:x,height:p},children:[n(l,{x:0,y:0,width:x,height:f,children:n(F,{start:e(0,0),end:e(0,f),colors:["#87CEEB","#98D8E8","#B0E0E6"]})}),s(d,{children:[s(a,{cx:.8*x,cy:b,r:40,children:[n(F,{start:e(-40,-40),end:e(40,40),colors:["#FFFF99","#FFD700","#FFA500","#FF8C00"]}),n(h,{dx:0,dy:0,blur:30,color:"#FFD700"})]}),n(a,{cx:.8*x-8,cy:b-8,r:15,children:n(F,{start:e(-15,-15),end:e(15,15),colors:["#FFFFFF","#FFFF99"]})}),Array.from({length:16},(r,c)=>{const o=22.5*c*Math.PI/180,t=c%2==0,F=t?25:15,l=t?4:2,a=.8*x+45*Math.cos(o),e=b+45*Math.sin(o),d=.8*x+Math.cos(o)*(45+F),h=b+Math.sin(o)*(45+F),s=i.Path.Make();return s.moveTo(a,e),s.lineTo(d,h),n(y,{path:s,style:"stroke",strokeWidth:l,color:"#FFD700",opacity:.7},c)}),n(a,{cx:.8*x,cy:b,r:60,opacity:.1,children:n(F,{start:e(-60,-60),end:e(60,60),colors:["#FFD700","transparent"]})})]}),s(d,{children:[s(d,{children:[n(a,{cx:.12*x,cy:u,r:16,color:"#F0F8FF",opacity:.35,children:n(h,{dx:1,dy:2,blur:12,color:"rgba(0,0,0,0.05)"})}),n(a,{cx:.18*x,cy:u-(.24*p-.21*p),r:22,color:"#FFFFFF",opacity:.45,children:n(h,{dx:1,dy:2,blur:12,color:"rgba(0,0,0,0.05)"})}),n(a,{cx:.25*x,cy:u-(.24*p-.19*p),r:26,color:"#F8F8FF",opacity:.55,children:n(h,{dx:2,dy:3,blur:12,color:"rgba(0,0,0,0.06)"})}),n(a,{cx:.32*x,cy:u-(.24*p-.21*p),r:20,color:"#FFFFFF",opacity:.5,children:n(h,{dx:1,dy:2,blur:12,color:"rgba(0,0,0,0.05)"})}),n(a,{cx:.37*x,cy:u,r:14,color:"#F0F8FF",opacity:.4,children:n(h,{dx:1,dy:2,blur:12,color:"rgba(0,0,0,0.04)"})}),n(a,{cx:.15*x,cy:u+(.26*p-.24*p),r:8,color:"#F8F8FF",opacity:.25}),n(a,{cx:.35*x,cy:u-(.24*p-.18*p),r:6,color:"#FFFFFF",opacity:.3}),n(a,{cx:.4*x,cy:u-(.24*p-.22*p),r:5,color:"#F0F8FF",opacity:.2}),n(a,{cx:.22*x,cy:u-(.24*p-.18*p),r:7,color:"#FFFFFF",opacity:.35}),n(a,{cx:.28*x,cy:u-(.24*p-.2*p),r:5,color:"#FFFFFF",opacity:.25})]}),s(d,{children:[n(a,{cx:.62*x,cy:g,r:15,color:"#F0F8FF",opacity:.4,children:n(h,{dx:1,dy:2,blur:10,color:"rgba(0,0,0,0.04)"})}),n(a,{cx:.69*x,cy:g-(.27*p-.24*p),r:19,color:"#FFFFFF",opacity:.5,children:n(h,{dx:1,dy:2,blur:10,color:"rgba(0,0,0,0.05)"})}),n(a,{cx:.76*x,cy:g-(.27*p-.26*p),r:13,color:"#F8F8FF",opacity:.45,children:n(h,{dx:1,dy:2,blur:10,color:"rgba(0,0,0,0.04)"})}),n(a,{cx:.81*x,cy:g+(.28*p-.27*p),r:9,color:"#F0F8FF",opacity:.35,children:n(h,{dx:1,dy:1,blur:8,color:"rgba(0,0,0,0.03)"})}),n(a,{cx:.65*x,cy:g+(.29*p-.27*p),r:6,color:"#F8F8FF",opacity:.2}),n(a,{cx:.78*x,cy:g-(.27*p-.23*p),r:4,color:"#FFFFFF",opacity:.25}),n(a,{cx:.67*x,cy:g-(.27*p-.23*p),r:5,color:"#FFFFFF",opacity:.3})]}),s(d,{children:[n(a,{cx:.84*x,cy:M,r:10,color:"#F0F8FF",opacity:.35,children:n(h,{dx:0,dy:1,blur:6,color:"rgba(0,0,0,0.03)"})}),n(a,{cx:.89*x,cy:M-(.19*p-.17*p),r:12,color:"#FFFFFF",opacity:.4,children:n(h,{dx:0,dy:1,blur:6,color:"rgba(0,0,0,0.03)"})}),n(a,{cx:.93*x,cy:M,r:8,color:"#F8F8FF",opacity:.3,children:n(h,{dx:0,dy:1,blur:6,color:"rgba(0,0,0,0.02)"})}),n(a,{cx:.96*x,cy:M-(.19*p-.18*p),r:4,color:"#F0F8FF",opacity:.15}),n(a,{cx:.86*x,cy:M+(.21*p-.19*p),r:3,color:"#FFFFFF",opacity:.2})]}),s(d,{children:[n(a,{cx:.45*x,cy:.15*p,r:8,color:"#F8F8FF",opacity:.25,children:n(h,{dx:0,dy:1,blur:4,color:"rgba(0,0,0,0.02)"})}),n(a,{cx:.5*x,cy:.13*p,r:10,color:"#FFFFFF",opacity:.3,children:n(h,{dx:0,dy:1,blur:4,color:"rgba(0,0,0,0.02)"})}),n(a,{cx:.54*x,cy:.15*p,r:6,color:"#F0F8FF",opacity:.2,children:n(h,{dx:0,dy:1,blur:4,color:"rgba(0,0,0,0.01)"})})]})]}),n(l,{x:0,y:f,width:x,height:k,children:n(F,{start:e(0,f),end:e(0,p),colors:["#8B4513","#A0522D","#654321"]})}),s(y,{path:m,children:[n(F,{start:e(0,f-20),end:e(0,f+20),colors:["#32CD32","#228B22","#006400"]}),n(h,{dx:0,dy:-2,blur:4,color:"rgba(0,0,0,0.2)"})]}),Array.from({length:50},(r,c)=>{const o=x/50*c+15*Math.random(),t=12+18*Math.random(),F=Math.random(),l=i.Path.Make();if(l.moveTo(o,f),.4>F)return l.quadTo(o+1,f-.6*t,o+2*Math.random()-1,f-t),n(y,{path:l,style:"stroke",strokeWidth:1.5,color:"#16a34a",opacity:.8+.2*Math.random()},"grass-"+c);if(.7>F)return l.quadTo(o+2,f-.4*t,o+3,f-t),n(y,{path:l,style:"stroke",strokeWidth:2,color:"#15803d",opacity:.7+.3*Math.random()},"grass-"+c);{const r=.5*t;return l.quadTo(o+1,f-r,o+2,f-t),s(d,{children:[n(y,{path:l,style:"stroke",strokeWidth:2.5,color:"#166534",opacity:.6+.4*Math.random()}),.3>Math.random()&&n(a,{cx:o+2,cy:f-t,r:.8,color:"#22c55e",opacity:.8})]},"grass-group-"+c)}}),Array.from({length:30},(r,c)=>{const o=Math.random()*x,t=f-10+20*Math.random(),F=8+6*Math.random(),l=i.Path.Make();return l.moveTo(o,t),l.lineTo(o+2*Math.random()-1,t-F),l.moveTo(o+2,t),l.lineTo(o+2+2*Math.random()-1,t-.8*F),l.moveTo(o+4,t),l.lineTo(o+4+2*Math.random()-1,t-.6*F),n(y,{path:l,style:"stroke",strokeWidth:1,color:"#22c55e",opacity:.4},"cluster-"+c)}),Array.from({length:15},(r,c)=>{const o=Math.random()*x,t=f+20+Math.random()*(k-40),F=2+3*Math.random();return n(a,{cx:o,cy:t,r:F,color:"#8B4513",opacity:.6},c)})]}),r]})});
@@ -1 +1 @@
1
- "use strict";import React,{useMemo}from 'react';import{View,StyleSheet,Dimensions}from 'react-native';import{GAME_CONFIG}from "../WhackAMoleService.js";import{GameHole}from "./GameHole.js";import{jsx as _jsx}from "react/jsx-runtime";const MemoizedGameHole = React.memo(GameHole,(prevProps,nextProps)=>{return prevProps.hole.id === nextProps.hole.id && prevProps.hole.isActive === nextProps.hole.isActive && prevProps.moleAnimation === nextProps.moleAnimation && prevProps.hitAnimation === nextProps.hitAnimation && prevProps.onPress === nextProps.onPress && prevProps.holeSize === nextProps.holeSize;});export const GameGrid = React.memo(({holes,moleAnimations,hitAnimations,onHolePress,gridSize = 3})=>{const responsiveDimensions = useMemo(()=>{const{width:screenWidth}= Dimensions.get('window');const maxContainerWidth = Math.min(screenWidth * 0.9,600);const availableWidth = maxContainerWidth - gridSize * 8;const maxHoleSize = availableWidth / gridSize;const holeSize = Math.max(Math.min(maxHoleSize,GAME_CONFIG.HOLE_SIZE),60);return{containerWidth:maxContainerWidth,holeSize,gridWidth:gridSize *(holeSize + 8)};},[gridSize]);const gridStyle = useMemo(()=>({width:responsiveDimensions.gridWidth,maxWidth:responsiveDimensions.containerWidth}),[responsiveDimensions]);const paddingStyle = useMemo(()=> gridSize === 4 ? styles.smallPadding:styles.largePadding,[gridSize]);const gapStyle = useMemo(()=> gridSize === 4 ? styles.smallGap:styles.largeGap,[gridSize]);return _jsx(View,{style:[styles.gameArea,paddingStyle],children:_jsx(View,{style:[styles.gameGrid,gapStyle,gridStyle],children:holes.map((hole,index)=>{const moleAnimation = moleAnimations[index];const hitAnimation = hitAnimations[index];if(!moleAnimation || !hitAnimation){return null;}return _jsx(MemoizedGameHole,{hole:hole,moleAnimation:moleAnimation,hitAnimation:hitAnimation,onPress:onHolePress,holeSize:responsiveDimensions.holeSize},hole.id);})})});});const styles = StyleSheet.create({gameArea:{flex:1,justifyContent:'center',alignItems:'center'},smallPadding:{paddingHorizontal:16,paddingVertical:20},largePadding:{paddingVertical:20},gameGrid:{flexDirection:'row',flexWrap:'wrap',justifyContent:'center',alignItems:'center'},smallGap:{gap:4},largeGap:{gap:8}});
1
+ "use strict";import e,{useMemo as t}from"react";import{View as i,StyleSheet as r,Dimensions as n}from"react-native";import{GAME_CONFIG as a}from"../WhackAMoleService.js";import{GameHole as o}from"./GameHole.js";import{jsx as l}from"react/jsx-runtime";const s=e.memo(o,(e,t)=>e.hole.id===t.hole.id&&e.hole.isActive===t.hole.isActive&&e.moleAnimation===t.moleAnimation&&e.hitAnimation===t.hitAnimation&&e.onPress===t.onPress&&e.holeSize===t.holeSize);export const GameGrid=e.memo(({holes:e,moleAnimations:r,hitAnimations:o,onHolePress:c,gridSize:d=3})=>{const h=t(()=>{const{width:e}=n.get("window"),t=Math.min(.9*e,600),i=Math.max(Math.min((t-8*d)/d,a.HOLE_SIZE),60);return{containerWidth:t,holeSize:i,gridWidth:d*(i+8)}},[d]),g=t(()=>({width:h.gridWidth,maxWidth:h.containerWidth}),[h]),p=t(()=>4===d?m.smallPadding:m.largePadding,[d]),f=t(()=>4===d?m.smallGap:m.largeGap,[d]);return l(i,{style:[m.gameArea,p],children:l(i,{style:[m.gameGrid,f,g],children:e.map((e,t)=>{const i=r[t],n=o[t];return i&&n?l(s,{hole:e,moleAnimation:i,hitAnimation:n,onPress:c,holeSize:h.holeSize},e.id):null})})})});const m=r.create({gameArea:{flex:1,justifyContent:"center",alignItems:"center"},smallPadding:{paddingHorizontal:16,paddingVertical:20},largePadding:{paddingVertical:20},gameGrid:{flexDirection:"row",flexWrap:"wrap",justifyContent:"center",alignItems:"center"},smallGap:{gap:4},largeGap:{gap:8}});
@@ -1 +1 @@
1
- "use strict";import React,{useCallback,useMemo}from 'react';import{View,TouchableOpacity,StyleSheet}from 'react-native';import Animated,{useSharedValue,useAnimatedStyle,withSpring,withSequence,withTiming,interpolate,Extrapolation}from 'react-native-reanimated';import{Canvas as SkiaCanvas,Circle,Group}from '@shopify/react-native-skia';import{GAME_CONFIG,COLORS}from "../WhackAMoleService.js";import{MoleCharacter}from "./MoleCharacter.js";import{jsx as _jsx,jsxs as _jsxs}from "react/jsx-runtime";export const GameHole = React.memo(({hole,moleAnimation,hitAnimation,onPress,holeSize = GAME_CONFIG.HOLE_SIZE})=>{const whackScale = useSharedValue(1);const whackRotation = useSharedValue(0);const whackBounce = useSharedValue(0);const animationConstants = useMemo(()=>({translateYRange:[holeSize * 0.3,holeSize * 0.1,-holeSize * 0.05],scaleRange:[0.3,0.8,1],maxTranslateY:-holeSize * 0.1}),[holeSize]);const moleStyle = useAnimatedStyle(()=>{const translateY = interpolate(moleAnimation.value,[0,0.3,1],animationConstants.translateYRange,Extrapolation.CLAMP);const emergenceScale = interpolate(moleAnimation.value,[0,0.4,1],animationConstants.scaleRange,Extrapolation.CLAMP);const bounceY = whackBounce.value * -8;const finalTranslateY = Math.max(translateY + bounceY,animationConstants.maxTranslateY);return{transform:[{translateY:finalTranslateY},{scale:whackScale.value * emergenceScale},{rotate:`${whackRotation.value}deg`}],opacity:moleAnimation.value};},[animationConstants]);const hitStyle = useAnimatedStyle(()=>{const scale = 1 + hitAnimation.value * 0.5;return{transform:[{scale}],opacity:hitAnimation.value};});const holeContainerStyle = useMemo(()=> [styles.holeContainer,{width:holeSize,height:holeSize}],[holeSize]);const holeStyle = useMemo(()=> [styles.hole,{width:holeSize * 0.8,height:holeSize * 0.8}],[holeSize]);const hitEffectContainerStyle = useMemo(()=> [styles.hitEffectContainer,{width:holeSize,height:holeSize}],[holeSize]);const moleContainerStyle = useMemo(()=> [styles.moleContainer,{bottom:holeSize * 0.1,zIndex:10}],[holeSize]);const handlePress = useCallback(()=>{if(hole.isActive || moleAnimation.value > 0){whackScale.value = withSequence(withSpring(1.3,{damping:8,stiffness:400}),withSpring(0.8,{damping:10,stiffness:300}),withTiming(0,{duration:400}));whackRotation.value = withSequence(withSpring(15,{damping:10,stiffness:300}),withSpring(-8,{damping:12,stiffness:250}),withTiming(0,{duration:300}));whackBounce.value = withSequence(withSpring(1,{damping:8,stiffness:400}),withSpring(0,{damping:12,stiffness:300}));setTimeout(()=>{onPress(hole.id);},150);setTimeout(()=>{whackScale.value = 1;whackRotation.value = 0;whackBounce.value = 0;},800);}else{onPress(hole.id);}},[hole.id,hole.isActive,onPress,moleAnimation]);return _jsxs(TouchableOpacity,{style:holeContainerStyle,onPress:handlePress,activeOpacity:0.8,children:[_jsx(View,{style:holeStyle}),_jsx(Animated.View,{style:[hitEffectContainerStyle,hitStyle],children:_jsx(SkiaCanvas,{style:{width:holeSize,height:holeSize},children:_jsxs(Group,{children:[_jsx(Circle,{cx:holeSize / 2,cy:holeSize / 2,r:holeSize * 0.25,color:COLORS.HIT_EFFECT_OUTER}),_jsx(Circle,{cx:holeSize / 2,cy:holeSize / 2,r:holeSize * 0.17,color:COLORS.HIT_EFFECT_INNER})]})})}),hole.isActive && _jsx(Animated.View,{style:[moleContainerStyle,moleStyle],children:_jsx(MoleCharacter,{size:holeSize * 0.6})})]});});const styles = StyleSheet.create({holeContainer:{justifyContent:'center',alignItems:'center',position:'relative'},hole:{backgroundColor:'#92400e',borderWidth:4,borderColor:'#a16207',borderRadius:9999,shadowColor:'#000',shadowOffset:{width:0,height:2},shadowOpacity:0.25,shadowRadius:3.84,elevation:5},moleContainer:{position:'absolute',justifyContent:'center',alignItems:'center',zIndex:10,elevation:10},hitEffectContainer:{position:'absolute',justifyContent:'center',alignItems:'center',pointerEvents:'none',zIndex:1,elevation:1}});
1
+ "use strict";import e,{useCallback as t,useMemo as i}from"react";import{View as o,TouchableOpacity as n,StyleSheet as s}from"react-native";import r,{useSharedValue as a,useAnimatedStyle as c,withSpring as l,withSequence as m,withTiming as h,interpolate as d,Extrapolation as f}from"react-native-reanimated";import{Canvas as p,Circle as g,Group as u}from"@shopify/react-native-skia";import{GAME_CONFIG as y,COLORS as v}from"../WhackAMoleService.js";import{MoleCharacter as C}from"./MoleCharacter.js";import{jsx as x,jsxs as w}from"react/jsx-runtime";export const GameHole=e.memo(({hole:e,moleAnimation:s,hitAnimation:b,onPress:I,holeSize:z=y.HOLE_SIZE})=>{const R=a(1),k=a(0),A=a(0),M=i(()=>({translateYRange:[.3*z,.1*z,.05*-z],scaleRange:[.3,.8,1],maxTranslateY:.1*-z}),[z]),O=c(()=>{const e=d(s.value,[0,.3,1],M.translateYRange,f.CLAMP),t=d(s.value,[0,.4,1],M.scaleRange,f.CLAMP),i=-8*A.value;return{transform:[{translateY:Math.max(e+i,M.maxTranslateY)},{scale:R.value*t},{rotate:k.value+"deg"}],opacity:s.value}},[M]),T=c(()=>({transform:[{scale:1+.5*b.value}],opacity:b.value})),Y=i(()=>[j.holeContainer,{width:z,height:z}],[z]),E=i(()=>[j.hole,{width:.8*z,height:.8*z}],[z]),P=i(()=>[j.hitEffectContainer,{width:z,height:z}],[z]),S=i(()=>[j.moleContainer,{bottom:.1*z,zIndex:10}],[z]),W=t(()=>{e.isActive||s.value>0?(R.value=m(l(1.3,{damping:8,stiffness:400}),l(.8,{damping:10,stiffness:300}),h(0,{duration:400})),k.value=m(l(15,{damping:10,stiffness:300}),l(-8,{damping:12,stiffness:250}),h(0,{duration:300})),A.value=m(l(1,{damping:8,stiffness:400}),l(0,{damping:12,stiffness:300})),setTimeout(()=>{I(e.id)},150),setTimeout(()=>{R.value=1,k.value=0,A.value=0},800)):I(e.id)},[e.id,e.isActive,I,s]);return w(n,{style:Y,onPress:W,activeOpacity:.8,children:[x(o,{style:E}),x(r.View,{style:[P,T],children:x(p,{style:{width:z,height:z},children:w(u,{children:[x(g,{cx:z/2,cy:z/2,r:.25*z,color:v.HIT_EFFECT_OUTER}),x(g,{cx:z/2,cy:z/2,r:.17*z,color:v.HIT_EFFECT_INNER})]})})}),e.isActive&&x(r.View,{style:[S,O],children:x(C,{size:.6*z})})]})});const j=s.create({holeContainer:{justifyContent:"center",alignItems:"center",position:"relative"},hole:{backgroundColor:"#92400e",borderWidth:4,borderColor:"#a16207",borderRadius:9999,shadowColor:"#000",shadowOffset:{width:0,height:2},shadowOpacity:.25,shadowRadius:3.84,elevation:5},moleContainer:{position:"absolute",justifyContent:"center",alignItems:"center",zIndex:10,elevation:10},hitEffectContainer:{position:"absolute",justifyContent:"center",alignItems:"center",pointerEvents:"none",zIndex:1,elevation:1}});
@@ -1 +1 @@
1
- "use strict";import React from 'react';import{View,StyleSheet}from 'react-native';import{jsx as _jsx,jsxs as _jsxs}from "react/jsx-runtime";export const MoleCharacter = React.memo(({size})=>{const moleSize = size * 0.8;const styles = createStyles(moleSize);return _jsx(View,{style:[styles.container,{width:size,height:size}],children:_jsxs(View,{style:styles.body,children:[_jsxs(View,{style:styles.head,children:[_jsx(View,{style:styles.leftEar}),_jsx(View,{style:styles.rightEar}),_jsx(View,{style:styles.leftInnerEar}),_jsx(View,{style:styles.rightInnerEar}),_jsx(View,{style:styles.leftEye,children:_jsx(View,{style:styles.eyeHighlight})}),_jsx(View,{style:styles.rightEye,children:_jsx(View,{style:styles.eyeHighlight})}),_jsx(View,{style:styles.nose}),_jsxs(View,{style:styles.mouth,children:[_jsx(View,{style:styles.leftMouth}),_jsx(View,{style:styles.rightMouth})]})]}),_jsx(View,{style:styles.leftWhisker1}),_jsx(View,{style:styles.leftWhisker2}),_jsx(View,{style:styles.rightWhisker1}),_jsx(View,{style:styles.rightWhisker2})]})});});const createStyles = moleSize => StyleSheet.create({container:{justifyContent:'center',alignItems:'center'},body:{width:moleSize,height:moleSize * 0.9,backgroundColor:'#FF8C42',borderRadius:moleSize * 0.4,justifyContent:'center',alignItems:'center',shadowColor:'#000',shadowOffset:{width:0,height:2},shadowOpacity:0.3,shadowRadius:4,elevation:5},head:{width:moleSize * 0.8,height:moleSize * 0.7,backgroundColor:'#FFA366',borderRadius:moleSize * 0.35,position:'relative',justifyContent:'center',alignItems:'center',marginTop:-moleSize * 0.1},leftEar:{position:'absolute',top:-moleSize * 0.15,left:moleSize * 0.15,width:moleSize * 0.25,height:moleSize * 0.25,backgroundColor:'#FF8C42',borderRadius:moleSize * 0.125,transform:[{rotate:'-30deg'}]},rightEar:{position:'absolute',top:-moleSize * 0.15,right:moleSize * 0.15,width:moleSize * 0.25,height:moleSize * 0.25,backgroundColor:'#FF8C42',borderRadius:moleSize * 0.125,transform:[{rotate:'30deg'}]},leftInnerEar:{position:'absolute',top:-moleSize * 0.12,left:moleSize * 0.18,width:moleSize * 0.15,height:moleSize * 0.15,backgroundColor:'#FF6B1A',borderRadius:moleSize * 0.075,transform:[{rotate:'-30deg'}]},rightInnerEar:{position:'absolute',top:-moleSize * 0.12,right:moleSize * 0.18,width:moleSize * 0.15,height:moleSize * 0.15,backgroundColor:'#FF6B1A',borderRadius:moleSize * 0.075,transform:[{rotate:'30deg'}]},leftEye:{position:'absolute',top:moleSize * 0.15,left:moleSize * 0.2,width:moleSize * 0.12,height:moleSize * 0.15,backgroundColor:'#000000',borderRadius:moleSize * 0.075,justifyContent:'center',alignItems:'center'},rightEye:{position:'absolute',top:moleSize * 0.15,right:moleSize * 0.2,width:moleSize * 0.12,height:moleSize * 0.15,backgroundColor:'#000000',borderRadius:moleSize * 0.075,justifyContent:'center',alignItems:'center'},eyeHighlight:{width:moleSize * 0.04,height:moleSize * 0.06,backgroundColor:'#FFFFFF',borderRadius:moleSize * 0.02},nose:{position:'absolute',top:moleSize * 0.28,width:moleSize * 0.08,height:moleSize * 0.06,backgroundColor:'#FF1493',borderRadius:moleSize * 0.04},mouth:{position:'absolute',top:moleSize * 0.35,width:moleSize * 0.2,height:moleSize * 0.1,justifyContent:'center',alignItems:'center'},leftMouth:{position:'absolute',left:0,width:moleSize * 0.08,height:2,backgroundColor:'#000000',borderRadius:1,transform:[{rotate:'20deg'}]},rightMouth:{position:'absolute',right:0,width:moleSize * 0.08,height:2,backgroundColor:'#000000',borderRadius:1,transform:[{rotate:'-20deg'}]},leftWhisker1:{position:'absolute',top:moleSize * 0.35,left:-moleSize * 0.15,width:moleSize * 0.2,height:1,backgroundColor:'#000000'},leftWhisker2:{position:'absolute',top:moleSize * 0.4,left:-moleSize * 0.15,width:moleSize * 0.18,height:1,backgroundColor:'#000000'},rightWhisker1:{position:'absolute',top:moleSize * 0.35,right:-moleSize * 0.15,width:moleSize * 0.2,height:1,backgroundColor:'#000000'},rightWhisker2:{position:'absolute',top:moleSize * 0.4,right:-moleSize * 0.15,width:moleSize * 0.18,height:1,backgroundColor:'#000000'}});
1
+ "use strict";import t from"react";import{View as e,StyleSheet as o}from"react-native";import{jsx as r,jsxs as i}from"react/jsx-runtime";export const MoleCharacter=t.memo(({size:t})=>{const o=s(.8*t);return r(e,{style:[o.container,{width:t,height:t}],children:i(e,{style:o.body,children:[i(e,{style:o.head,children:[r(e,{style:o.leftEar}),r(e,{style:o.rightEar}),r(e,{style:o.leftInnerEar}),r(e,{style:o.rightInnerEar}),r(e,{style:o.leftEye,children:r(e,{style:o.eyeHighlight})}),r(e,{style:o.rightEye,children:r(e,{style:o.eyeHighlight})}),r(e,{style:o.nose}),i(e,{style:o.mouth,children:[r(e,{style:o.leftMouth}),r(e,{style:o.rightMouth})]})]}),r(e,{style:o.leftWhisker1}),r(e,{style:o.leftWhisker2}),r(e,{style:o.rightWhisker1}),r(e,{style:o.rightWhisker2})]})})});const s=t=>o.create({container:{justifyContent:"center",alignItems:"center"},body:{width:t,height:.9*t,backgroundColor:"#FF8C42",borderRadius:.4*t,justifyContent:"center",alignItems:"center",shadowColor:"#000",shadowOffset:{width:0,height:2},shadowOpacity:.3,shadowRadius:4,elevation:5},head:{width:.8*t,height:.7*t,backgroundColor:"#FFA366",borderRadius:.35*t,position:"relative",justifyContent:"center",alignItems:"center",marginTop:.1*-t},leftEar:{position:"absolute",top:.15*-t,left:.15*t,width:.25*t,height:.25*t,backgroundColor:"#FF8C42",borderRadius:.125*t,transform:[{rotate:"-30deg"}]},rightEar:{position:"absolute",top:.15*-t,right:.15*t,width:.25*t,height:.25*t,backgroundColor:"#FF8C42",borderRadius:.125*t,transform:[{rotate:"30deg"}]},leftInnerEar:{position:"absolute",top:.12*-t,left:.18*t,width:.15*t,height:.15*t,backgroundColor:"#FF6B1A",borderRadius:.075*t,transform:[{rotate:"-30deg"}]},rightInnerEar:{position:"absolute",top:.12*-t,right:.18*t,width:.15*t,height:.15*t,backgroundColor:"#FF6B1A",borderRadius:.075*t,transform:[{rotate:"30deg"}]},leftEye:{position:"absolute",top:.15*t,left:.2*t,width:.12*t,height:.15*t,backgroundColor:"#000000",borderRadius:.075*t,justifyContent:"center",alignItems:"center"},rightEye:{position:"absolute",top:.15*t,right:.2*t,width:.12*t,height:.15*t,backgroundColor:"#000000",borderRadius:.075*t,justifyContent:"center",alignItems:"center"},eyeHighlight:{width:.04*t,height:.06*t,backgroundColor:"#FFFFFF",borderRadius:.02*t},nose:{position:"absolute",top:.28*t,width:.08*t,height:.06*t,backgroundColor:"#FF1493",borderRadius:.04*t},mouth:{position:"absolute",top:.35*t,width:.2*t,height:.1*t,justifyContent:"center",alignItems:"center"},leftMouth:{position:"absolute",left:0,width:.08*t,height:2,backgroundColor:"#000000",borderRadius:1,transform:[{rotate:"20deg"}]},rightMouth:{position:"absolute",right:0,width:.08*t,height:2,backgroundColor:"#000000",borderRadius:1,transform:[{rotate:"-20deg"}]},leftWhisker1:{position:"absolute",top:.35*t,left:.15*-t,width:.2*t,height:1,backgroundColor:"#000000"},leftWhisker2:{position:"absolute",top:.4*t,left:.15*-t,width:.18*t,height:1,backgroundColor:"#000000"},rightWhisker1:{position:"absolute",top:.35*t,right:.15*-t,width:.2*t,height:1,backgroundColor:"#000000"},rightWhisker2:{position:"absolute",top:.4*t,right:.15*-t,width:.18*t,height:1,backgroundColor:"#000000"}});
@@ -1 +1 @@
1
- "use strict";import React from 'react';import{View,Text,StyleSheet}from 'react-native';import{ScoreBoardContainer}from "../../../helpers/index.js";import{jsx as _jsx,jsxs as _jsxs}from "react/jsx-runtime";export const ScoreBoard = React.memo(({score,timeLeft,offset = 0})=>{const formatTime = seconds =>{const mins = Math.floor(seconds / 60);const secs = seconds % 60;return `${mins.toString().padStart(2,'0')}:${secs.toString().padStart(2,'0')}`;};return _jsx(ScoreBoardContainer,{offset:offset,backgroundColor:"rgba(22,101,52,0.4)",borderColor:"rgba(255,255,255,0.3)",children:_jsxs(View,{style:styles.scoreBoard,children:[_jsxs(View,{style:styles.scoreSection,children:[_jsx(Text,{style:styles.scoreLabel,children:"Score"}),_jsx(Text,{style:styles.scoreValue,children:score})]}),_jsxs(View,{style:styles.scoreSection,children:[_jsx(Text,{style:styles.scoreLabel,children:"Time"}),_jsx(Text,{style:styles.timeValue,children:formatTime(timeLeft)})]})]})});});const styles = StyleSheet.create({scoreBoard:{flexDirection:'row',justifyContent:'space-between',alignItems:'center'},scoreSection:{alignItems:'center',flex:1},scoreLabel:{fontSize:16,fontWeight:'bold',color:'#ffffff',marginBottom:4},scoreValue:{fontSize:25,fontWeight:'bold',color:'#92400e'},timeValue:{fontSize:25,fontWeight:'bold',color:'#92400e'}});
1
+ "use strict";import e from"react";import{View as o,Text as t,StyleSheet as r}from"react-native";import{ScoreBoardContainer as i}from"../../../helpers/index.js";import{jsx as n,jsxs as c}from"react/jsx-runtime";export const ScoreBoard=e.memo(({score:e,timeLeft:r,offset:s=0})=>n(i,{offset:s,backgroundColor:"rgba(22, 101, 52, 0.4)",borderColor:"rgba(255, 255, 255, 0.3)",children:c(o,{style:l.scoreBoard,children:[c(o,{style:l.scoreSection,children:[n(t,{style:l.scoreLabel,children:"Score"}),n(t,{style:l.scoreValue,children:e})]}),c(o,{style:l.scoreSection,children:[n(t,{style:l.scoreLabel,children:"Time"}),n(t,{style:l.timeValue,children:(e=>{const o=e%60;return`${Math.floor(e/60).toString().padStart(2,"0")}:${o.toString().padStart(2,"0")}`})(r)})]})]})}));const l=r.create({scoreBoard:{flexDirection:"row",justifyContent:"space-between",alignItems:"center"},scoreSection:{alignItems:"center",flex:1},scoreLabel:{fontSize:16,fontWeight:"bold",color:"#ffffff",marginBottom:4},scoreValue:{fontSize:25,fontWeight:"bold",color:"#92400e"},timeValue:{fontSize:25,fontWeight:"bold",color:"#92400e"}});
@@ -1 +1 @@
1
- "use strict";export{ScoreBoard}from "./ScoreBoard.js";export{GameHole}from "./GameHole.js";export{GameGrid}from "./GameGrid.js";export{MoleCharacter}from "./MoleCharacter.js";export{GameBackground}from "./GameBackground.js";
1
+ "use strict";export{ScoreBoard}from"./ScoreBoard.js";export{GameHole}from"./GameHole.js";export{GameGrid}from"./GameGrid.js";export{MoleCharacter}from"./MoleCharacter.js";export{GameBackground}from"./GameBackground.js";
@@ -1 +1 @@
1
- "use strict";import{useEffect,useRef}from 'react';export class AnimationFrameManager{animationId = null;isRunning = false;lastTime = 0;constructor(callback,interval = 100){this.callback = callback;this.interval = interval;}start(){if(this.isRunning)return;this.isRunning = true;this.lastTime = performance.now();this.loop();}stop(){if(this.animationId){cancelAnimationFrame(this.animationId);this.animationId = null;}this.isRunning = false;}loop =()=>{if(!this.isRunning)return;const currentTime = performance.now();const deltaTime = currentTime - this.lastTime;if(deltaTime >= this.interval){this.callback();this.lastTime = currentTime;}this.animationId = requestAnimationFrame(this.loop);};updateCallback(callback){this.callback = callback;}updateInterval(interval){this.interval = interval;}}export function useAnimationFrame(callback,interval = 100,dependencies = []){const managerRef = useRef(null);useEffect(()=>{if(!managerRef.current){managerRef.current = new AnimationFrameManager(callback,interval);}else{managerRef.current.updateCallback(callback);managerRef.current.updateInterval(interval);}managerRef.current.start();return()=>{if(managerRef.current){managerRef.current.stop();}};},dependencies);useEffect(()=>{return()=>{if(managerRef.current){managerRef.current.stop();}};},[]);}export function useAnimationFrameManager(interval = 100){const managerRef = useRef(null);if(!managerRef.current){managerRef.current = new AnimationFrameManager(()=>{},interval);}useEffect(()=>{return()=>{if(managerRef.current){managerRef.current.stop();}};},[]);return managerRef.current;}
1
+ "use strict";import{useEffect as t,useRef as i}from"react";export class AnimationFrameManager{animationId=null;isRunning=!1;lastTime=0;constructor(t,i=100){this.callback=t,this.interval=i}start(){this.isRunning||(this.isRunning=!0,this.lastTime=performance.now(),this.loop())}stop(){this.animationId&&(cancelAnimationFrame(this.animationId),this.animationId=null),this.isRunning=!1}loop=()=>{if(!this.isRunning)return;const t=performance.now();t-this.lastTime<this.interval||(this.callback(),this.lastTime=t),this.animationId=requestAnimationFrame(this.loop)};updateCallback(t){this.callback=t}updateInterval(t){this.interval=t}}export function useAnimationFrame(n,a=100,s=[]){const e=i(null);t(()=>(e.current?(e.current.updateCallback(n),e.current.updateInterval(a)):e.current=new AnimationFrameManager(n,a),e.current.start(),()=>{e.current&&e.current.stop()}),s),t(()=>()=>{e.current&&e.current.stop()},[])}export function useAnimationFrameManager(n=100){const a=i(null);return a.current||(a.current=new AnimationFrameManager(()=>{},n)),t(()=>()=>{a.current&&a.current.stop()},[]),a.current}
@@ -1 +1 @@
1
- "use strict";import{useRef}from 'react';export const DEFAULT_ANIMATION_STATE ={scale:1,opacity:1,rotation:0,translateX:0,translateY:0};export class AnimationTracker extends Map{constructor(){super();}set(id,state){const currentState = super.get(id)||{...DEFAULT_ANIMATION_STATE};const newState ={...currentState,...state};super.set(id,newState);return this;}initialize(id,initialState){if(!this.has(id)){const state ={...DEFAULT_ANIMATION_STATE,...initialState};super.set(id,state);return state;}return this.get(id);}updateBatch(updates){updates.forEach(({id,state})=>{this.set(id,state);});}}export function useAnimationTracker(){return useRef(new AnimationTracker()).current;}export function useAnimationTrackers(trackerNames){const trackers = useRef(trackerNames.reduce((acc,name)=>{acc[name] = new AnimationTracker();return acc;},{})).current;return trackers;}
1
+ "use strict";import{useRef as t}from"react";export const DEFAULT_ANIMATION_STATE={scale:1,opacity:1,rotation:0,translateX:0,translateY:0};export class AnimationTracker extends Map{constructor(){super()}set(t,r){const e={...super.get(t)||{...DEFAULT_ANIMATION_STATE},...r};return super.set(t,e),this}initialize(t,r){if(!this.has(t)){const e={...DEFAULT_ANIMATION_STATE,...r};return super.set(t,e),e}return this.get(t)}updateBatch(t){t.forEach(({id:t,state:r})=>{this.set(t,r)})}}export function useAnimationTracker(){return t(new AnimationTracker).current}export function useAnimationTrackers(r){return t(r.reduce((t,r)=>(t[r]=new AnimationTracker,t),{})).current}
@@ -1 +1 @@
1
- "use strict";import{useCallback,useRef}from 'react';export let GameErrorType = function(GameErrorType){GameErrorType["INITIALIZATION_ERROR"] = "INITIALIZATION_ERROR";GameErrorType["ANIMATION_ERROR"] = "ANIMATION_ERROR";GameErrorType["STORAGE_ERROR"] = "STORAGE_ERROR";GameErrorType["SOUND_ERROR"] = "SOUND_ERROR";GameErrorType["HAPTIC_ERROR"] = "HAPTIC_ERROR";GameErrorType["GESTURE_ERROR"] = "GESTURE_ERROR";GameErrorType["PERFORMANCE_ERROR"] = "PERFORMANCE_ERROR";GameErrorType["NETWORK_ERROR"] = "NETWORK_ERROR";GameErrorType["UNKNOWN_ERROR"] = "UNKNOWN_ERROR";return GameErrorType;}({});export const DEFAULT_ERROR_CONFIG ={enableLogging:__DEV__,enableConsoleOutput:__DEV__,maxErrorHistory:50,enableCrashRecovery:true};export class GameErrorHandler{errorHistory = [];errorCounts = new Map();constructor(config ={}){this.config ={...DEFAULT_ERROR_CONFIG,...config};}handleError(type,message,gameId,context){const error ={type,message,gameId,timestamp:Date.now(),stack:new Error().stack,context};this.errorHistory.push(error);if(this.errorHistory.length > this.config.maxErrorHistory){this.errorHistory.shift();}const currentCount = this.errorCounts.get(type)|| 0;this.errorCounts.set(type,currentCount + 1);if(this.config.enableLogging && this.config.enableConsoleOutput){this.logError(error);}if(this.config.onError){try{this.config.onError(error);}catch(handlerError){console.error('Error in custom error handler:',handlerError);}}}wrapFunction(fn,errorType,gameId){return(...args)=>{try{const result = fn(...args);if(result && typeof result.catch === 'function'){return result.catch(error =>{this.handleError(errorType,error.message || 'Async function error',gameId,{functionName:fn.name,args});throw error;});}return result;}catch(error){this.handleError(errorType,error instanceof Error ? error.message:'Unknown error',gameId,{functionName:fn.name,args});throw error;}};}safeExecute(fn,fallback,errorType,gameId){try{return fn();}catch(error){this.handleError(errorType,error instanceof Error ? error.message:'Safe execution failed',gameId,{fallback});return fallback;}}async safeExecuteAsync(fn,fallback,errorType,gameId){try{return await fn();}catch(error){this.handleError(errorType,error instanceof Error ? error.message:'Safe async execution failed',gameId,{fallback});return fallback;}}getErrorStats(){const errorsByType ={};for(const [type,count] of this.errorCounts.entries()){errorsByType[type] = count;}return{totalErrors:this.errorHistory.length,errorsByType,recentErrors:this.errorHistory.slice(-10)};}clearHistory(){this.errorHistory = [];this.errorCounts.clear();}updateConfig(config){this.config ={...this.config,...config};}logError(error){const prefix = error.gameId ? `[${error.gameId}]`:'[Game]';console.error(`${prefix}${error.type}:${error.message}`,{timestamp:new Date(error.timestamp).toISOString(),context:error.context,stack:error.stack});}}export const globalErrorHandler = new GameErrorHandler();export function useGameErrorHandler(gameId,config ={}){const handlerRef = useRef(null);if(!handlerRef.current){handlerRef.current = new GameErrorHandler(config);}const handleError = useCallback((type,message,context)=>{handlerRef.current?.handleError(type,message,gameId,context);},[gameId]);const wrapFunction = useCallback((fn,errorType)=>{return handlerRef.current?.wrapFunction(fn,errorType,gameId)|| fn;},[gameId]);const safeExecute = useCallback((fn,fallback,errorType)=>{return handlerRef.current?.safeExecute(fn,fallback,errorType,gameId)|| fallback;},[gameId]);const safeExecuteAsync = useCallback((fn,fallback,errorType)=>{return handlerRef.current?.safeExecuteAsync(fn,fallback,errorType,gameId)|| Promise.resolve(fallback);},[gameId]);return{handleError,wrapFunction,safeExecute,safeExecuteAsync,errorStats:handlerRef.current?.getErrorStats()||{totalErrors:0,errorsByType:{},recentErrors:[]}};}export function withErrorHandling(fn,gameId,errorType = GameErrorType.UNKNOWN_ERROR){return globalErrorHandler.wrapFunction(fn,errorType,gameId);}export const ErrorUtils ={safeAnimate:(animationFn,gameId,fallback)=>{globalErrorHandler.safeExecute(animationFn,fallback ? fallback():undefined,GameErrorType.ANIMATION_ERROR,gameId);},safePlaySound:(soundFn,gameId)=>{globalErrorHandler.safeExecute(soundFn,undefined,GameErrorType.SOUND_ERROR,gameId);},safeHaptic:(hapticFn,gameId)=>{globalErrorHandler.safeExecute(hapticFn,undefined,GameErrorType.HAPTIC_ERROR,gameId);},safeGesture:(gestureFn,gameId)=>{globalErrorHandler.safeExecute(gestureFn,undefined,GameErrorType.GESTURE_ERROR,gameId);}};
1
+ "use strict";import{useCallback as r,useRef as e}from"react";export let GameErrorType=function(r){return r.INITIALIZATION_ERROR="INITIALIZATION_ERROR",r.ANIMATION_ERROR="ANIMATION_ERROR",r.STORAGE_ERROR="STORAGE_ERROR",r.SOUND_ERROR="SOUND_ERROR",r.HAPTIC_ERROR="HAPTIC_ERROR",r.GESTURE_ERROR="GESTURE_ERROR",r.PERFORMANCE_ERROR="PERFORMANCE_ERROR",r.NETWORK_ERROR="NETWORK_ERROR",r.UNKNOWN_ERROR="UNKNOWN_ERROR",r}({});export const DEFAULT_ERROR_CONFIG={enableLogging:__DEV__,enableConsoleOutput:__DEV__,maxErrorHistory:50,enableCrashRecovery:!0};export class GameErrorHandler{errorHistory=[];errorCounts=new Map;constructor(r={}){this.config={...DEFAULT_ERROR_CONFIG,...r}}handleError(r,e,t,o){const a={type:r,message:e,gameId:t,timestamp:Date.now(),stack:Error().stack,context:o};this.errorHistory.push(a),this.errorHistory.length>this.config.maxErrorHistory&&this.errorHistory.shift();const n=this.errorCounts.get(r)||0;if(this.errorCounts.set(r,n+1),this.config.enableLogging&&this.config.enableConsoleOutput&&this.logError(a),this.config.onError)try{this.config.onError(a)}catch(r){}}wrapFunction(r,e,t){return(...o)=>{try{const a=r(...o);return a&&"function"==typeof a.catch?a.catch(a=>{throw this.handleError(e,a.message||"Async function error",t,{functionName:r.name,args:o}),a}):a}catch(a){throw this.handleError(e,a instanceof Error?a.message:"Unknown error",t,{functionName:r.name,args:o}),a}}}safeExecute(r,e,t,o){try{return r()}catch(r){return this.handleError(t,r instanceof Error?r.message:"Safe execution failed",o,{fallback:e}),e}}async safeExecuteAsync(r,e,t,o){try{return await r()}catch(r){return this.handleError(t,r instanceof Error?r.message:"Safe async execution failed",o,{fallback:e}),e}}getErrorStats(){const r={};for(const[e,t]of this.errorCounts.entries())r[e]=t;return{totalErrors:this.errorHistory.length,errorsByType:r,recentErrors:this.errorHistory.slice(-10)}}clearHistory(){this.errorHistory=[],this.errorCounts.clear()}updateConfig(r){this.config={...this.config,...r}}logError(r){r.gameId&&r.gameId}}export const globalErrorHandler=new GameErrorHandler;export function useGameErrorHandler(t,o={}){const a=e(null);return a.current||(a.current=new GameErrorHandler(o)),{handleError:r((r,e,o)=>{a.current?.handleError(r,e,t,o)},[t]),wrapFunction:r((r,e)=>a.current?.wrapFunction(r,e,t)||r,[t]),safeExecute:r((r,e,o)=>a.current?.safeExecute(r,e,o,t)||e,[t]),safeExecuteAsync:r((r,e,o)=>a.current?.safeExecuteAsync(r,e,o,t)||Promise.resolve(e),[t]),errorStats:a.current?.getErrorStats()||{totalErrors:0,errorsByType:{},recentErrors:[]}}}export function withErrorHandling(r,e,t=GameErrorType.UNKNOWN_ERROR){return globalErrorHandler.wrapFunction(r,t,e)}export const ErrorUtils={safeAnimate:(r,e,t)=>{globalErrorHandler.safeExecute(r,t?t():void 0,GameErrorType.ANIMATION_ERROR,e)},safePlaySound:(r,e)=>{globalErrorHandler.safeExecute(r,void 0,GameErrorType.SOUND_ERROR,e)},safeHaptic:(r,e)=>{globalErrorHandler.safeExecute(r,void 0,GameErrorType.HAPTIC_ERROR,e)},safeGesture:(r,e)=>{globalErrorHandler.safeExecute(r,void 0,GameErrorType.GESTURE_ERROR,e)}};
@@ -1 +1 @@
1
- "use strict";import React,{useRef,useEffect,useMemo}from 'react';import{View,TouchableOpacity,Text,StyleSheet,Animated}from 'react-native';import{jsx as _jsx,jsxs as _jsxs}from "react/jsx-runtime";export const GameControlButton = React.memo(({isPlaying,gameOver,onStartGame,onStopGame,startButtonText = 'START GAME',stopButtonText = 'STOP GAME',startButtonSubtext = 'Begin playing!',stopButtonSubtext = 'End current game',startButtonColor = '#10b981',stopButtonColor = '#dc2626',startButtonBorderColor = '#34d399',stopButtonBorderColor = '#f87171'})=>{const scaleAnim = useRef(new Animated.Value(1)).current;const pulseAnim = useRef(new Animated.Value(1)).current;const glowAnim = useRef(new Animated.Value(0)).current;useEffect(()=>{if(!isPlaying){const pulseAnimation = Animated.loop(Animated.sequence([Animated.timing(pulseAnim,{toValue:1.05,duration:1000,useNativeDriver:true}),Animated.timing(pulseAnim,{toValue:1,duration:1000,useNativeDriver:true})]));pulseAnimation.start();return()=> pulseAnimation.stop();}return()=>{};},[isPlaying,gameOver,pulseAnim]);useEffect(()=>{if(isPlaying){const glowAnimation = Animated.loop(Animated.sequence([Animated.timing(glowAnim,{toValue:1,duration:800,useNativeDriver:false}),Animated.timing(glowAnim,{toValue:0,duration:800,useNativeDriver:false})]));glowAnimation.start();return()=> glowAnimation.stop();}return()=>{};},[isPlaying,glowAnim]);const handlePressIn =()=>{Animated.spring(scaleAnim,{toValue:0.95,useNativeDriver:true}).start();};const handlePressOut =()=>{Animated.spring(scaleAnim,{toValue:1,friction:3,tension:40,useNativeDriver:true}).start();};const glowColor = useMemo(()=> glowAnim.interpolate({inputRange:[0,1],outputRange:[`${stopButtonColor}30`,`${stopButtonColor}CC`]}),[glowAnim,stopButtonColor]);return _jsx(View,{style:styles.controlButtonContainer,children:_jsxs(View,{style:styles.gameControls,children:[!isPlaying && _jsx(Animated.View,{style:[{transform:[{scale:pulseAnim}]}],children:_jsx(TouchableOpacity,{style:[styles.button,styles.startButton,{backgroundColor:startButtonColor,borderColor:startButtonBorderColor}],onPress:onStartGame,onPressIn:handlePressIn,onPressOut:handlePressOut,activeOpacity:0.8,children:_jsxs(Animated.View,{style:[styles.buttonContent,{transform:[{scale:scaleAnim}]}],children:[_jsx(Text,{style:styles.buttonText,children:startButtonText}),_jsx(Text,{style:styles.buttonSubtext,children:startButtonSubtext})]})})}),isPlaying && _jsx(Animated.View,{style:[styles.stopButtonContainer,{shadowColor:glowColor}],children:_jsx(TouchableOpacity,{style:[styles.button,styles.stopButton,{backgroundColor:stopButtonColor,borderColor:stopButtonBorderColor}],onPress:onStopGame,onPressIn:handlePressIn,onPressOut:handlePressOut,activeOpacity:0.8,children:_jsxs(Animated.View,{style:[styles.buttonContent,{transform:[{scale:scaleAnim}]}],children:[_jsx(Text,{style:styles.buttonText,children:stopButtonText}),_jsx(Text,{style:styles.buttonSubtext,children:stopButtonSubtext})]})})})]})});});const styles = StyleSheet.create({controlButtonContainer:{position:'absolute',bottom:0,left:20,right:20,zIndex:100,pointerEvents:'box-none'},gameControls:{justifyContent:'center',alignItems:'center',paddingVertical:20,paddingHorizontal:20},button:{paddingHorizontal:32,paddingVertical:20,borderRadius:30,shadowColor:'#000',shadowOffset:{width:0,height:8},shadowOpacity:0.4,shadowRadius:12,elevation:8,justifyContent:'center',alignItems:'center',minHeight:70,minWidth:200,borderWidth:3,position:'relative',overflow:'hidden'},startButton:{},stopButton:{},stopButtonContainer:{shadowOffset:{width:0,height:0},shadowOpacity:0.6,shadowRadius:20,elevation:10},buttonContent:{alignItems:'center',justifyContent:'center'},buttonText:{fontSize:20,fontWeight:'800',color:'#ffffff',textAlign:'center',textShadowColor:'rgba(0,0,0,0.3)',textShadowOffset:{width:1,height:1},textShadowRadius:2,letterSpacing:1},buttonSubtext:{fontSize:12,fontWeight:'600',color:'rgba(255,255,255,0.8)',textAlign:'center',marginTop:4,letterSpacing:0.5}});
1
+ "use strict";import t,{useRef as e,useEffect as o,useMemo as n}from"react";import{View as r,TouchableOpacity as i,Text as a,StyleSheet as s,Animated as l}from"react-native";import{jsx as u,jsxs as d}from"react/jsx-runtime";export const GameControlButton=t.memo(({isPlaying:t,gameOver:s,onStartGame:h,onStopGame:f,startButtonText:g="START GAME",stopButtonText:p="STOP GAME",startButtonSubtext:m="Begin playing!",stopButtonSubtext:v="End current game",startButtonColor:y="#10b981",stopButtonColor:C="#dc2626",startButtonBorderColor:b="#34d399",stopButtonBorderColor:w="#f87171"})=>{const x=e(new l.Value(1)).current,B=e(new l.Value(1)).current,S=e(new l.Value(0)).current;o(()=>{if(!t){const t=l.loop(l.sequence([l.timing(B,{toValue:1.05,duration:1e3,useNativeDriver:!0}),l.timing(B,{toValue:1,duration:1e3,useNativeDriver:!0})]));return t.start(),()=>t.stop()}return()=>{}},[t,s,B]),o(()=>{if(t){const t=l.loop(l.sequence([l.timing(S,{toValue:1,duration:800,useNativeDriver:!1}),l.timing(S,{toValue:0,duration:800,useNativeDriver:!1})]));return t.start(),()=>t.stop()}return()=>{}},[t,S]);const O=()=>{l.spring(x,{toValue:.95,useNativeDriver:!0}).start()},P=()=>{l.spring(x,{toValue:1,friction:3,tension:40,useNativeDriver:!0}).start()},V=n(()=>S.interpolate({inputRange:[0,1],outputRange:[C+"30",C+"CC"]}),[S,C]);return u(r,{style:c.controlButtonContainer,children:d(r,{style:c.gameControls,children:[!t&&u(l.View,{style:[{transform:[{scale:B}]}],children:u(i,{style:[c.button,c.startButton,{backgroundColor:y,borderColor:b}],onPress:h,onPressIn:O,onPressOut:P,activeOpacity:.8,children:d(l.View,{style:[c.buttonContent,{transform:[{scale:x}]}],children:[u(a,{style:c.buttonText,children:g}),u(a,{style:c.buttonSubtext,children:m})]})})}),t&&u(l.View,{style:[c.stopButtonContainer,{shadowColor:V}],children:u(i,{style:[c.button,c.stopButton,{backgroundColor:C,borderColor:w}],onPress:f,onPressIn:O,onPressOut:P,activeOpacity:.8,children:d(l.View,{style:[c.buttonContent,{transform:[{scale:x}]}],children:[u(a,{style:c.buttonText,children:p}),u(a,{style:c.buttonSubtext,children:v})]})})})]})})});const c=s.create({controlButtonContainer:{position:"absolute",bottom:0,left:20,right:20,zIndex:100,pointerEvents:"box-none"},gameControls:{justifyContent:"center",alignItems:"center",paddingVertical:20,paddingHorizontal:20},button:{paddingHorizontal:32,paddingVertical:20,borderRadius:30,shadowColor:"#000",shadowOffset:{width:0,height:8},shadowOpacity:.4,shadowRadius:12,elevation:8,justifyContent:"center",alignItems:"center",minHeight:70,minWidth:200,borderWidth:3,position:"relative",overflow:"hidden"},startButton:{},stopButton:{},stopButtonContainer:{shadowOffset:{width:0,height:0},shadowOpacity:.6,shadowRadius:20,elevation:10},buttonContent:{alignItems:"center",justifyContent:"center"},buttonText:{fontSize:20,fontWeight:"800",color:"#ffffff",textAlign:"center",textShadowColor:"rgba(0, 0, 0, 0.3)",textShadowOffset:{width:1,height:1},textShadowRadius:2,letterSpacing:1},buttonSubtext:{fontSize:12,fontWeight:"600",color:"rgba(255, 255, 255, 0.8)",textAlign:"center",marginTop:4,letterSpacing:.5}});