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.
- package/README.md +58 -7
- package/lib/module/games/balloon-blaster/BalloonBlaster.js +1 -167
- package/lib/module/games/balloon-blaster/BalloonBlaster.js.map +1 -1
- package/lib/module/games/balloon-blaster/BalloonBlasterConstants.js +1 -182
- package/lib/module/games/balloon-blaster/BalloonBlasterConstants.js.map +1 -1
- package/lib/module/games/balloon-blaster/BalloonBlasterService.js +1 -318
- package/lib/module/games/balloon-blaster/BalloonBlasterStore.js +1 -183
- package/lib/module/games/balloon-blaster/components/BalloonComponent.js +1 -237
- package/lib/module/games/balloon-blaster/components/GameArea.js +1 -156
- package/lib/module/games/balloon-blaster/components/GameBackground.js +1 -476
- package/lib/module/games/balloon-blaster/components/ScoreBoard.js +1 -112
- package/lib/module/games/balloon-blaster/components/ScoreBoard.js.map +1 -1
- package/lib/module/games/balloon-blaster/components/index.js +1 -7
- package/lib/module/games/candy-crush/CandyCrush.js +1 -131
- package/lib/module/games/candy-crush/CandyCrush.js.map +1 -1
- package/lib/module/games/candy-crush/CandyCrushConstants.js +1 -125
- package/lib/module/games/candy-crush/CandyCrushConstants.js.map +1 -1
- package/lib/module/games/candy-crush/CandyCrushService.js +1 -370
- package/lib/module/games/candy-crush/CandyCrushStore.js +1 -303
- package/lib/module/games/candy-crush/components/CandyItem.js +1 -191
- package/lib/module/games/candy-crush/components/GameBackground.js +1 -85
- package/lib/module/games/candy-crush/components/GameGrid.js +1 -314
- package/lib/module/games/candy-crush/components/ScoreBoard.js +1 -79
- package/lib/module/games/candy-crush/components/index.js +1 -7
- package/lib/module/games/candy-crush/index.js +1 -6
- package/lib/module/games/colors-sort/ColorsSort.js +1 -143
- package/lib/module/games/colors-sort/ColorsSort.js.map +1 -1
- package/lib/module/games/colors-sort/ColorsSortConstants.js +1 -72
- package/lib/module/games/colors-sort/ColorsSortConstants.js.map +1 -1
- package/lib/module/games/colors-sort/ColorsSortService.js +1 -255
- package/lib/module/games/colors-sort/ColorsSortStore.js +1 -257
- package/lib/module/games/colors-sort/ColorsSortStore.js.map +1 -1
- package/lib/module/games/colors-sort/components/ColorContainer.js +1 -140
- package/lib/module/games/colors-sort/components/GameBackground.js +1 -135
- package/lib/module/games/colors-sort/components/ScoreBoard.js +1 -70
- package/lib/module/games/colors-sort/components/index.js +1 -6
- package/lib/module/games/dino-jump/DinoJump.js +1 -209
- package/lib/module/games/dino-jump/DinoJump.js.map +1 -1
- package/lib/module/games/dino-jump/DinoJumpConstants.js +1 -189
- package/lib/module/games/dino-jump/DinoJumpConstants.js.map +1 -1
- package/lib/module/games/dino-jump/DinoJumpService.js +1 -270
- package/lib/module/games/dino-jump/DinoJumpStore.js +1 -381
- package/lib/module/games/dino-jump/components/DinoSprite.js +1 -418
- package/lib/module/games/dino-jump/components/DinoSprite.js.map +1 -1
- package/lib/module/games/dino-jump/components/GameArea.js +1 -68
- package/lib/module/games/dino-jump/components/GameBackground.js +1 -444
- package/lib/module/games/dino-jump/components/ObstacleSprite.js +1 -306
- package/lib/module/games/dino-jump/components/ScoreBoard.js +1 -105
- package/lib/module/games/dino-jump/components/ScoreBoard.js.map +1 -1
- package/lib/module/games/dino-jump/components/StarSprite.js +1 -45
- package/lib/module/games/dino-jump/components/index.js +1 -9
- package/lib/module/games/flappy-bird/FlappyBird.js +1 -126
- package/lib/module/games/flappy-bird/FlappyBird.js.map +1 -1
- package/lib/module/games/flappy-bird/FlappyBirdConstants.js +1 -90
- package/lib/module/games/flappy-bird/FlappyBirdConstants.js.map +1 -1
- package/lib/module/games/flappy-bird/FlappyBirdStore.js +1 -300
- package/lib/module/games/flappy-bird/components/Bird.js +1 -87
- package/lib/module/games/flappy-bird/components/GameArea.js +1 -87
- package/lib/module/games/flappy-bird/components/GameBackground.js +1 -79
- package/lib/module/games/flappy-bird/components/Pipes.js +1 -172
- package/lib/module/games/flappy-bird/components/ScoreBoard.js +1 -73
- package/lib/module/games/flappy-bird/components/index.js +1 -8
- package/lib/module/games/fruit-merger/FruitMerger.js +1 -120
- package/lib/module/games/fruit-merger/FruitMerger.js.map +1 -1
- package/lib/module/games/fruit-merger/FruitMergerConstants.js +1 -119
- package/lib/module/games/fruit-merger/FruitMergerConstants.js.map +1 -1
- package/lib/module/games/fruit-merger/FruitMergerService.js +1 -13
- package/lib/module/games/fruit-merger/FruitMergerStore.js +1 -315
- package/lib/module/games/fruit-merger/components/FruitItem.js +1 -102
- package/lib/module/games/fruit-merger/components/GameArea.js +1 -103
- package/lib/module/games/fruit-merger/components/GameBackground.js +1 -498
- package/lib/module/games/fruit-merger/components/ScoreBoard.js +1 -58
- package/lib/module/games/fruit-merger/components/index.js +1 -7
- package/lib/module/games/fruit-ninja/FruitNinja.js +1 -134
- package/lib/module/games/fruit-ninja/FruitNinja.js.map +1 -1
- package/lib/module/games/fruit-ninja/FruitNinjaConstants.js +1 -148
- package/lib/module/games/fruit-ninja/FruitNinjaConstants.js.map +1 -1
- package/lib/module/games/fruit-ninja/FruitNinjaService.js +1 -311
- package/lib/module/games/fruit-ninja/FruitNinjaStore.js +1 -191
- package/lib/module/games/fruit-ninja/FruitNinjaStore.js.map +1 -1
- package/lib/module/games/fruit-ninja/components/FruitComponent.js +1 -99
- package/lib/module/games/fruit-ninja/components/GameArea.js +1 -215
- package/lib/module/games/fruit-ninja/components/GameBackground.js +1 -1267
- package/lib/module/games/fruit-ninja/components/ScoreBoard.js +1 -92
- package/lib/module/games/fruit-ninja/components/ScoreBoard.js.map +1 -1
- package/lib/module/games/fruit-ninja/components/index.js +1 -7
- package/lib/module/games/game-2048/Game2048.js +1 -149
- package/lib/module/games/game-2048/Game2048.js.map +1 -1
- package/lib/module/games/game-2048/Game2048Constants.js +1 -263
- package/lib/module/games/game-2048/Game2048Constants.js.map +1 -1
- package/lib/module/games/game-2048/Game2048Service.js +1 -457
- package/lib/module/games/game-2048/Game2048Store.js +1 -236
- package/lib/module/games/game-2048/components/GameBackground.js +1 -247
- package/lib/module/games/game-2048/components/GameGrid.js +1 -139
- package/lib/module/games/game-2048/components/GameTile.js +1 -72
- package/lib/module/games/game-2048/components/ScoreBoard.js +1 -52
- package/lib/module/games/game-2048/components/index.js +1 -7
- package/lib/module/games/maze-runner/MazeRunner.js +1 -267
- package/lib/module/games/maze-runner/MazeRunner.js.map +1 -1
- package/lib/module/games/maze-runner/MazeRunnerConstants.js +1 -100
- package/lib/module/games/maze-runner/MazeRunnerConstants.js.map +1 -1
- package/lib/module/games/maze-runner/MazeRunnerService.js +1 -586
- package/lib/module/games/maze-runner/components/EnhancedBallComponent.js +1 -150
- package/lib/module/games/maze-runner/components/EnhancedGameArea.js +1 -370
- package/lib/module/games/maze-runner/components/GameBackground.js +1 -175
- package/lib/module/games/maze-runner/components/ScoreBoard.js +1 -61
- package/lib/module/games/maze-runner/components/SkiaPipeComponent.js +1 -209
- package/lib/module/games/maze-runner/components/StaticGameBackground.js +1 -169
- package/lib/module/games/maze-runner/components/WallComponent.js +1 -91
- package/lib/module/games/maze-runner/components/index.js +1 -8
- package/lib/module/games/popit-fidget/PopitFidget.js +1 -285
- package/lib/module/games/popit-fidget/PopitFidget.js.map +1 -1
- package/lib/module/games/popit-fidget/PopitFidgetConstants.js +1 -113
- package/lib/module/games/popit-fidget/PopitFidgetConstants.js.map +1 -1
- package/lib/module/games/popit-fidget/PopitFidgetService.js +1 -132
- package/lib/module/games/popit-fidget/PopitFidgetStore.js +1 -125
- package/lib/module/games/popit-fidget/components/BubbleComponent.js +1 -198
- package/lib/module/games/popit-fidget/components/FidgetGrid.js +1 -165
- package/lib/module/games/popit-fidget/components/GameBackground.js +1 -177
- package/lib/module/games/popit-fidget/components/ScoreBoard.js +1 -61
- package/lib/module/games/popit-fidget/components/index.js +1 -7
- package/lib/module/games/sliding-numbers/SlidingNumbers.js +1 -159
- package/lib/module/games/sliding-numbers/SlidingNumbers.js.map +1 -1
- package/lib/module/games/sliding-numbers/SlidingNumbersConstants.js +1 -207
- package/lib/module/games/sliding-numbers/SlidingNumbersConstants.js.map +1 -1
- package/lib/module/games/sliding-numbers/SlidingNumbersService.js +1 -248
- package/lib/module/games/sliding-numbers/SlidingNumbersStore.js +1 -274
- package/lib/module/games/sliding-numbers/components/GameBackground.js +1 -259
- package/lib/module/games/sliding-numbers/components/NumbersGrid.js +1 -174
- package/lib/module/games/sliding-numbers/components/NumbersTile.js +1 -116
- package/lib/module/games/sliding-numbers/components/ScoreBoard.js +1 -64
- package/lib/module/games/sliding-numbers/components/index.js +1 -7
- package/lib/module/games/snake/Snake.js +1 -189
- package/lib/module/games/snake/Snake.js.map +1 -1
- package/lib/module/games/snake/SnakeConstants.js +1 -138
- package/lib/module/games/snake/SnakeConstants.js.map +1 -1
- package/lib/module/games/snake/SnakeService.js +1 -148
- package/lib/module/games/snake/SnakeStore.js +1 -182
- package/lib/module/games/snake/components/GameBackground.js +1 -221
- package/lib/module/games/snake/components/GameGrid.js +1 -153
- package/lib/module/games/snake/components/ScoreBoard.js +1 -51
- package/lib/module/games/snake/components/index.js +1 -6
- package/lib/module/games/snake/index.js +1 -6
- package/lib/module/games/space-fighter/SpaceFighter.js +1 -165
- package/lib/module/games/space-fighter/SpaceFighter.js.map +1 -1
- package/lib/module/games/space-fighter/SpaceFighterConstants.js +1 -108
- package/lib/module/games/space-fighter/SpaceFighterConstants.js.map +1 -1
- package/lib/module/games/space-fighter/SpaceFighterService.js +1 -326
- package/lib/module/games/space-fighter/SpaceFighterStore.js +1 -209
- package/lib/module/games/space-fighter/components/AsteroidComponent.js +1 -113
- package/lib/module/games/space-fighter/components/GameArea.js +1 -289
- package/lib/module/games/space-fighter/components/GameBackground.js +1 -239
- package/lib/module/games/space-fighter/components/ScoreBoard.js +1 -136
- package/lib/module/games/space-fighter/components/Spacecraft3D.js +1 -202
- package/lib/module/games/space-fighter/components/SpacecraftPath.js +1 -52
- package/lib/module/games/space-fighter/components/index.js +1 -9
- package/lib/module/games/whack-a-mole/WhackAMole.js +1 -270
- package/lib/module/games/whack-a-mole/WhackAMole.js.map +1 -1
- package/lib/module/games/whack-a-mole/WhackAMoleConstants.js +1 -115
- package/lib/module/games/whack-a-mole/WhackAMoleConstants.js.map +1 -1
- package/lib/module/games/whack-a-mole/WhackAMoleService.js +1 -120
- package/lib/module/games/whack-a-mole/WhackAMoleStore.js +1 -172
- package/lib/module/games/whack-a-mole/components/GameBackground.js +1 -477
- package/lib/module/games/whack-a-mole/components/GameGrid.js +1 -97
- package/lib/module/games/whack-a-mole/components/GameHole.js +1 -196
- package/lib/module/games/whack-a-mole/components/MoleCharacter.js +1 -241
- package/lib/module/games/whack-a-mole/components/ScoreBoard.js +1 -67
- package/lib/module/games/whack-a-mole/components/ScoreBoard.js.map +1 -1
- package/lib/module/games/whack-a-mole/components/index.js +1 -8
- package/lib/module/helpers/AnimationFrame.js +1 -120
- package/lib/module/helpers/AnimationTracker.js +1 -89
- package/lib/module/helpers/ErrorHandler.js +1 -269
- package/lib/module/helpers/GameControlButton.js +1 -219
- package/lib/module/helpers/GameOverModal.js +1 -144
- package/lib/module/helpers/GameOverModal.js.map +1 -1
- package/lib/module/helpers/GameSettingsModal.js +1 -287
- package/lib/module/helpers/ParticleBlast.js +1 -134
- package/lib/module/helpers/ScoreBoardContainer.js +1 -34
- package/lib/module/helpers/index.js +1 -12
- package/lib/module/index.js +1 -22
- package/lib/module/services/GamesConstants.js +1 -178
- package/lib/module/services/GamesService.js +1 -112
- package/lib/module/services/GamesService.js.map +1 -1
- package/lib/module/services/HapticsService.js +1 -77
- package/lib/module/services/SoundsService.js +1 -302
- package/lib/module/services/UtilsService.js +1 -32
- package/lib/typescript/src/games/balloon-blaster/BalloonBlaster.d.ts.map +1 -1
- package/lib/typescript/src/games/balloon-blaster/BalloonBlasterConstants.d.ts +1 -1
- package/lib/typescript/src/games/balloon-blaster/components/ScoreBoard.d.ts.map +1 -1
- package/lib/typescript/src/games/candy-crush/CandyCrushConstants.d.ts +7 -7
- package/lib/typescript/src/games/colors-sort/ColorsSort.d.ts.map +1 -1
- package/lib/typescript/src/games/colors-sort/ColorsSortStore.d.ts.map +1 -1
- package/lib/typescript/src/games/dino-jump/DinoJump.d.ts.map +1 -1
- package/lib/typescript/src/games/dino-jump/components/DinoSprite.d.ts.map +1 -1
- package/lib/typescript/src/games/flappy-bird/FlappyBird.d.ts.map +1 -1
- package/lib/typescript/src/games/flappy-bird/FlappyBirdConstants.d.ts.map +1 -1
- package/lib/typescript/src/games/fruit-merger/FruitMerger.d.ts.map +1 -1
- package/lib/typescript/src/games/fruit-merger/FruitMergerConstants.d.ts.map +1 -1
- package/lib/typescript/src/games/fruit-ninja/FruitNinja.d.ts.map +1 -1
- package/lib/typescript/src/games/fruit-ninja/components/ScoreBoard.d.ts.map +1 -1
- package/lib/typescript/src/games/game-2048/Game2048.d.ts.map +1 -1
- package/lib/typescript/src/games/maze-runner/MazeRunner.d.ts.map +1 -1
- package/lib/typescript/src/games/popit-fidget/PopitFidget.d.ts.map +1 -1
- package/lib/typescript/src/games/sliding-numbers/SlidingNumbers.d.ts.map +1 -1
- package/lib/typescript/src/games/space-fighter/SpaceFighter.d.ts.map +1 -1
- package/lib/typescript/src/games/whack-a-mole/WhackAMole.d.ts.map +1 -1
- package/lib/typescript/src/games/whack-a-mole/WhackAMoleConstants.d.ts +1 -1
- package/lib/typescript/src/games/whack-a-mole/components/ScoreBoard.d.ts.map +1 -1
- package/lib/typescript/src/helpers/GameOverModal.d.ts +3 -0
- package/lib/typescript/src/helpers/GameOverModal.d.ts.map +1 -1
- package/lib/typescript/src/services/GamesConstants.d.ts +7 -7
- 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;
|