react-native-games 1.0.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 +80 -368
- 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,318 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
import { Dimensions } from 'react-native';
|
|
4
|
-
import { BALLOON_BLASTER_GAME_CONFIG as GAME_CONFIG, BALLOON_BLASTER_ANIMATION_CONFIG as ANIMATION_CONFIG, BALLOON_BLASTER_COLORS as COLORS, BALLOON_TYPES, BALLOON_SPECIAL_ITEMS as SPECIAL_ITEMS } from "./BalloonBlasterConstants.js";
|
|
5
|
-
const {
|
|
6
|
-
width,
|
|
7
|
-
height
|
|
8
|
-
} = Dimensions.get('window');
|
|
9
|
-
|
|
10
|
-
// Constants now imported from BalloonBlasterConstants.ts
|
|
11
|
-
// Re-export for backward compatibility
|
|
12
|
-
export { GAME_CONFIG, ANIMATION_CONFIG, COLORS, BALLOON_TYPES, SPECIAL_ITEMS };
|
|
13
|
-
|
|
14
|
-
// Types
|
|
15
|
-
|
|
16
|
-
export class BalloonBlasterService {
|
|
17
|
-
gameTimerRef = null;
|
|
18
|
-
balloonSpawnRef = null;
|
|
19
|
-
animationRef = null;
|
|
20
|
-
comboTimeoutRef = null;
|
|
21
|
-
particles = [];
|
|
22
|
-
constructor(balloonAnimations, particleAnimations) {
|
|
23
|
-
this.balloonAnimations = balloonAnimations;
|
|
24
|
-
this.particleAnimations = particleAnimations;
|
|
25
|
-
}
|
|
26
|
-
startGameTimer(onTick) {
|
|
27
|
-
this.clearGameTimer();
|
|
28
|
-
this.gameTimerRef = setInterval(onTick, 1000);
|
|
29
|
-
}
|
|
30
|
-
startBalloonSpawning(spawnBalloon, customSpawnInterval) {
|
|
31
|
-
this.clearBalloonSpawn();
|
|
32
|
-
const spawnInterval = customSpawnInterval || GAME_CONFIG.BALLOON_SPAWN_INTERVAL;
|
|
33
|
-
const spawnLoop = () => {
|
|
34
|
-
const balloon = this.createRandomBalloon();
|
|
35
|
-
spawnBalloon(balloon);
|
|
36
|
-
|
|
37
|
-
// Reduced random variation for more consistent spawning
|
|
38
|
-
const randomVariation = (Math.random() - 0.5) * 150; // Further reduced for more consistent spawning
|
|
39
|
-
const nextSpawnTime = spawnInterval + randomVariation;
|
|
40
|
-
this.balloonSpawnRef = setTimeout(spawnLoop, Math.max(200, nextSpawnTime)); // Reduced minimum to 200ms for faster spawning
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
// Spawn initial balloons immediately for instant action
|
|
44
|
-
for (let i = 0; i < 3; i++) {
|
|
45
|
-
// 3 balloons for immediate start
|
|
46
|
-
setTimeout(() => {
|
|
47
|
-
const initialBalloon = this.createRandomBalloon();
|
|
48
|
-
spawnBalloon(initialBalloon);
|
|
49
|
-
}, i * 50); // Very fast stagger for immediate appearance
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// Start continuous spawning loop immediately
|
|
53
|
-
this.balloonSpawnRef = setTimeout(spawnLoop, 100); // Almost immediate continuous spawning
|
|
54
|
-
}
|
|
55
|
-
startPhysicsLoop(updateBalloon, removeBalloon, getBalloons) {
|
|
56
|
-
let lastTime = performance.now();
|
|
57
|
-
const targetFPS = 60;
|
|
58
|
-
const targetFrameTime = 1000 / targetFPS;
|
|
59
|
-
const updateLoop = currentTime => {
|
|
60
|
-
const deltaTime = currentTime - lastTime;
|
|
61
|
-
|
|
62
|
-
// Frame rate limiting - only update if enough time has passed
|
|
63
|
-
if (deltaTime < targetFrameTime) {
|
|
64
|
-
this.animationRef = requestAnimationFrame(updateLoop);
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
lastTime = currentTime;
|
|
68
|
-
const deltaMultiplier = deltaTime / 16.67; // Normalize to 60fps baseline
|
|
69
|
-
|
|
70
|
-
// Always update particles for smooth animation with delta time
|
|
71
|
-
this.updateParticles(deltaMultiplier);
|
|
72
|
-
const balloons = getBalloons();
|
|
73
|
-
|
|
74
|
-
// Use for loop instead of forEach for better performance
|
|
75
|
-
for (let i = 0; i < balloons.length; i++) {
|
|
76
|
-
const balloon = balloons[i];
|
|
77
|
-
if (!balloon || balloon.isPopped) continue;
|
|
78
|
-
|
|
79
|
-
// Physics calculations with delta time
|
|
80
|
-
const newVelocityY = balloon.velocity.y + GAME_CONFIG.GRAVITY * deltaMultiplier;
|
|
81
|
-
let newX = balloon.position.x + balloon.velocity.x * deltaMultiplier;
|
|
82
|
-
const newY = balloon.position.y + newVelocityY * deltaMultiplier;
|
|
83
|
-
const newRotation = balloon.rotation + balloon.rotationSpeed * deltaMultiplier;
|
|
84
|
-
|
|
85
|
-
// Remove balloons that float off screen (top only)
|
|
86
|
-
if (newY < -100) {
|
|
87
|
-
removeBalloon(balloon.id);
|
|
88
|
-
continue;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// Remove balloons that go too far below screen (they should only move upward)
|
|
92
|
-
if (newY > height + 100) {
|
|
93
|
-
// Remove balloons that somehow drift too far down
|
|
94
|
-
removeBalloon(balloon.id);
|
|
95
|
-
continue;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// Simplified wall bounce logic
|
|
99
|
-
let newVelocityX = balloon.velocity.x;
|
|
100
|
-
if (newX <= 0) {
|
|
101
|
-
newX = 0;
|
|
102
|
-
newVelocityX = Math.abs(newVelocityX) * 0.8; // Bounce right with damping
|
|
103
|
-
} else if (newX >= width - GAME_CONFIG.BALLOON_SIZE) {
|
|
104
|
-
newX = width - GAME_CONFIG.BALLOON_SIZE;
|
|
105
|
-
newVelocityX = -Math.abs(newVelocityX) * 0.8; // Bounce left with damping
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// Batch update for better performance
|
|
109
|
-
updateBalloon(balloon.id, {
|
|
110
|
-
position: {
|
|
111
|
-
x: newX,
|
|
112
|
-
y: newY
|
|
113
|
-
},
|
|
114
|
-
velocity: {
|
|
115
|
-
x: newVelocityX,
|
|
116
|
-
y: newVelocityY
|
|
117
|
-
},
|
|
118
|
-
rotation: newRotation
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
this.animationRef = requestAnimationFrame(updateLoop);
|
|
122
|
-
};
|
|
123
|
-
this.animationRef = requestAnimationFrame(updateLoop);
|
|
124
|
-
}
|
|
125
|
-
createRandomBalloon() {
|
|
126
|
-
// 10% chance for special items
|
|
127
|
-
const isSpecial = Math.random() < 0.1;
|
|
128
|
-
const type = isSpecial ? SPECIAL_ITEMS[Math.floor(Math.random() * SPECIAL_ITEMS.length)] : BALLOON_TYPES[Math.floor(Math.random() * BALLOON_TYPES.length)];
|
|
129
|
-
|
|
130
|
-
// Use fallback if type is undefined
|
|
131
|
-
const balloonType = type || BALLOON_TYPES[0];
|
|
132
|
-
|
|
133
|
-
// FORCE all balloons to spawn from bottom with better random X distribution
|
|
134
|
-
const balloonSize = GAME_CONFIG.BALLOON_SIZE;
|
|
135
|
-
const margin = balloonSize / 2; // Add margin from edges
|
|
136
|
-
const availableWidth = width - margin * 2 - balloonSize;
|
|
137
|
-
const spawnX = margin + Math.random() * availableWidth;
|
|
138
|
-
const spawnY = height - 30; // Spawn slightly below screen for gradual appearance
|
|
139
|
-
|
|
140
|
-
// Simple upward velocity
|
|
141
|
-
const velocityX = (Math.random() - 0.5) * GAME_CONFIG.INITIAL_VELOCITY_X_RANGE;
|
|
142
|
-
const velocityY = GAME_CONFIG.INITIAL_VELOCITY_Y;
|
|
143
|
-
return {
|
|
144
|
-
id: `balloon_${Date.now()}_${Math.random()}`,
|
|
145
|
-
type: balloonType,
|
|
146
|
-
position: {
|
|
147
|
-
x: spawnX,
|
|
148
|
-
y: spawnY
|
|
149
|
-
},
|
|
150
|
-
velocity: {
|
|
151
|
-
x: velocityX,
|
|
152
|
-
y: velocityY
|
|
153
|
-
},
|
|
154
|
-
rotation: 0,
|
|
155
|
-
rotationSpeed: (Math.random() - 0.5) * GAME_CONFIG.ROTATION_SPEED_RANGE,
|
|
156
|
-
isPopped: false,
|
|
157
|
-
spawnTime: Date.now(),
|
|
158
|
-
isBomb: 'isBomb' in balloonType && balloonType.isBomb,
|
|
159
|
-
isBonus: 'isBonus' in balloonType && balloonType.isBonus
|
|
160
|
-
};
|
|
161
|
-
}
|
|
162
|
-
createPopParticles(balloon) {
|
|
163
|
-
// Aggressive particle limiting to prevent performance issues during rapid popping
|
|
164
|
-
const maxTotalParticles = 15; // Reduced maximum particles on screen at once
|
|
165
|
-
if (this.particles.length >= maxTotalParticles) {
|
|
166
|
-
// Remove half of existing particles to make room for new ones
|
|
167
|
-
this.particles.splice(0, Math.floor(this.particles.length / 2));
|
|
168
|
-
}
|
|
169
|
-
const particles = [];
|
|
170
|
-
const particleCount = Math.min(GAME_CONFIG.PARTICLE_COUNT, 6); // Limit particles per balloon to 6
|
|
171
|
-
|
|
172
|
-
// Calculate balloon center for particle spawn
|
|
173
|
-
const balloonCenterX = balloon.position.x + GAME_CONFIG.BALLOON_SIZE / 2;
|
|
174
|
-
const balloonCenterY = balloon.position.y + GAME_CONFIG.BALLOON_SIZE / 2;
|
|
175
|
-
for (let i = 0; i < particleCount; i++) {
|
|
176
|
-
const angle = i / particleCount * Math.PI * 2;
|
|
177
|
-
const speed = 5 + Math.random() * 4; // Increased speed for better visibility
|
|
178
|
-
|
|
179
|
-
particles.push({
|
|
180
|
-
id: `particle_${balloon.id}_${i}_${Date.now()}_${Math.random()}`,
|
|
181
|
-
// More unique ID
|
|
182
|
-
position: {
|
|
183
|
-
x: balloonCenterX,
|
|
184
|
-
// Center particles exactly on balloon center
|
|
185
|
-
y: balloonCenterY
|
|
186
|
-
},
|
|
187
|
-
velocity: {
|
|
188
|
-
x: Math.cos(angle) * speed,
|
|
189
|
-
y: Math.sin(angle) * speed - 3 // Stronger upward bias for visibility
|
|
190
|
-
},
|
|
191
|
-
color: COLORS.PARTICLE_COLORS[i % COLORS.PARTICLE_COLORS.length] || '#FF6B6B',
|
|
192
|
-
size: 4 + Math.random() * 3,
|
|
193
|
-
// Slightly smaller particles (4-7px) for better performance
|
|
194
|
-
lifetime: 0,
|
|
195
|
-
maxLifetime: Math.min(GAME_CONFIG.PARTICLE_LIFETIME, 800) // Reduced lifetime for better performance
|
|
196
|
-
});
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
// Create new particles array instead of mutating existing one
|
|
200
|
-
this.particles = [...this.particles, ...particles];
|
|
201
|
-
return particles;
|
|
202
|
-
}
|
|
203
|
-
updateParticles(deltaMultiplier = 1) {
|
|
204
|
-
// Optimized particle update with delta time
|
|
205
|
-
const deltaTime = 16 * deltaMultiplier; // Scale with actual frame time
|
|
206
|
-
const gravity = 0.08 * deltaMultiplier; // Scale gravity with delta time
|
|
207
|
-
|
|
208
|
-
// Use filter to create new array instead of mutating existing one
|
|
209
|
-
const updatedParticles = [];
|
|
210
|
-
for (let i = 0; i < this.particles.length; i++) {
|
|
211
|
-
const particle = this.particles[i];
|
|
212
|
-
if (!particle) continue;
|
|
213
|
-
|
|
214
|
-
// Create a new particle object to avoid mutation
|
|
215
|
-
const updatedParticle = {
|
|
216
|
-
...particle
|
|
217
|
-
};
|
|
218
|
-
updatedParticle.lifetime += deltaTime;
|
|
219
|
-
if (updatedParticle.lifetime >= updatedParticle.maxLifetime) {
|
|
220
|
-
// Skip expired particle (don't add to updatedParticles)
|
|
221
|
-
continue;
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
// Update particle physics with delta time scaling
|
|
225
|
-
updatedParticle.position = {
|
|
226
|
-
x: updatedParticle.position.x + updatedParticle.velocity.x * deltaMultiplier,
|
|
227
|
-
y: updatedParticle.position.y + updatedParticle.velocity.y * deltaMultiplier
|
|
228
|
-
};
|
|
229
|
-
updatedParticle.velocity = {
|
|
230
|
-
x: updatedParticle.velocity.x * Math.pow(0.99, deltaMultiplier),
|
|
231
|
-
y: (updatedParticle.velocity.y + gravity) * Math.pow(0.99, deltaMultiplier)
|
|
232
|
-
};
|
|
233
|
-
updatedParticles.push(updatedParticle);
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
// Replace particles array with updated one
|
|
237
|
-
this.particles = updatedParticles;
|
|
238
|
-
}
|
|
239
|
-
getParticles() {
|
|
240
|
-
return this.particles;
|
|
241
|
-
}
|
|
242
|
-
checkBalloonPop(balloon, slicePath) {
|
|
243
|
-
if (balloon.isPopped || slicePath.length < 2) return false;
|
|
244
|
-
const balloonCenter = {
|
|
245
|
-
x: balloon.position.x + GAME_CONFIG.BALLOON_SIZE / 2,
|
|
246
|
-
y: balloon.position.y + GAME_CONFIG.BALLOON_SIZE / 2
|
|
247
|
-
};
|
|
248
|
-
const balloonRadius = GAME_CONFIG.BALLOON_SIZE / 2;
|
|
249
|
-
|
|
250
|
-
// Check if slice path intersects with balloon
|
|
251
|
-
for (let i = 0; i < slicePath.length - 1; i++) {
|
|
252
|
-
const p1 = slicePath[i];
|
|
253
|
-
const p2 = slicePath[i + 1];
|
|
254
|
-
if (!p1 || !p2) continue;
|
|
255
|
-
const distance = this.distanceFromPointToLine(balloonCenter, p1, p2);
|
|
256
|
-
if (distance <= balloonRadius) {
|
|
257
|
-
return true;
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
return false;
|
|
261
|
-
}
|
|
262
|
-
distanceFromPointToLine(point, lineStart, lineEnd) {
|
|
263
|
-
const A = point.x - lineStart.x;
|
|
264
|
-
const B = point.y - lineStart.y;
|
|
265
|
-
const C = lineEnd.x - lineStart.x;
|
|
266
|
-
const D = lineEnd.y - lineStart.y;
|
|
267
|
-
const dot = A * C + B * D;
|
|
268
|
-
const lenSq = C * C + D * D;
|
|
269
|
-
if (lenSq === 0) return Math.sqrt(A * A + B * B);
|
|
270
|
-
let param = dot / lenSq;
|
|
271
|
-
param = Math.max(0, Math.min(1, param));
|
|
272
|
-
const xx = lineStart.x + param * C;
|
|
273
|
-
const yy = lineStart.y + param * D;
|
|
274
|
-
const dx = point.x - xx;
|
|
275
|
-
const dy = point.y - yy;
|
|
276
|
-
return Math.sqrt(dx * dx + dy * dy);
|
|
277
|
-
}
|
|
278
|
-
resetAnimations() {
|
|
279
|
-
this.balloonAnimations.clear();
|
|
280
|
-
this.particleAnimations.clear();
|
|
281
|
-
this.particles = [];
|
|
282
|
-
}
|
|
283
|
-
cleanup() {
|
|
284
|
-
this.clearGameTimer();
|
|
285
|
-
this.clearBalloonSpawn();
|
|
286
|
-
this.clearAnimationLoop();
|
|
287
|
-
this.clearComboTimeout();
|
|
288
|
-
this.particles = [];
|
|
289
|
-
}
|
|
290
|
-
clearGameTimer() {
|
|
291
|
-
if (this.gameTimerRef) {
|
|
292
|
-
clearInterval(this.gameTimerRef);
|
|
293
|
-
this.gameTimerRef = null;
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
clearBalloonSpawn() {
|
|
297
|
-
if (this.balloonSpawnRef) {
|
|
298
|
-
clearTimeout(this.balloonSpawnRef);
|
|
299
|
-
this.balloonSpawnRef = null;
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
clearAnimationLoop() {
|
|
303
|
-
if (this.animationRef) {
|
|
304
|
-
cancelAnimationFrame(this.animationRef);
|
|
305
|
-
this.animationRef = null;
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
clearComboTimeout() {
|
|
309
|
-
if (this.comboTimeoutRef) {
|
|
310
|
-
clearTimeout(this.comboTimeoutRef);
|
|
311
|
-
this.comboTimeoutRef = null;
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
export const createBalloonBlasterService = (balloonAnimations, particleAnimations) => {
|
|
316
|
-
return new BalloonBlasterService(balloonAnimations, particleAnimations);
|
|
317
|
-
};
|
|
318
|
-
//# sourceMappingURL=BalloonBlasterService.js.map
|
|
1
|
+
"use strict";import{Dimensions}from 'react-native';import{BALLOON_BLASTER_GAME_CONFIG as GAME_CONFIG,BALLOON_BLASTER_ANIMATION_CONFIG as ANIMATION_CONFIG,BALLOON_BLASTER_COLORS as COLORS,BALLOON_TYPES,BALLOON_SPECIAL_ITEMS as SPECIAL_ITEMS}from "./BalloonBlasterConstants.js";const{width,height}= Dimensions.get('window');export{GAME_CONFIG,ANIMATION_CONFIG,COLORS,BALLOON_TYPES,SPECIAL_ITEMS};export class BalloonBlasterService{gameTimerRef = null;balloonSpawnRef = null;animationRef = null;comboTimeoutRef = null;particles = [];constructor(balloonAnimations,particleAnimations){this.balloonAnimations = balloonAnimations;this.particleAnimations = particleAnimations;}startGameTimer(onTick){this.clearGameTimer();this.gameTimerRef = setInterval(onTick,1000);}startBalloonSpawning(spawnBalloon,customSpawnInterval){this.clearBalloonSpawn();const spawnInterval = customSpawnInterval || GAME_CONFIG.BALLOON_SPAWN_INTERVAL;const spawnLoop =()=>{const balloon = this.createRandomBalloon();spawnBalloon(balloon);const randomVariation =(Math.random()- 0.5)* 150;const nextSpawnTime = spawnInterval + randomVariation;this.balloonSpawnRef = setTimeout(spawnLoop,Math.max(200,nextSpawnTime));};for(let i = 0;i < 3;i++){setTimeout(()=>{const initialBalloon = this.createRandomBalloon();spawnBalloon(initialBalloon);},i * 50);}this.balloonSpawnRef = setTimeout(spawnLoop,100);}startPhysicsLoop(updateBalloon,removeBalloon,getBalloons){let lastTime = performance.now();const targetFPS = 60;const targetFrameTime = 1000 / targetFPS;const updateLoop = currentTime =>{const deltaTime = currentTime - lastTime;if(deltaTime < targetFrameTime){this.animationRef = requestAnimationFrame(updateLoop);return;}lastTime = currentTime;const deltaMultiplier = deltaTime / 16.67;this.updateParticles(deltaMultiplier);const balloons = getBalloons();for(let i = 0;i < balloons.length;i++){const balloon = balloons[i];if(!balloon || balloon.isPopped)continue;const newVelocityY = balloon.velocity.y + GAME_CONFIG.GRAVITY * deltaMultiplier;let newX = balloon.position.x + balloon.velocity.x * deltaMultiplier;const newY = balloon.position.y + newVelocityY * deltaMultiplier;const newRotation = balloon.rotation + balloon.rotationSpeed * deltaMultiplier;if(newY < -100){removeBalloon(balloon.id);continue;}if(newY > height + 100){removeBalloon(balloon.id);continue;}let newVelocityX = balloon.velocity.x;if(newX <= 0){newX = 0;newVelocityX = Math.abs(newVelocityX)* 0.8;}else if(newX >= width - GAME_CONFIG.BALLOON_SIZE){newX = width - GAME_CONFIG.BALLOON_SIZE;newVelocityX = -Math.abs(newVelocityX)* 0.8;}updateBalloon(balloon.id,{position:{x:newX,y:newY},velocity:{x:newVelocityX,y:newVelocityY},rotation:newRotation});}this.animationRef = requestAnimationFrame(updateLoop);};this.animationRef = requestAnimationFrame(updateLoop);}createRandomBalloon(){const isSpecial = Math.random()< 0.1;const type = isSpecial ? SPECIAL_ITEMS[Math.floor(Math.random()* SPECIAL_ITEMS.length)]:BALLOON_TYPES[Math.floor(Math.random()* BALLOON_TYPES.length)];const balloonType = type || BALLOON_TYPES[0];const balloonSize = GAME_CONFIG.BALLOON_SIZE;const margin = balloonSize / 2;const availableWidth = width - margin * 2 - balloonSize;const spawnX = margin + Math.random()* availableWidth;const spawnY = height - 30;const velocityX =(Math.random()- 0.5)* GAME_CONFIG.INITIAL_VELOCITY_X_RANGE;const velocityY = GAME_CONFIG.INITIAL_VELOCITY_Y;return{id:`balloon_${Date.now()}_${Math.random()}`,type:balloonType,position:{x:spawnX,y:spawnY},velocity:{x:velocityX,y:velocityY},rotation:0,rotationSpeed:(Math.random()- 0.5)* GAME_CONFIG.ROTATION_SPEED_RANGE,isPopped:false,spawnTime:Date.now(),isBomb:'isBomb' in balloonType && balloonType.isBomb,isBonus:'isBonus' in balloonType && balloonType.isBonus};}createPopParticles(balloon){const maxTotalParticles = 15;if(this.particles.length >= maxTotalParticles){this.particles.splice(0,Math.floor(this.particles.length / 2));}const particles = [];const particleCount = Math.min(GAME_CONFIG.PARTICLE_COUNT,6);const balloonCenterX = balloon.position.x + GAME_CONFIG.BALLOON_SIZE / 2;const balloonCenterY = balloon.position.y + GAME_CONFIG.BALLOON_SIZE / 2;for(let i = 0;i < particleCount;i++){const angle = i / particleCount * Math.PI * 2;const speed = 5 + Math.random()* 4;particles.push({id:`particle_${balloon.id}_${i}_${Date.now()}_${Math.random()}`,position:{x:balloonCenterX,y:balloonCenterY},velocity:{x:Math.cos(angle)* speed,y:Math.sin(angle)* speed - 3},color:COLORS.PARTICLE_COLORS[i % COLORS.PARTICLE_COLORS.length] || '#FF6B6B',size:4 + Math.random()* 3,lifetime:0,maxLifetime:Math.min(GAME_CONFIG.PARTICLE_LIFETIME,800)});}this.particles = [...this.particles,...particles];return particles;}updateParticles(deltaMultiplier = 1){const deltaTime = 16 * deltaMultiplier;const gravity = 0.08 * deltaMultiplier;const updatedParticles = [];for(let i = 0;i < this.particles.length;i++){const particle = this.particles[i];if(!particle)continue;const updatedParticle ={...particle};updatedParticle.lifetime += deltaTime;if(updatedParticle.lifetime >= updatedParticle.maxLifetime){continue;}updatedParticle.position ={x:updatedParticle.position.x + updatedParticle.velocity.x * deltaMultiplier,y:updatedParticle.position.y + updatedParticle.velocity.y * deltaMultiplier};updatedParticle.velocity ={x:updatedParticle.velocity.x * Math.pow(0.99,deltaMultiplier),y:(updatedParticle.velocity.y + gravity)* Math.pow(0.99,deltaMultiplier)};updatedParticles.push(updatedParticle);}this.particles = updatedParticles;}getParticles(){return this.particles;}checkBalloonPop(balloon,slicePath){if(balloon.isPopped || slicePath.length < 2)return false;const balloonCenter ={x:balloon.position.x + GAME_CONFIG.BALLOON_SIZE / 2,y:balloon.position.y + GAME_CONFIG.BALLOON_SIZE / 2};const balloonRadius = GAME_CONFIG.BALLOON_SIZE / 2;for(let i = 0;i < slicePath.length - 1;i++){const p1 = slicePath[i];const p2 = slicePath[i + 1];if(!p1 || !p2)continue;const distance = this.distanceFromPointToLine(balloonCenter,p1,p2);if(distance <= balloonRadius){return true;}}return false;}distanceFromPointToLine(point,lineStart,lineEnd){const A = point.x - lineStart.x;const B = point.y - lineStart.y;const C = lineEnd.x - lineStart.x;const D = lineEnd.y - lineStart.y;const dot = A * C + B * D;const lenSq = C * C + D * D;if(lenSq === 0)return Math.sqrt(A * A + B * B);let param = dot / lenSq;param = Math.max(0,Math.min(1,param));const xx = lineStart.x + param * C;const yy = lineStart.y + param * D;const dx = point.x - xx;const dy = point.y - yy;return Math.sqrt(dx * dx + dy * dy);}resetAnimations(){this.balloonAnimations.clear();this.particleAnimations.clear();this.particles = [];}cleanup(){this.clearGameTimer();this.clearBalloonSpawn();this.clearAnimationLoop();this.clearComboTimeout();this.particles = [];}clearGameTimer(){if(this.gameTimerRef){clearInterval(this.gameTimerRef);this.gameTimerRef = null;}}clearBalloonSpawn(){if(this.balloonSpawnRef){clearTimeout(this.balloonSpawnRef);this.balloonSpawnRef = null;}}clearAnimationLoop(){if(this.animationRef){cancelAnimationFrame(this.animationRef);this.animationRef = null;}}clearComboTimeout(){if(this.comboTimeoutRef){clearTimeout(this.comboTimeoutRef);this.comboTimeoutRef = null;}}}export const createBalloonBlasterService =(balloonAnimations,particleAnimations)=>{return new BalloonBlasterService(balloonAnimations,particleAnimations);};
|
|
@@ -1,183 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
import { create } from 'zustand';
|
|
4
|
-
import { subscribeWithSelector } from 'zustand/middleware';
|
|
5
|
-
import { GAME_CONFIG } from "./BalloonBlasterService.js";
|
|
6
|
-
import { immerMiddleware } from "../../services/UtilsService.js";
|
|
7
|
-
// Optimized store with selective subscriptions for low-end devices
|
|
8
|
-
export const useBalloonBlasterStore = create()(subscribeWithSelector(immerMiddleware((set, get) => ({
|
|
9
|
-
// Initial state
|
|
10
|
-
score: 0,
|
|
11
|
-
timeLeft: 60,
|
|
12
|
-
// Fixed 60 seconds regardless of difficulty
|
|
13
|
-
isPlaying: false,
|
|
14
|
-
gameOver: false,
|
|
15
|
-
combo: 0,
|
|
16
|
-
lives: GAME_CONFIG.MAX_LIVES,
|
|
17
|
-
balloons: [],
|
|
18
|
-
particles: [],
|
|
19
|
-
slicePath: [],
|
|
20
|
-
isSlicing: false,
|
|
21
|
-
// Actions
|
|
22
|
-
startGame: _gameDuration => {
|
|
23
|
-
// Always use fixed duration regardless of difficulty or passed duration
|
|
24
|
-
const duration = 60;
|
|
25
|
-
set(draft => {
|
|
26
|
-
draft.score = 0;
|
|
27
|
-
draft.timeLeft = duration;
|
|
28
|
-
draft.isPlaying = true;
|
|
29
|
-
draft.gameOver = false;
|
|
30
|
-
draft.combo = 0;
|
|
31
|
-
draft.lives = GAME_CONFIG.MAX_LIVES;
|
|
32
|
-
draft.balloons = [];
|
|
33
|
-
draft.slicePath = [];
|
|
34
|
-
draft.isSlicing = false;
|
|
35
|
-
});
|
|
36
|
-
},
|
|
37
|
-
stopGame: () => {
|
|
38
|
-
set(draft => {
|
|
39
|
-
draft.score = 0;
|
|
40
|
-
draft.timeLeft = 60; // Fixed 60 seconds
|
|
41
|
-
draft.isPlaying = false;
|
|
42
|
-
draft.gameOver = false;
|
|
43
|
-
draft.combo = 0;
|
|
44
|
-
draft.lives = GAME_CONFIG.MAX_LIVES;
|
|
45
|
-
draft.balloons = [];
|
|
46
|
-
draft.slicePath = [];
|
|
47
|
-
draft.isSlicing = false;
|
|
48
|
-
});
|
|
49
|
-
},
|
|
50
|
-
resetGame: () => {
|
|
51
|
-
set(draft => {
|
|
52
|
-
draft.score = 0;
|
|
53
|
-
draft.timeLeft = 60; // Fixed 60 seconds
|
|
54
|
-
draft.isPlaying = false;
|
|
55
|
-
draft.gameOver = false;
|
|
56
|
-
draft.combo = 0;
|
|
57
|
-
draft.lives = GAME_CONFIG.MAX_LIVES;
|
|
58
|
-
draft.balloons = [];
|
|
59
|
-
draft.slicePath = [];
|
|
60
|
-
draft.isSlicing = false;
|
|
61
|
-
});
|
|
62
|
-
},
|
|
63
|
-
popBalloon: balloonId => {
|
|
64
|
-
const {
|
|
65
|
-
balloons,
|
|
66
|
-
isPlaying
|
|
67
|
-
} = get();
|
|
68
|
-
if (!isPlaying) return;
|
|
69
|
-
|
|
70
|
-
// Optimized: Use for-loop instead of find for better performance
|
|
71
|
-
let balloonIndex = -1;
|
|
72
|
-
for (let i = 0; i < balloons.length; i++) {
|
|
73
|
-
if (balloons[i].id === balloonId) {
|
|
74
|
-
balloonIndex = i;
|
|
75
|
-
break;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
if (balloonIndex === -1 || balloons[balloonIndex].isPopped) return;
|
|
79
|
-
|
|
80
|
-
// Simplified scoring: each balloon = 10 points (no combo multipliers)
|
|
81
|
-
const points = 10;
|
|
82
|
-
set(draft => {
|
|
83
|
-
draft.score = draft.score + points;
|
|
84
|
-
// Optimized: Direct array access instead of find
|
|
85
|
-
if (draft.balloons[balloonIndex]) {
|
|
86
|
-
draft.balloons[balloonIndex].isPopped = true;
|
|
87
|
-
draft.balloons[balloonIndex].popTime = Date.now();
|
|
88
|
-
}
|
|
89
|
-
});
|
|
90
|
-
},
|
|
91
|
-
updateScore: points => {
|
|
92
|
-
set(draft => {
|
|
93
|
-
draft.score = draft.score + points;
|
|
94
|
-
});
|
|
95
|
-
},
|
|
96
|
-
decrementTime: () => {
|
|
97
|
-
set(draft => {
|
|
98
|
-
const newTimeLeft = draft.timeLeft - 1;
|
|
99
|
-
if (newTimeLeft <= 0) {
|
|
100
|
-
draft.timeLeft = 0;
|
|
101
|
-
draft.isPlaying = false;
|
|
102
|
-
draft.gameOver = true;
|
|
103
|
-
} else {
|
|
104
|
-
draft.timeLeft = newTimeLeft;
|
|
105
|
-
}
|
|
106
|
-
});
|
|
107
|
-
},
|
|
108
|
-
addBalloon: balloon => {
|
|
109
|
-
set(draft => {
|
|
110
|
-
// FORCE all balloons to spawn from bottom - override any wrong positions
|
|
111
|
-
const {
|
|
112
|
-
height
|
|
113
|
-
} = require('react-native').Dimensions.get('window');
|
|
114
|
-
const correctedBalloon = {
|
|
115
|
-
...balloon,
|
|
116
|
-
position: {
|
|
117
|
-
x: balloon.position.x,
|
|
118
|
-
y: height + 20 // Force bottom spawn regardless of input
|
|
119
|
-
}
|
|
120
|
-
};
|
|
121
|
-
draft.balloons.push(correctedBalloon);
|
|
122
|
-
});
|
|
123
|
-
},
|
|
124
|
-
removeBalloon: balloonId => {
|
|
125
|
-
set(draft => {
|
|
126
|
-
draft.balloons = draft.balloons.filter(b => b.id !== balloonId);
|
|
127
|
-
});
|
|
128
|
-
},
|
|
129
|
-
updateBalloon: (balloonId, updates) => {
|
|
130
|
-
set(draft => {
|
|
131
|
-
// Optimized: Use for-loop instead of find for better performance
|
|
132
|
-
for (let i = 0; i < draft.balloons.length; i++) {
|
|
133
|
-
if (draft.balloons[i].id === balloonId) {
|
|
134
|
-
Object.assign(draft.balloons[i], updates);
|
|
135
|
-
break;
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
});
|
|
139
|
-
},
|
|
140
|
-
setParticles: particles => {
|
|
141
|
-
set(draft => {
|
|
142
|
-
draft.particles = particles;
|
|
143
|
-
});
|
|
144
|
-
},
|
|
145
|
-
setSlicePath: path => {
|
|
146
|
-
set(draft => {
|
|
147
|
-
draft.slicePath = path;
|
|
148
|
-
});
|
|
149
|
-
},
|
|
150
|
-
setIsSlicing: isSlicing => {
|
|
151
|
-
set(draft => {
|
|
152
|
-
draft.isSlicing = isSlicing;
|
|
153
|
-
});
|
|
154
|
-
},
|
|
155
|
-
incrementCombo: () => {
|
|
156
|
-
set(draft => {
|
|
157
|
-
draft.combo = draft.combo + 1;
|
|
158
|
-
});
|
|
159
|
-
},
|
|
160
|
-
resetCombo: () => {
|
|
161
|
-
set(draft => {
|
|
162
|
-
draft.combo = 0;
|
|
163
|
-
});
|
|
164
|
-
},
|
|
165
|
-
loseLife: () => {
|
|
166
|
-
set(draft => {
|
|
167
|
-
const newLives = draft.lives - 1;
|
|
168
|
-
if (newLives <= 0) {
|
|
169
|
-
draft.lives = 0;
|
|
170
|
-
draft.isPlaying = false;
|
|
171
|
-
draft.gameOver = true;
|
|
172
|
-
} else {
|
|
173
|
-
draft.lives = newLives;
|
|
174
|
-
}
|
|
175
|
-
});
|
|
176
|
-
},
|
|
177
|
-
addLife: () => {
|
|
178
|
-
set(draft => {
|
|
179
|
-
draft.lives = Math.min(draft.lives + 1, GAME_CONFIG.MAX_LIVES); // Cap at max lives
|
|
180
|
-
});
|
|
181
|
-
}
|
|
182
|
-
}))));
|
|
183
|
-
//# sourceMappingURL=BalloonBlasterStore.js.map
|
|
1
|
+
"use strict";import{create}from 'zustand';import{subscribeWithSelector}from 'zustand/middleware';import{GAME_CONFIG}from "./BalloonBlasterService.js";import{immerMiddleware}from "../../services/UtilsService.js";export const useBalloonBlasterStore = create()(subscribeWithSelector(immerMiddleware((set,get)=>({score:0,timeLeft:60,isPlaying:false,gameOver:false,combo:0,lives:GAME_CONFIG.MAX_LIVES,balloons:[],particles:[],slicePath:[],isSlicing:false,startGame:_gameDuration =>{const duration = 60;set(draft =>{draft.score = 0;draft.timeLeft = duration;draft.isPlaying = true;draft.gameOver = false;draft.combo = 0;draft.lives = GAME_CONFIG.MAX_LIVES;draft.balloons = [];draft.slicePath = [];draft.isSlicing = false;});},stopGame:()=>{set(draft =>{draft.score = 0;draft.timeLeft = 60;draft.isPlaying = false;draft.gameOver = false;draft.combo = 0;draft.lives = GAME_CONFIG.MAX_LIVES;draft.balloons = [];draft.slicePath = [];draft.isSlicing = false;});},resetGame:()=>{set(draft =>{draft.score = 0;draft.timeLeft = 60;draft.isPlaying = false;draft.gameOver = false;draft.combo = 0;draft.lives = GAME_CONFIG.MAX_LIVES;draft.balloons = [];draft.slicePath = [];draft.isSlicing = false;});},popBalloon:balloonId =>{const{balloons,isPlaying}= get();if(!isPlaying)return;let balloonIndex = -1;for(let i = 0;i < balloons.length;i++){if(balloons[i].id === balloonId){balloonIndex = i;break;}}if(balloonIndex === -1 || balloons[balloonIndex].isPopped)return;const points = 10;set(draft =>{draft.score = draft.score + points;if(draft.balloons[balloonIndex]){draft.balloons[balloonIndex].isPopped = true;draft.balloons[balloonIndex].popTime = Date.now();}});},updateScore:points =>{set(draft =>{draft.score = draft.score + points;});},decrementTime:()=>{set(draft =>{const newTimeLeft = draft.timeLeft - 1;if(newTimeLeft <= 0){draft.timeLeft = 0;draft.isPlaying = false;draft.gameOver = true;}else{draft.timeLeft = newTimeLeft;}});},addBalloon:balloon =>{set(draft =>{const{height}= require('react-native').Dimensions.get('window');const correctedBalloon ={...balloon,position:{x:balloon.position.x,y:height + 20}};draft.balloons.push(correctedBalloon);});},removeBalloon:balloonId =>{set(draft =>{draft.balloons = draft.balloons.filter(b => b.id !== balloonId);});},updateBalloon:(balloonId,updates)=>{set(draft =>{for(let i = 0;i < draft.balloons.length;i++){if(draft.balloons[i].id === balloonId){Object.assign(draft.balloons[i],updates);break;}}});},setParticles:particles =>{set(draft =>{draft.particles = particles;});},setSlicePath:path =>{set(draft =>{draft.slicePath = path;});},setIsSlicing:isSlicing =>{set(draft =>{draft.isSlicing = isSlicing;});},incrementCombo:()=>{set(draft =>{draft.combo = draft.combo + 1;});},resetCombo:()=>{set(draft =>{draft.combo = 0;});},loseLife:()=>{set(draft =>{const newLives = draft.lives - 1;if(newLives <= 0){draft.lives = 0;draft.isPlaying = false;draft.gameOver = true;}else{draft.lives = newLives;}});},addLife:()=>{set(draft =>{draft.lives = Math.min(draft.lives + 1,GAME_CONFIG.MAX_LIVES);});}}))));
|