react-native-games 1.1.0 → 1.2.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 (212) hide show
  1. package/README.md +58 -7
  2. package/lib/module/games/balloon-blaster/BalloonBlaster.js +1 -167
  3. package/lib/module/games/balloon-blaster/BalloonBlaster.js.map +1 -1
  4. package/lib/module/games/balloon-blaster/BalloonBlasterConstants.js +1 -182
  5. package/lib/module/games/balloon-blaster/BalloonBlasterConstants.js.map +1 -1
  6. package/lib/module/games/balloon-blaster/BalloonBlasterService.js +1 -318
  7. package/lib/module/games/balloon-blaster/BalloonBlasterStore.js +1 -183
  8. package/lib/module/games/balloon-blaster/components/BalloonComponent.js +1 -237
  9. package/lib/module/games/balloon-blaster/components/GameArea.js +1 -156
  10. package/lib/module/games/balloon-blaster/components/GameBackground.js +1 -476
  11. package/lib/module/games/balloon-blaster/components/ScoreBoard.js +1 -112
  12. package/lib/module/games/balloon-blaster/components/ScoreBoard.js.map +1 -1
  13. package/lib/module/games/balloon-blaster/components/index.js +1 -7
  14. package/lib/module/games/candy-crush/CandyCrush.js +1 -131
  15. package/lib/module/games/candy-crush/CandyCrush.js.map +1 -1
  16. package/lib/module/games/candy-crush/CandyCrushConstants.js +1 -125
  17. package/lib/module/games/candy-crush/CandyCrushConstants.js.map +1 -1
  18. package/lib/module/games/candy-crush/CandyCrushService.js +1 -370
  19. package/lib/module/games/candy-crush/CandyCrushStore.js +1 -303
  20. package/lib/module/games/candy-crush/components/CandyItem.js +1 -191
  21. package/lib/module/games/candy-crush/components/GameBackground.js +1 -85
  22. package/lib/module/games/candy-crush/components/GameGrid.js +1 -314
  23. package/lib/module/games/candy-crush/components/ScoreBoard.js +1 -79
  24. package/lib/module/games/candy-crush/components/index.js +1 -7
  25. package/lib/module/games/candy-crush/index.js +1 -6
  26. package/lib/module/games/colors-sort/ColorsSort.js +1 -143
  27. package/lib/module/games/colors-sort/ColorsSort.js.map +1 -1
  28. package/lib/module/games/colors-sort/ColorsSortConstants.js +1 -72
  29. package/lib/module/games/colors-sort/ColorsSortConstants.js.map +1 -1
  30. package/lib/module/games/colors-sort/ColorsSortService.js +1 -255
  31. package/lib/module/games/colors-sort/ColorsSortStore.js +1 -257
  32. package/lib/module/games/colors-sort/ColorsSortStore.js.map +1 -1
  33. package/lib/module/games/colors-sort/components/ColorContainer.js +1 -140
  34. package/lib/module/games/colors-sort/components/GameBackground.js +1 -135
  35. package/lib/module/games/colors-sort/components/ScoreBoard.js +1 -70
  36. package/lib/module/games/colors-sort/components/index.js +1 -6
  37. package/lib/module/games/dino-jump/DinoJump.js +1 -209
  38. package/lib/module/games/dino-jump/DinoJump.js.map +1 -1
  39. package/lib/module/games/dino-jump/DinoJumpConstants.js +1 -189
  40. package/lib/module/games/dino-jump/DinoJumpConstants.js.map +1 -1
  41. package/lib/module/games/dino-jump/DinoJumpService.js +1 -270
  42. package/lib/module/games/dino-jump/DinoJumpStore.js +1 -381
  43. package/lib/module/games/dino-jump/components/DinoSprite.js +1 -418
  44. package/lib/module/games/dino-jump/components/DinoSprite.js.map +1 -1
  45. package/lib/module/games/dino-jump/components/GameArea.js +1 -68
  46. package/lib/module/games/dino-jump/components/GameBackground.js +1 -444
  47. package/lib/module/games/dino-jump/components/ObstacleSprite.js +1 -306
  48. package/lib/module/games/dino-jump/components/ScoreBoard.js +1 -105
  49. package/lib/module/games/dino-jump/components/ScoreBoard.js.map +1 -1
  50. package/lib/module/games/dino-jump/components/StarSprite.js +1 -45
  51. package/lib/module/games/dino-jump/components/index.js +1 -9
  52. package/lib/module/games/flappy-bird/FlappyBird.js +1 -126
  53. package/lib/module/games/flappy-bird/FlappyBird.js.map +1 -1
  54. package/lib/module/games/flappy-bird/FlappyBirdConstants.js +1 -90
  55. package/lib/module/games/flappy-bird/FlappyBirdConstants.js.map +1 -1
  56. package/lib/module/games/flappy-bird/FlappyBirdStore.js +1 -300
  57. package/lib/module/games/flappy-bird/components/Bird.js +1 -87
  58. package/lib/module/games/flappy-bird/components/GameArea.js +1 -87
  59. package/lib/module/games/flappy-bird/components/GameBackground.js +1 -79
  60. package/lib/module/games/flappy-bird/components/Pipes.js +1 -172
  61. package/lib/module/games/flappy-bird/components/ScoreBoard.js +1 -73
  62. package/lib/module/games/flappy-bird/components/index.js +1 -8
  63. package/lib/module/games/fruit-merger/FruitMerger.js +1 -120
  64. package/lib/module/games/fruit-merger/FruitMerger.js.map +1 -1
  65. package/lib/module/games/fruit-merger/FruitMergerConstants.js +1 -119
  66. package/lib/module/games/fruit-merger/FruitMergerConstants.js.map +1 -1
  67. package/lib/module/games/fruit-merger/FruitMergerService.js +1 -13
  68. package/lib/module/games/fruit-merger/FruitMergerStore.js +1 -315
  69. package/lib/module/games/fruit-merger/components/FruitItem.js +1 -102
  70. package/lib/module/games/fruit-merger/components/GameArea.js +1 -103
  71. package/lib/module/games/fruit-merger/components/GameBackground.js +1 -498
  72. package/lib/module/games/fruit-merger/components/ScoreBoard.js +1 -58
  73. package/lib/module/games/fruit-merger/components/index.js +1 -7
  74. package/lib/module/games/fruit-ninja/FruitNinja.js +1 -134
  75. package/lib/module/games/fruit-ninja/FruitNinja.js.map +1 -1
  76. package/lib/module/games/fruit-ninja/FruitNinjaConstants.js +1 -148
  77. package/lib/module/games/fruit-ninja/FruitNinjaConstants.js.map +1 -1
  78. package/lib/module/games/fruit-ninja/FruitNinjaService.js +1 -311
  79. package/lib/module/games/fruit-ninja/FruitNinjaStore.js +1 -191
  80. package/lib/module/games/fruit-ninja/FruitNinjaStore.js.map +1 -1
  81. package/lib/module/games/fruit-ninja/components/FruitComponent.js +1 -99
  82. package/lib/module/games/fruit-ninja/components/GameArea.js +1 -215
  83. package/lib/module/games/fruit-ninja/components/GameBackground.js +1 -1267
  84. package/lib/module/games/fruit-ninja/components/ScoreBoard.js +1 -92
  85. package/lib/module/games/fruit-ninja/components/ScoreBoard.js.map +1 -1
  86. package/lib/module/games/fruit-ninja/components/index.js +1 -7
  87. package/lib/module/games/game-2048/Game2048.js +1 -149
  88. package/lib/module/games/game-2048/Game2048.js.map +1 -1
  89. package/lib/module/games/game-2048/Game2048Constants.js +1 -263
  90. package/lib/module/games/game-2048/Game2048Constants.js.map +1 -1
  91. package/lib/module/games/game-2048/Game2048Service.js +1 -457
  92. package/lib/module/games/game-2048/Game2048Store.js +1 -236
  93. package/lib/module/games/game-2048/components/GameBackground.js +1 -247
  94. package/lib/module/games/game-2048/components/GameGrid.js +1 -139
  95. package/lib/module/games/game-2048/components/GameTile.js +1 -72
  96. package/lib/module/games/game-2048/components/ScoreBoard.js +1 -52
  97. package/lib/module/games/game-2048/components/index.js +1 -7
  98. package/lib/module/games/maze-runner/MazeRunner.js +1 -267
  99. package/lib/module/games/maze-runner/MazeRunner.js.map +1 -1
  100. package/lib/module/games/maze-runner/MazeRunnerConstants.js +1 -100
  101. package/lib/module/games/maze-runner/MazeRunnerConstants.js.map +1 -1
  102. package/lib/module/games/maze-runner/MazeRunnerService.js +1 -586
  103. package/lib/module/games/maze-runner/components/EnhancedBallComponent.js +1 -150
  104. package/lib/module/games/maze-runner/components/EnhancedGameArea.js +1 -370
  105. package/lib/module/games/maze-runner/components/GameBackground.js +1 -175
  106. package/lib/module/games/maze-runner/components/ScoreBoard.js +1 -61
  107. package/lib/module/games/maze-runner/components/SkiaPipeComponent.js +1 -209
  108. package/lib/module/games/maze-runner/components/StaticGameBackground.js +1 -169
  109. package/lib/module/games/maze-runner/components/WallComponent.js +1 -91
  110. package/lib/module/games/maze-runner/components/index.js +1 -8
  111. package/lib/module/games/popit-fidget/PopitFidget.js +1 -285
  112. package/lib/module/games/popit-fidget/PopitFidget.js.map +1 -1
  113. package/lib/module/games/popit-fidget/PopitFidgetConstants.js +1 -113
  114. package/lib/module/games/popit-fidget/PopitFidgetConstants.js.map +1 -1
  115. package/lib/module/games/popit-fidget/PopitFidgetService.js +1 -132
  116. package/lib/module/games/popit-fidget/PopitFidgetStore.js +1 -125
  117. package/lib/module/games/popit-fidget/components/BubbleComponent.js +1 -198
  118. package/lib/module/games/popit-fidget/components/FidgetGrid.js +1 -165
  119. package/lib/module/games/popit-fidget/components/GameBackground.js +1 -177
  120. package/lib/module/games/popit-fidget/components/ScoreBoard.js +1 -61
  121. package/lib/module/games/popit-fidget/components/index.js +1 -7
  122. package/lib/module/games/sliding-numbers/SlidingNumbers.js +1 -159
  123. package/lib/module/games/sliding-numbers/SlidingNumbers.js.map +1 -1
  124. package/lib/module/games/sliding-numbers/SlidingNumbersConstants.js +1 -207
  125. package/lib/module/games/sliding-numbers/SlidingNumbersConstants.js.map +1 -1
  126. package/lib/module/games/sliding-numbers/SlidingNumbersService.js +1 -248
  127. package/lib/module/games/sliding-numbers/SlidingNumbersStore.js +1 -274
  128. package/lib/module/games/sliding-numbers/components/GameBackground.js +1 -259
  129. package/lib/module/games/sliding-numbers/components/NumbersGrid.js +1 -174
  130. package/lib/module/games/sliding-numbers/components/NumbersTile.js +1 -116
  131. package/lib/module/games/sliding-numbers/components/ScoreBoard.js +1 -64
  132. package/lib/module/games/sliding-numbers/components/index.js +1 -7
  133. package/lib/module/games/snake/Snake.js +1 -189
  134. package/lib/module/games/snake/Snake.js.map +1 -1
  135. package/lib/module/games/snake/SnakeConstants.js +1 -138
  136. package/lib/module/games/snake/SnakeConstants.js.map +1 -1
  137. package/lib/module/games/snake/SnakeService.js +1 -148
  138. package/lib/module/games/snake/SnakeStore.js +1 -182
  139. package/lib/module/games/snake/components/GameBackground.js +1 -221
  140. package/lib/module/games/snake/components/GameGrid.js +1 -153
  141. package/lib/module/games/snake/components/ScoreBoard.js +1 -51
  142. package/lib/module/games/snake/components/index.js +1 -6
  143. package/lib/module/games/snake/index.js +1 -6
  144. package/lib/module/games/space-fighter/SpaceFighter.js +1 -165
  145. package/lib/module/games/space-fighter/SpaceFighter.js.map +1 -1
  146. package/lib/module/games/space-fighter/SpaceFighterConstants.js +1 -108
  147. package/lib/module/games/space-fighter/SpaceFighterConstants.js.map +1 -1
  148. package/lib/module/games/space-fighter/SpaceFighterService.js +1 -326
  149. package/lib/module/games/space-fighter/SpaceFighterStore.js +1 -209
  150. package/lib/module/games/space-fighter/components/AsteroidComponent.js +1 -113
  151. package/lib/module/games/space-fighter/components/GameArea.js +1 -289
  152. package/lib/module/games/space-fighter/components/GameBackground.js +1 -239
  153. package/lib/module/games/space-fighter/components/ScoreBoard.js +1 -136
  154. package/lib/module/games/space-fighter/components/Spacecraft3D.js +1 -202
  155. package/lib/module/games/space-fighter/components/SpacecraftPath.js +1 -52
  156. package/lib/module/games/space-fighter/components/index.js +1 -9
  157. package/lib/module/games/whack-a-mole/WhackAMole.js +1 -270
  158. package/lib/module/games/whack-a-mole/WhackAMole.js.map +1 -1
  159. package/lib/module/games/whack-a-mole/WhackAMoleConstants.js +1 -115
  160. package/lib/module/games/whack-a-mole/WhackAMoleConstants.js.map +1 -1
  161. package/lib/module/games/whack-a-mole/WhackAMoleService.js +1 -120
  162. package/lib/module/games/whack-a-mole/WhackAMoleStore.js +1 -172
  163. package/lib/module/games/whack-a-mole/components/GameBackground.js +1 -477
  164. package/lib/module/games/whack-a-mole/components/GameGrid.js +1 -97
  165. package/lib/module/games/whack-a-mole/components/GameHole.js +1 -196
  166. package/lib/module/games/whack-a-mole/components/MoleCharacter.js +1 -241
  167. package/lib/module/games/whack-a-mole/components/ScoreBoard.js +1 -67
  168. package/lib/module/games/whack-a-mole/components/ScoreBoard.js.map +1 -1
  169. package/lib/module/games/whack-a-mole/components/index.js +1 -8
  170. package/lib/module/helpers/AnimationFrame.js +1 -120
  171. package/lib/module/helpers/AnimationTracker.js +1 -89
  172. package/lib/module/helpers/ErrorHandler.js +1 -269
  173. package/lib/module/helpers/GameControlButton.js +1 -219
  174. package/lib/module/helpers/GameOverModal.js +1 -144
  175. package/lib/module/helpers/GameOverModal.js.map +1 -1
  176. package/lib/module/helpers/GameSettingsModal.js +1 -287
  177. package/lib/module/helpers/ParticleBlast.js +1 -134
  178. package/lib/module/helpers/ScoreBoardContainer.js +1 -34
  179. package/lib/module/helpers/index.js +1 -12
  180. package/lib/module/index.js +1 -22
  181. package/lib/module/services/GamesConstants.js +1 -178
  182. package/lib/module/services/GamesService.js +1 -112
  183. package/lib/module/services/GamesService.js.map +1 -1
  184. package/lib/module/services/HapticsService.js +1 -77
  185. package/lib/module/services/SoundsService.js +1 -302
  186. package/lib/module/services/UtilsService.js +1 -32
  187. package/lib/typescript/src/games/balloon-blaster/BalloonBlaster.d.ts.map +1 -1
  188. package/lib/typescript/src/games/balloon-blaster/BalloonBlasterConstants.d.ts +1 -1
  189. package/lib/typescript/src/games/balloon-blaster/components/ScoreBoard.d.ts.map +1 -1
  190. package/lib/typescript/src/games/candy-crush/CandyCrushConstants.d.ts +7 -7
  191. package/lib/typescript/src/games/colors-sort/ColorsSort.d.ts.map +1 -1
  192. package/lib/typescript/src/games/colors-sort/ColorsSortStore.d.ts.map +1 -1
  193. package/lib/typescript/src/games/dino-jump/DinoJump.d.ts.map +1 -1
  194. package/lib/typescript/src/games/dino-jump/components/DinoSprite.d.ts.map +1 -1
  195. package/lib/typescript/src/games/flappy-bird/FlappyBird.d.ts.map +1 -1
  196. package/lib/typescript/src/games/flappy-bird/FlappyBirdConstants.d.ts.map +1 -1
  197. package/lib/typescript/src/games/fruit-merger/FruitMerger.d.ts.map +1 -1
  198. package/lib/typescript/src/games/fruit-merger/FruitMergerConstants.d.ts.map +1 -1
  199. package/lib/typescript/src/games/fruit-ninja/FruitNinja.d.ts.map +1 -1
  200. package/lib/typescript/src/games/fruit-ninja/components/ScoreBoard.d.ts.map +1 -1
  201. package/lib/typescript/src/games/game-2048/Game2048.d.ts.map +1 -1
  202. package/lib/typescript/src/games/maze-runner/MazeRunner.d.ts.map +1 -1
  203. package/lib/typescript/src/games/popit-fidget/PopitFidget.d.ts.map +1 -1
  204. package/lib/typescript/src/games/sliding-numbers/SlidingNumbers.d.ts.map +1 -1
  205. package/lib/typescript/src/games/space-fighter/SpaceFighter.d.ts.map +1 -1
  206. package/lib/typescript/src/games/whack-a-mole/WhackAMole.d.ts.map +1 -1
  207. package/lib/typescript/src/games/whack-a-mole/WhackAMoleConstants.d.ts +1 -1
  208. package/lib/typescript/src/games/whack-a-mole/components/ScoreBoard.d.ts.map +1 -1
  209. package/lib/typescript/src/helpers/GameOverModal.d.ts +3 -0
  210. package/lib/typescript/src/helpers/GameOverModal.d.ts.map +1 -1
  211. package/lib/typescript/src/services/GamesConstants.d.ts +7 -7
  212. package/package.json +2 -2
@@ -1,132 +1 @@
1
- "use strict";
2
-
3
- import { Dimensions } from 'react-native';
4
- import { POPIT_FIDGET_GAME_CONFIG as GAME_CONFIG, POPIT_FIDGET_ANIMATION_CONFIG as ANIMATION_CONFIG, POPIT_FIDGET_COLORS as COLORS, RAINBOW_COLORS, BUBBLE_COLORS } from "./PopitFidgetConstants.js";
5
- const {
6
- width,
7
- height
8
- } = Dimensions.get('window');
9
-
10
- // Constants now imported from PopitFidgetConstants.ts
11
- // Re-export for backward compatibility
12
- export { GAME_CONFIG, ANIMATION_CONFIG, COLORS, BUBBLE_COLORS };
13
-
14
- // Types - Simplified to always use square grids
15
-
16
- export class PopitFidgetService {
17
- gameTimerRef = null;
18
- constructor() {}
19
-
20
- // Generate square fidget grid based on difficulty
21
- generateFidgetGrid(difficulty) {
22
- const availableWidth = width * 0.85; // Match PopitFidget component calculation
23
- const availableHeight = height * 0.6; // Match PopitFidget component calculation
24
-
25
- // Get grid size from difficulty-based configuration
26
- const gridSize = GAME_CONFIG.GRID_SIZES[difficulty];
27
-
28
- // Use same bubble size calculation as PopitFidget component
29
- const maxSize = Math.min(availableWidth / gridSize, availableHeight / gridSize);
30
- const bubbleSize = Math.max(45, Math.min(80, maxSize * 0.9));
31
-
32
- // Calculate grid dimensions with proper spacing
33
- const spacing = bubbleSize * 1.1;
34
- const gridWidth = (gridSize - 1) * spacing + bubbleSize;
35
- const gridHeight = (gridSize - 1) * spacing + bubbleSize;
36
- const bubbles = [];
37
-
38
- // Generate square grid - all bubbles are included (no shape filtering)
39
- for (let row = 0; row < gridSize; row++) {
40
- bubbles[row] = [];
41
- for (let col = 0; col < gridSize; col++) {
42
- // Position bubbles with proper spacing to prevent overlap
43
- const x = col * spacing + bubbleSize / 2;
44
- const y = row * spacing + bubbleSize / 2;
45
- bubbles[row][col] = {
46
- id: `${row}-${col}`,
47
- row,
48
- col,
49
- x,
50
- y,
51
- isPopped: false,
52
- color: this.getRainbowColorForPosition(row, gridSize),
53
- animationProgress: 0
54
- };
55
- }
56
- }
57
- return {
58
- size: gridSize,
59
- bubbles,
60
- centerX: gridWidth / 2,
61
- centerY: gridHeight / 2,
62
- width: gridWidth,
63
- height: gridHeight
64
- };
65
- }
66
-
67
- // Get rainbow gradient color based on row position for authentic Pop It look
68
- getRainbowColorForPosition(row, totalRows) {
69
- // Create rainbow gradient effect like real Pop It fidget toys
70
- const colorIndex = Math.floor(row / totalRows * RAINBOW_COLORS.length);
71
- return RAINBOW_COLORS[colorIndex] || RAINBOW_COLORS[0];
72
- }
73
-
74
- // Check if all bubbles are popped
75
- checkAllBubblesPopped(grid) {
76
- for (let row = 0; row < grid.size; row++) {
77
- for (let col = 0; col < grid.size; col++) {
78
- const bubble = grid.bubbles[row]?.[col];
79
- if (bubble && !bubble.isPopped) {
80
- return false;
81
- }
82
- }
83
- }
84
- return true;
85
- }
86
-
87
- // Calculate completion percentage
88
- calculateCompletionPercentage(grid) {
89
- let totalBubbles = 0;
90
- let poppedBubbles = 0;
91
- for (let row = 0; row < grid.size; row++) {
92
- for (let col = 0; col < grid.size; col++) {
93
- const bubble = grid.bubbles[row]?.[col];
94
- if (bubble) {
95
- totalBubbles++;
96
- if (bubble.isPopped) {
97
- poppedBubbles++;
98
- }
99
- }
100
- }
101
- }
102
- return totalBubbles > 0 ? poppedBubbles / totalBubbles * 100 : 0;
103
- }
104
-
105
- // Start game timer
106
- startGameTimer(duration, onTick, onComplete) {
107
- this.stopGameTimer();
108
- let timeLeft = duration;
109
- this.gameTimerRef = setInterval(() => {
110
- timeLeft -= 1;
111
- onTick(timeLeft);
112
- if (timeLeft <= 0) {
113
- this.stopGameTimer();
114
- onComplete();
115
- }
116
- }, 1000);
117
- }
118
-
119
- // Stop game timer
120
- stopGameTimer() {
121
- if (this.gameTimerRef) {
122
- clearInterval(this.gameTimerRef);
123
- this.gameTimerRef = null;
124
- }
125
- }
126
-
127
- // Cleanup
128
- cleanup() {
129
- this.stopGameTimer();
130
- }
131
- }
132
- //# sourceMappingURL=PopitFidgetService.js.map
1
+ "use strict";import{Dimensions}from 'react-native';import{POPIT_FIDGET_GAME_CONFIG as GAME_CONFIG,POPIT_FIDGET_ANIMATION_CONFIG as ANIMATION_CONFIG,POPIT_FIDGET_COLORS as COLORS,RAINBOW_COLORS,BUBBLE_COLORS}from "./PopitFidgetConstants.js";const{width,height}= Dimensions.get('window');export{GAME_CONFIG,ANIMATION_CONFIG,COLORS,BUBBLE_COLORS};export class PopitFidgetService{gameTimerRef = null;constructor(){}generateFidgetGrid(difficulty){const availableWidth = width * 0.85;const availableHeight = height * 0.6;const gridSize = GAME_CONFIG.GRID_SIZES[difficulty];const maxSize = Math.min(availableWidth / gridSize,availableHeight / gridSize);const bubbleSize = Math.max(45,Math.min(80,maxSize * 0.9));const spacing = bubbleSize * 1.1;const gridWidth =(gridSize - 1)* spacing + bubbleSize;const gridHeight =(gridSize - 1)* spacing + bubbleSize;const bubbles = [];for(let row = 0;row < gridSize;row++){bubbles[row] = [];for(let col = 0;col < gridSize;col++){const x = col * spacing + bubbleSize / 2;const y = row * spacing + bubbleSize / 2;bubbles[row][col] ={id:`${row}-${col}`,row,col,x,y,isPopped:false,color:this.getRainbowColorForPosition(row,gridSize),animationProgress:0};}}return{size:gridSize,bubbles,centerX:gridWidth / 2,centerY:gridHeight / 2,width:gridWidth,height:gridHeight};}getRainbowColorForPosition(row,totalRows){const colorIndex = Math.floor(row / totalRows * RAINBOW_COLORS.length);return RAINBOW_COLORS[colorIndex] || RAINBOW_COLORS[0];}checkAllBubblesPopped(grid){for(let row = 0;row < grid.size;row++){for(let col = 0;col < grid.size;col++){const bubble = grid.bubbles[row]?.[col];if(bubble && !bubble.isPopped){return false;}}}return true;}calculateCompletionPercentage(grid){let totalBubbles = 0;let poppedBubbles = 0;for(let row = 0;row < grid.size;row++){for(let col = 0;col < grid.size;col++){const bubble = grid.bubbles[row]?.[col];if(bubble){totalBubbles++;if(bubble.isPopped){poppedBubbles++;}}}}return totalBubbles > 0 ? poppedBubbles / totalBubbles * 100:0;}startGameTimer(duration,onTick,onComplete){this.stopGameTimer();let timeLeft = duration;this.gameTimerRef = setInterval(()=>{timeLeft -= 1;onTick(timeLeft);if(timeLeft <= 0){this.stopGameTimer();onComplete();}},1000);}stopGameTimer(){if(this.gameTimerRef){clearInterval(this.gameTimerRef);this.gameTimerRef = null;}}cleanup(){this.stopGameTimer();}}
@@ -1,125 +1 @@
1
- "use strict";
2
-
3
- import { create } from 'zustand';
4
- import { subscribeWithSelector } from 'zustand/middleware';
5
- import { immerMiddleware } from "../../services/UtilsService.js";
6
- // Optimized store with selective subscriptions for low-end devices
7
- export const usePopitFidgetStore = create()(subscribeWithSelector(immerMiddleware((set, get) => ({
8
- // Initial state
9
- timeElapsed: 0,
10
- isPlaying: false,
11
- gameOver: false,
12
- gameWon: false,
13
- fidgetGrid: null,
14
- bubblesPopped: 0,
15
- totalBubbles: 0,
16
- bubbleStates: {},
17
- // Actions
18
- startGame: _gameDuration => {
19
- set(draft => {
20
- draft.isPlaying = true;
21
- draft.gameOver = false;
22
- draft.gameWon = false;
23
- draft.timeElapsed = 0;
24
- draft.bubblesPopped = 0;
25
- });
26
- },
27
- stopGame: () => {
28
- set(draft => {
29
- draft.isPlaying = false;
30
- draft.gameOver = true;
31
- });
32
- },
33
- resetGame: () => {
34
- set(draft => {
35
- draft.timeElapsed = 0;
36
- draft.isPlaying = false;
37
- draft.gameOver = false;
38
- draft.gameWon = false;
39
- draft.fidgetGrid = null;
40
- draft.bubblesPopped = 0;
41
- draft.totalBubbles = 0;
42
- });
43
- },
44
- setFidgetGrid: grid => {
45
- // For square grids, total bubbles = size * size
46
- const totalCount = grid.size * grid.size;
47
- set(draft => {
48
- draft.fidgetGrid = grid;
49
- draft.totalBubbles = totalCount;
50
- draft.bubblesPopped = 0;
51
-
52
- // Initialize bubble states for all bubbles
53
- draft.bubbleStates = {};
54
- for (let row = 0; row < grid.size; row++) {
55
- for (let col = 0; col < grid.size; col++) {
56
- const bubble = grid.bubbles[row]?.[col];
57
- if (bubble) {
58
- draft.bubbleStates[bubble.id] = {
59
- isPopped: bubble.isPopped || false,
60
- popTime: bubble.popTime
61
- };
62
- }
63
- }
64
- }
65
- });
66
- },
67
- popBubble: (row, col) => {
68
- set(draft => {
69
- if (!draft.fidgetGrid) return;
70
- const bubble = draft.fidgetGrid.bubbles[row]?.[col];
71
- if (!bubble) return;
72
-
73
- // Check if bubble is already popped using bubbleStates
74
- const bubbleState = draft.bubbleStates[bubble.id];
75
- if (bubbleState?.isPopped) return;
76
-
77
- // Update only the bubbleStates, not the fidgetGrid
78
- // This prevents the entire fidgetGrid array from changing references
79
- draft.bubbleStates[bubble.id] = {
80
- isPopped: true,
81
- popTime: Date.now()
82
- };
83
- draft.bubblesPopped = draft.bubblesPopped + 1;
84
- });
85
-
86
- // Check if game is won (only if actively playing)
87
- const state = get();
88
- if (state.isPlaying) {
89
- get().checkGameWon();
90
- }
91
- },
92
- incrementTime: () => {
93
- set(draft => {
94
- draft.timeElapsed = draft.timeElapsed + 1;
95
- });
96
- },
97
- checkGameWon: () => {
98
- const state = get();
99
- if (!state.fidgetGrid) return;
100
-
101
- // Check if all bubbles are popped using bubbleStates
102
- let allPopped = true;
103
- for (let row = 0; row < state.fidgetGrid.size; row++) {
104
- for (let col = 0; col < state.fidgetGrid.size; col++) {
105
- const bubble = state.fidgetGrid.bubbles[row]?.[col];
106
- if (bubble) {
107
- const bubbleState = state.bubbleStates[bubble.id];
108
- if (!bubbleState?.isPopped) {
109
- allPopped = false;
110
- break;
111
- }
112
- }
113
- }
114
- if (!allPopped) break;
115
- }
116
- if (allPopped && state.isPlaying) {
117
- set(draft => {
118
- draft.isPlaying = false;
119
- draft.gameWon = true;
120
- draft.gameOver = true;
121
- });
122
- }
123
- }
124
- }))));
125
- //# sourceMappingURL=PopitFidgetStore.js.map
1
+ "use strict";import{create}from 'zustand';import{subscribeWithSelector}from 'zustand/middleware';import{immerMiddleware}from "../../services/UtilsService.js";export const usePopitFidgetStore = create()(subscribeWithSelector(immerMiddleware((set,get)=>({timeElapsed:0,isPlaying:false,gameOver:false,gameWon:false,fidgetGrid:null,bubblesPopped:0,totalBubbles:0,bubbleStates:{},startGame:_gameDuration =>{set(draft =>{draft.isPlaying = true;draft.gameOver = false;draft.gameWon = false;draft.timeElapsed = 0;draft.bubblesPopped = 0;});},stopGame:()=>{set(draft =>{draft.isPlaying = false;draft.gameOver = true;});},resetGame:()=>{set(draft =>{draft.timeElapsed = 0;draft.isPlaying = false;draft.gameOver = false;draft.gameWon = false;draft.fidgetGrid = null;draft.bubblesPopped = 0;draft.totalBubbles = 0;});},setFidgetGrid:grid =>{const totalCount = grid.size * grid.size;set(draft =>{draft.fidgetGrid = grid;draft.totalBubbles = totalCount;draft.bubblesPopped = 0;draft.bubbleStates ={};for(let row = 0;row < grid.size;row++){for(let col = 0;col < grid.size;col++){const bubble = grid.bubbles[row]?.[col];if(bubble){draft.bubbleStates[bubble.id] ={isPopped:bubble.isPopped || false,popTime:bubble.popTime};}}}});},popBubble:(row,col)=>{set(draft =>{if(!draft.fidgetGrid)return;const bubble = draft.fidgetGrid.bubbles[row]?.[col];if(!bubble)return;const bubbleState = draft.bubbleStates[bubble.id];if(bubbleState?.isPopped)return;draft.bubbleStates[bubble.id] ={isPopped:true,popTime:Date.now()};draft.bubblesPopped = draft.bubblesPopped + 1;});const state = get();if(state.isPlaying){get().checkGameWon();}},incrementTime:()=>{set(draft =>{draft.timeElapsed = draft.timeElapsed + 1;});},checkGameWon:()=>{const state = get();if(!state.fidgetGrid)return;let allPopped = true;for(let row = 0;row < state.fidgetGrid.size;row++){for(let col = 0;col < state.fidgetGrid.size;col++){const bubble = state.fidgetGrid.bubbles[row]?.[col];if(bubble){const bubbleState = state.bubbleStates[bubble.id];if(!bubbleState?.isPopped){allPopped = false;break;}}}if(!allPopped)break;}if(allPopped && state.isPlaying){set(draft =>{draft.isPlaying = false;draft.gameWon = true;draft.gameOver = true;});}}}))));
@@ -1,198 +1 @@
1
- "use strict";
2
-
3
- import React, { useState, useCallback, useMemo } from 'react';
4
- import { View, TouchableOpacity } from 'react-native';
5
- import { Canvas, Circle, LinearGradient, vec, Shadow } from '@shopify/react-native-skia';
6
- import { playHaptic, HapticType } from "../../../services/HapticsService.js";
7
- import { usePopitFidgetStore } from "../PopitFidgetStore.js";
8
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
9
- const BubbleComponent = ({
10
- bubble,
11
- size,
12
- onPop,
13
- hapticEnabled = true,
14
- isPlaying
15
- }) => {
16
- // Get bubble state from store to prevent re-renders when other bubbles change
17
- const bubbleState = usePopitFidgetStore(state => state.bubbleStates[bubble.id]);
18
- const isPopped = bubbleState?.isPopped || false;
19
- // Simple state for press feedback - no animations to prevent crashes
20
- const [isPressed, setIsPressed] = useState(false);
21
-
22
- // Memoize callbacks to prevent unnecessary re-renders
23
- const handlePop = useCallback(() => {
24
- // Only allow popping when game is actively playing
25
- if (!isPlaying || isPopped) return;
26
-
27
- // Enhanced haptic feedback - stronger for more satisfaction
28
- playHaptic(HapticType.MEDIUM, hapticEnabled || false);
29
-
30
- // Trigger pop callback
31
- onPop();
32
- }, [onPop, hapticEnabled, isPlaying, isPopped]);
33
- const handlePressIn = useCallback(() => {
34
- if (!isPopped && isPlaying) {
35
- setIsPressed(true);
36
- // Haptic feedback on press
37
- playHaptic(HapticType.LIGHT, hapticEnabled || false);
38
- }
39
- }, [isPopped, isPlaying, hapticEnabled]);
40
- const handlePressOut = useCallback(() => {
41
- setIsPressed(false);
42
- }, []);
43
-
44
- // Memoize bubble style to prevent recalculation
45
- const bubbleStyle = useMemo(() => ({
46
- position: 'absolute',
47
- left: bubble.x - size / 2,
48
- top: bubble.y - size / 2,
49
- width: size,
50
- height: size,
51
- transform: [{
52
- scale: isPressed ? 0.95 : 1
53
- }]
54
- }), [bubble.x, bubble.y, size, isPressed]);
55
-
56
- // Simplified popped state rendering
57
- if (isPopped) {
58
- return /*#__PURE__*/_jsx(View, {
59
- style: bubbleStyle,
60
- children: /*#__PURE__*/_jsxs(Canvas, {
61
- style: {
62
- width: size,
63
- height: size
64
- },
65
- children: [/*#__PURE__*/_jsx(Circle, {
66
- cx: size / 2,
67
- cy: size / 2,
68
- r: size / 2,
69
- color: bubble.color,
70
- children: /*#__PURE__*/_jsx(LinearGradient, {
71
- start: vec(0, 0),
72
- end: vec(size, size),
73
- colors: [`${bubble.color}60`,
74
- // Muted to show flatness
75
- `${bubble.color}40`,
76
- // More muted
77
- `${bubble.color}30` // Very muted to show depression
78
- ]
79
- })
80
- }), /*#__PURE__*/_jsx(Circle, {
81
- cx: size / 2,
82
- cy: size / 2 + 1,
83
- r: size / 2 - 6,
84
- color: bubble.color,
85
- children: /*#__PURE__*/_jsx(LinearGradient, {
86
- start: vec(size * 0.7, size * 0.7),
87
- end: vec(size * 0.3, size * 0.3),
88
- colors: ['#FFFFFF30',
89
- // Light highlight
90
- `${bubble.color}80`,
91
- // Bubble color
92
- '#00000020' // Subtle shadow
93
- ]
94
- })
95
- }), /*#__PURE__*/_jsx(Circle, {
96
- cx: size / 2 + size * 0.15,
97
- cy: size / 2 + size * 0.2,
98
- r: size * 0.06,
99
- color: "#FFFFFF",
100
- opacity: 0.6
101
- })]
102
- })
103
- });
104
- }
105
-
106
- // Simplified unpopped bubble rendering with TouchableOpacity wrapper for iOS/Android compatibility
107
- return /*#__PURE__*/_jsxs(View, {
108
- style: bubbleStyle,
109
- children: [/*#__PURE__*/_jsxs(Canvas, {
110
- style: {
111
- width: size,
112
- height: size
113
- },
114
- children: [/*#__PURE__*/_jsx(Circle, {
115
- cx: size / 2,
116
- cy: size / 2,
117
- r: size / 2,
118
- color: bubble.color,
119
- children: /*#__PURE__*/_jsx(LinearGradient, {
120
- start: vec(0, 0),
121
- end: vec(size, size),
122
- colors: [`${bubble.color}E0`, `${bubble.color}A0`, `${bubble.color}80`]
123
- })
124
- }), /*#__PURE__*/_jsx(Circle, {
125
- cx: size / 2,
126
- cy: size / 2 + 2,
127
- r: size / 2 - 4,
128
- color: "rgba(0,0,0,0.15)"
129
- }), /*#__PURE__*/_jsxs(Circle, {
130
- cx: size / 2,
131
- cy: size / 2 - 1,
132
- r: size / 2 - 4,
133
- color: bubble.color,
134
- children: [/*#__PURE__*/_jsx(LinearGradient, {
135
- start: vec(size * 0.2, size * 0.2),
136
- end: vec(size * 0.8, size * 0.8),
137
- colors: ['#FFFFFF', '#FFFFFFA0', bubble.color, `${bubble.color}C0`, '#00000020']
138
- }), /*#__PURE__*/_jsx(Shadow, {
139
- dx: 0,
140
- dy: 3,
141
- blur: 6,
142
- color: "rgba(0,0,0,0.2)"
143
- })]
144
- }), /*#__PURE__*/_jsx(Circle, {
145
- cx: size / 2 - size * 0.15,
146
- cy: size / 2 - size * 0.2,
147
- r: size * 0.12,
148
- color: "#FFFFFF",
149
- opacity: 0.8,
150
- children: /*#__PURE__*/_jsx(LinearGradient, {
151
- start: vec(0, 0),
152
- end: vec(size * 0.24, size * 0.24),
153
- colors: ['#FFFFFF', '#FFFFFF80', '#FFFFFF00']
154
- })
155
- }), /*#__PURE__*/_jsx(Circle, {
156
- cx: size / 2 + size * 0.1,
157
- cy: size / 2 - size * 0.15,
158
- r: size * 0.06,
159
- color: "#FFFFFF",
160
- opacity: 0.6
161
- })]
162
- }), /*#__PURE__*/_jsx(TouchableOpacity, {
163
- style: {
164
- position: 'absolute',
165
- top: 0,
166
- left: 0,
167
- width: size,
168
- height: size,
169
- backgroundColor: 'transparent'
170
- },
171
- onPress: handlePop,
172
- onPressIn: handlePressIn,
173
- onPressOut: handlePressOut,
174
- activeOpacity: 1,
175
- disabled: isPopped || !isPlaying,
176
- hitSlop: {
177
- top: 10,
178
- bottom: 10,
179
- left: 10,
180
- right: 10
181
- },
182
- delayPressIn: 0,
183
- delayPressOut: 0
184
- })]
185
- });
186
- };
187
-
188
- // Memoized BubbleComponent with custom comparison to prevent unnecessary re-renders
189
- // Note: We don't compare onPop function reference as it may change but functionality remains the same
190
- // Note: We don't compare bubble.isPopped as we now use store state which is subscribed individually
191
- const MemoizedBubbleComponent = /*#__PURE__*/React.memo(BubbleComponent, (prevProps, nextProps) => {
192
- return prevProps.bubble.id === nextProps.bubble.id && prevProps.bubble.x === nextProps.bubble.x && prevProps.bubble.y === nextProps.bubble.y && prevProps.bubble.color === nextProps.bubble.color && prevProps.size === nextProps.size && prevProps.hapticEnabled === nextProps.hapticEnabled && prevProps.isPlaying === nextProps.isPlaying
193
- // Removed bubble.isPopped comparison as we now use individual store subscriptions
194
- // Removed onPop comparison as function reference may change but behavior is the same
195
- ;
196
- });
197
- export default MemoizedBubbleComponent;
198
- //# sourceMappingURL=BubbleComponent.js.map
1
+ "use strict";import React,{useState,useCallback,useMemo}from 'react';import{View,TouchableOpacity}from 'react-native';import{Canvas,Circle,LinearGradient,vec,Shadow}from '@shopify/react-native-skia';import{playHaptic,HapticType}from "../../../services/HapticsService.js";import{usePopitFidgetStore}from "../PopitFidgetStore.js";import{jsx as _jsx,jsxs as _jsxs}from "react/jsx-runtime";const BubbleComponent =({bubble,size,onPop,hapticEnabled = true,isPlaying})=>{const bubbleState = usePopitFidgetStore(state => state.bubbleStates[bubble.id]);const isPopped = bubbleState?.isPopped || false;const [isPressed,setIsPressed] = useState(false);const handlePop = useCallback(()=>{if(!isPlaying || isPopped)return;playHaptic(HapticType.MEDIUM,hapticEnabled || false);onPop();},[onPop,hapticEnabled,isPlaying,isPopped]);const handlePressIn = useCallback(()=>{if(!isPopped && isPlaying){setIsPressed(true);playHaptic(HapticType.LIGHT,hapticEnabled || false);}},[isPopped,isPlaying,hapticEnabled]);const handlePressOut = useCallback(()=>{setIsPressed(false);},[]);const bubbleStyle = useMemo(()=>({position:'absolute',left:bubble.x - size / 2,top:bubble.y - size / 2,width:size,height:size,transform:[{scale:isPressed ? 0.95:1}]}),[bubble.x,bubble.y,size,isPressed]);if(isPopped){return _jsx(View,{style:bubbleStyle,children:_jsxs(Canvas,{style:{width:size,height:size},children:[_jsx(Circle,{cx:size / 2,cy:size / 2,r:size / 2,color:bubble.color,children:_jsx(LinearGradient,{start:vec(0,0),end:vec(size,size),colors:[`${bubble.color}60`,`${bubble.color}40`,`${bubble.color}30` ]})}),_jsx(Circle,{cx:size / 2,cy:size / 2 + 1,r:size / 2 - 6,color:bubble.color,children:_jsx(LinearGradient,{start:vec(size * 0.7,size * 0.7),end:vec(size * 0.3,size * 0.3),colors:['#FFFFFF30',`${bubble.color}80`,'#00000020' ]})}),_jsx(Circle,{cx:size / 2 + size * 0.15,cy:size / 2 + size * 0.2,r:size * 0.06,color:"#FFFFFF",opacity:0.6})]})});}return _jsxs(View,{style:bubbleStyle,children:[_jsxs(Canvas,{style:{width:size,height:size},children:[_jsx(Circle,{cx:size / 2,cy:size / 2,r:size / 2,color:bubble.color,children:_jsx(LinearGradient,{start:vec(0,0),end:vec(size,size),colors:[`${bubble.color}E0`,`${bubble.color}A0`,`${bubble.color}80`]})}),_jsx(Circle,{cx:size / 2,cy:size / 2 + 2,r:size / 2 - 4,color:"rgba(0,0,0,0.15)"}),_jsxs(Circle,{cx:size / 2,cy:size / 2 - 1,r:size / 2 - 4,color:bubble.color,children:[_jsx(LinearGradient,{start:vec(size * 0.2,size * 0.2),end:vec(size * 0.8,size * 0.8),colors:['#FFFFFF','#FFFFFFA0',bubble.color,`${bubble.color}C0`,'#00000020']}),_jsx(Shadow,{dx:0,dy:3,blur:6,color:"rgba(0,0,0,0.2)"})]}),_jsx(Circle,{cx:size / 2 - size * 0.15,cy:size / 2 - size * 0.2,r:size * 0.12,color:"#FFFFFF",opacity:0.8,children:_jsx(LinearGradient,{start:vec(0,0),end:vec(size * 0.24,size * 0.24),colors:['#FFFFFF','#FFFFFF80','#FFFFFF00']})}),_jsx(Circle,{cx:size / 2 + size * 0.1,cy:size / 2 - size * 0.15,r:size * 0.06,color:"#FFFFFF",opacity:0.6})]}),_jsx(TouchableOpacity,{style:{position:'absolute',top:0,left:0,width:size,height:size,backgroundColor:'transparent'},onPress:handlePop,onPressIn:handlePressIn,onPressOut:handlePressOut,activeOpacity:1,disabled:isPopped || !isPlaying,hitSlop:{top:10,bottom:10,left:10,right:10},delayPressIn:0,delayPressOut:0})]});};const MemoizedBubbleComponent = React.memo(BubbleComponent,(prevProps,nextProps)=>{return prevProps.bubble.id === nextProps.bubble.id && prevProps.bubble.x === nextProps.bubble.x && prevProps.bubble.y === nextProps.bubble.y && prevProps.bubble.color === nextProps.bubble.color && prevProps.size === nextProps.size && prevProps.hapticEnabled === nextProps.hapticEnabled && prevProps.isPlaying === nextProps.isPlaying;});export default MemoizedBubbleComponent;
@@ -1,165 +1 @@
1
- "use strict";
2
-
3
- import React, { useMemo, useCallback } from 'react';
4
- import { View, StyleSheet } from 'react-native';
5
- import { RAINBOW_COLORS } from "../PopitFidgetConstants.js";
6
- import BubbleComponent from "./BubbleComponent.js";
7
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
8
- const FidgetGrid = ({
9
- grid,
10
- bubbleSize,
11
- onBubblePop,
12
- hapticEnabled = true,
13
- isPlaying
14
- }) => {
15
- const padding = 20;
16
-
17
- // Memoize row color calculation to prevent recalculation
18
- const getRowColor = useCallback(rowIndex => {
19
- const colorIndex = Math.floor(rowIndex / (grid.size - 1) * (RAINBOW_COLORS.length - 1));
20
- return RAINBOW_COLORS[colorIndex] || RAINBOW_COLORS[0];
21
- }, [grid.size]);
22
-
23
- // Memoize container dimensions to prevent recalculation
24
- const containerDimensions = useMemo(() => ({
25
- width: grid.width + padding * 2,
26
- height: grid.height + padding * 2
27
- }), [grid.width, grid.height, padding]);
28
-
29
- // Memoize bubble pop handlers using a stable reference pattern
30
- const bubblePopHandlers = useMemo(() => {
31
- const handlers = {};
32
- grid.bubbles.forEach((row, rowIndex) => {
33
- row.forEach((bubble, colIndex) => {
34
- if (bubble) {
35
- handlers[bubble.id] = () => onBubblePop(rowIndex, colIndex);
36
- }
37
- });
38
- });
39
- return handlers;
40
- }, [grid.bubbles, onBubblePop]);
41
- return /*#__PURE__*/_jsxs(View, {
42
- style: [styles.container, containerDimensions],
43
- children: [/*#__PURE__*/_jsxs(View, {
44
- style: [styles.backgroundContainer, styles.fidget3D, {
45
- ...containerDimensions,
46
- borderRadius: 20,
47
- overflow: 'hidden'
48
- }],
49
- children: [/*#__PURE__*/_jsx(View, {
50
- style: [styles.outerBorder, {
51
- ...containerDimensions,
52
- borderRadius: 20
53
- }]
54
- }), /*#__PURE__*/_jsx(View, {
55
- style: [styles.innerRecess, {
56
- position: 'absolute',
57
- left: 8,
58
- top: 8,
59
- width: containerDimensions.width - 16,
60
- height: containerDimensions.height - 16,
61
- borderRadius: 12,
62
- overflow: 'hidden'
63
- }],
64
- children: grid.bubbles.map((_, rowIndex) => {
65
- const rowHeight = grid.height / grid.size;
66
- const rowColor = getRowColor(rowIndex);
67
- return /*#__PURE__*/_jsx(View, {
68
- style: {
69
- position: 'absolute',
70
- left: padding - 8,
71
- top: padding - 8 + rowIndex * rowHeight,
72
- width: grid.width,
73
- height: rowHeight,
74
- backgroundColor: `${rowColor}50`
75
- }
76
- }, `row-bg-${rowIndex}`);
77
- })
78
- })]
79
- }), /*#__PURE__*/_jsx(View, {
80
- style: {
81
- position: 'absolute',
82
- left: padding,
83
- top: padding
84
- },
85
- children: grid.bubbles.map((row, _rowIndex) => row.map((bubble, _colIndex) => {
86
- if (!bubble) return null;
87
- const bubbleHandler = bubblePopHandlers[bubble.id];
88
- if (!bubbleHandler) return null;
89
- return /*#__PURE__*/_jsx(BubbleComponent, {
90
- bubble: bubble,
91
- size: bubbleSize,
92
- onPop: bubbleHandler,
93
- hapticEnabled: hapticEnabled,
94
- isPlaying: isPlaying
95
- }, bubble.id);
96
- }))
97
- })]
98
- });
99
- };
100
- const styles = StyleSheet.create({
101
- container: {
102
- position: 'relative',
103
- padding: 15
104
- // Removed flex: 1 since we now use explicit width/height
105
- // The parent gameArea container handles centering
106
- },
107
- backgroundContainer: {
108
- position: 'absolute'
109
- },
110
- fidget3D: {
111
- // Deep shadow for authentic Pop It depth
112
- shadowColor: '#000',
113
- shadowOffset: {
114
- width: 0,
115
- height: 8
116
- },
117
- shadowOpacity: 0.4,
118
- shadowRadius: 12,
119
- elevation: 12
120
- },
121
- outerBorder: {
122
- position: 'absolute',
123
- backgroundColor: '#f0f0f0',
124
- // Raised border gradient effect using multiple borders
125
- borderWidth: 2,
126
- borderTopColor: '#ffffff',
127
- borderLeftColor: '#ffffff',
128
- borderRightColor: '#cccccc',
129
- borderBottomColor: '#aaaaaa'
130
- },
131
- innerRecess: {
132
- backgroundColor: '#e8e8e8',
133
- // Recessed inner area with inverted lighting
134
- borderWidth: 1,
135
- borderTopColor: '#cccccc',
136
- borderLeftColor: '#cccccc',
137
- borderRightColor: '#ffffff',
138
- borderBottomColor: '#ffffff',
139
- // Inner shadow effect
140
- shadowColor: '#000',
141
- shadowOffset: {
142
- width: 0,
143
- height: -2
144
- },
145
- shadowOpacity: 0.2,
146
- shadowRadius: 4,
147
- elevation: -2
148
- }
149
- });
150
-
151
- // Memoized FidgetGrid component to prevent unnecessary re-renders
152
- const MemoizedFidgetGrid = /*#__PURE__*/React.memo(FidgetGrid, (prevProps, nextProps) => {
153
- // Only re-render if grid structure, bubble states, or key props change
154
- return prevProps.grid.size === nextProps.grid.size && prevProps.grid.width === nextProps.grid.width && prevProps.grid.height === nextProps.grid.height && prevProps.bubbleSize === nextProps.bubbleSize && prevProps.hapticEnabled === nextProps.hapticEnabled && prevProps.isPlaying === nextProps.isPlaying && prevProps.onBubblePop === nextProps.onBubblePop &&
155
- // Check if bubble states have changed
156
- JSON.stringify(prevProps.grid.bubbles.map(row => row.map(bubble => bubble ? {
157
- id: bubble.id,
158
- isPopped: bubble.isPopped
159
- } : null))) === JSON.stringify(nextProps.grid.bubbles.map(row => row.map(bubble => bubble ? {
160
- id: bubble.id,
161
- isPopped: bubble.isPopped
162
- } : null)));
163
- });
164
- export default MemoizedFidgetGrid;
165
- //# sourceMappingURL=FidgetGrid.js.map
1
+ "use strict";import React,{useMemo,useCallback}from 'react';import{View,StyleSheet}from 'react-native';import{RAINBOW_COLORS}from "../PopitFidgetConstants.js";import BubbleComponent from "./BubbleComponent.js";import{jsx as _jsx,jsxs as _jsxs}from "react/jsx-runtime";const FidgetGrid =({grid,bubbleSize,onBubblePop,hapticEnabled = true,isPlaying})=>{const padding = 20;const getRowColor = useCallback(rowIndex =>{const colorIndex = Math.floor(rowIndex /(grid.size - 1)*(RAINBOW_COLORS.length - 1));return RAINBOW_COLORS[colorIndex] || RAINBOW_COLORS[0];},[grid.size]);const containerDimensions = useMemo(()=>({width:grid.width + padding * 2,height:grid.height + padding * 2}),[grid.width,grid.height,padding]);const bubblePopHandlers = useMemo(()=>{const handlers ={};grid.bubbles.forEach((row,rowIndex)=>{row.forEach((bubble,colIndex)=>{if(bubble){handlers[bubble.id] =()=> onBubblePop(rowIndex,colIndex);}});});return handlers;},[grid.bubbles,onBubblePop]);return _jsxs(View,{style:[styles.container,containerDimensions],children:[_jsxs(View,{style:[styles.backgroundContainer,styles.fidget3D,{...containerDimensions,borderRadius:20,overflow:'hidden'}],children:[_jsx(View,{style:[styles.outerBorder,{...containerDimensions,borderRadius:20}]}),_jsx(View,{style:[styles.innerRecess,{position:'absolute',left:8,top:8,width:containerDimensions.width - 16,height:containerDimensions.height - 16,borderRadius:12,overflow:'hidden'}],children:grid.bubbles.map((_,rowIndex)=>{const rowHeight = grid.height / grid.size;const rowColor = getRowColor(rowIndex);return _jsx(View,{style:{position:'absolute',left:padding - 8,top:padding - 8 + rowIndex * rowHeight,width:grid.width,height:rowHeight,backgroundColor:`${rowColor}50`}},`row-bg-${rowIndex}`);})})]}),_jsx(View,{style:{position:'absolute',left:padding,top:padding},children:grid.bubbles.map((row,_rowIndex)=> row.map((bubble,_colIndex)=>{if(!bubble)return null;const bubbleHandler = bubblePopHandlers[bubble.id];if(!bubbleHandler)return null;return _jsx(BubbleComponent,{bubble:bubble,size:bubbleSize,onPop:bubbleHandler,hapticEnabled:hapticEnabled,isPlaying:isPlaying},bubble.id);}))})]});};const styles = StyleSheet.create({container:{position:'relative',padding:15},backgroundContainer:{position:'absolute'},fidget3D:{shadowColor:'#000',shadowOffset:{width:0,height:8},shadowOpacity:0.4,shadowRadius:12,elevation:12},outerBorder:{position:'absolute',backgroundColor:'#f0f0f0',borderWidth:2,borderTopColor:'#ffffff',borderLeftColor:'#ffffff',borderRightColor:'#cccccc',borderBottomColor:'#aaaaaa'},innerRecess:{backgroundColor:'#e8e8e8',borderWidth:1,borderTopColor:'#cccccc',borderLeftColor:'#cccccc',borderRightColor:'#ffffff',borderBottomColor:'#ffffff',shadowColor:'#000',shadowOffset:{width:0,height:-2},shadowOpacity:0.2,shadowRadius:4,elevation:-2}});const MemoizedFidgetGrid = React.memo(FidgetGrid,(prevProps,nextProps)=>{return prevProps.grid.size === nextProps.grid.size && prevProps.grid.width === nextProps.grid.width && prevProps.grid.height === nextProps.grid.height && prevProps.bubbleSize === nextProps.bubbleSize && prevProps.hapticEnabled === nextProps.hapticEnabled && prevProps.isPlaying === nextProps.isPlaying && prevProps.onBubblePop === nextProps.onBubblePop && JSON.stringify(prevProps.grid.bubbles.map(row => row.map(bubble => bubble ?{id:bubble.id,isPopped:bubble.isPopped}:null)))=== JSON.stringify(nextProps.grid.bubbles.map(row => row.map(bubble => bubble ?{id:bubble.id,isPopped:bubble.isPopped}:null)));});export default MemoizedFidgetGrid;