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,191 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
import React, { useEffect, useRef } from 'react';
|
|
4
|
-
import { StyleSheet } from 'react-native';
|
|
5
|
-
import { Gesture, GestureDetector } from 'react-native-gesture-handler';
|
|
6
|
-
import Animated, { useSharedValue, useAnimatedStyle, withSpring, withTiming, runOnJS } from 'react-native-reanimated';
|
|
7
|
-
import { Canvas, RoundedRect, Group, Shadow } from '@shopify/react-native-skia';
|
|
8
|
-
import { CandyCrushService } from "../CandyCrushService.js";
|
|
9
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
10
|
-
const gameService = new CandyCrushService();
|
|
11
|
-
const CandyItemComponent = ({
|
|
12
|
-
candy,
|
|
13
|
-
size,
|
|
14
|
-
isSelected,
|
|
15
|
-
isMatched,
|
|
16
|
-
isFalling,
|
|
17
|
-
onSwipe
|
|
18
|
-
}) => {
|
|
19
|
-
// Reanimated shared values for smooth animations
|
|
20
|
-
const translateX = useSharedValue(0);
|
|
21
|
-
const translateY = useSharedValue(0);
|
|
22
|
-
const scale = useSharedValue(1);
|
|
23
|
-
const opacity = useSharedValue(1);
|
|
24
|
-
const zIndex = useSharedValue(0);
|
|
25
|
-
|
|
26
|
-
// Track previous states to avoid unnecessary animations
|
|
27
|
-
const prevMatchedRef = useRef(isMatched);
|
|
28
|
-
const prevFallingRef = useRef(isFalling);
|
|
29
|
-
const prevRowRef = useRef(candy.row);
|
|
30
|
-
|
|
31
|
-
// Match animation - only trigger when state changes from false to true
|
|
32
|
-
useEffect(() => {
|
|
33
|
-
if (isMatched && !prevMatchedRef.current) {
|
|
34
|
-
scale.value = withTiming(0, {
|
|
35
|
-
duration: 300
|
|
36
|
-
});
|
|
37
|
-
opacity.value = withTiming(0, {
|
|
38
|
-
duration: 300
|
|
39
|
-
});
|
|
40
|
-
} else if (!isMatched && prevMatchedRef.current) {
|
|
41
|
-
// Reset when candy is replaced
|
|
42
|
-
scale.value = 1;
|
|
43
|
-
opacity.value = 1;
|
|
44
|
-
}
|
|
45
|
-
prevMatchedRef.current = isMatched;
|
|
46
|
-
}, [isMatched]);
|
|
47
|
-
|
|
48
|
-
// Fall animation - only trigger when falling state changes or row changes
|
|
49
|
-
useEffect(() => {
|
|
50
|
-
const rowChanged = candy.row !== prevRowRef.current;
|
|
51
|
-
if (isFalling && !prevFallingRef.current) {
|
|
52
|
-
scale.value = withSpring(1, {
|
|
53
|
-
damping: 8,
|
|
54
|
-
stiffness: 40
|
|
55
|
-
});
|
|
56
|
-
} else if (rowChanged && isFalling) {
|
|
57
|
-
// Animate position change during fall
|
|
58
|
-
scale.value = withSpring(1, {
|
|
59
|
-
damping: 8,
|
|
60
|
-
stiffness: 40
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
prevFallingRef.current = isFalling;
|
|
64
|
-
prevRowRef.current = candy.row;
|
|
65
|
-
}, [isFalling, candy.row]);
|
|
66
|
-
|
|
67
|
-
// Swipe gesture
|
|
68
|
-
const panGesture = Gesture.Pan().onStart(() => {
|
|
69
|
-
// Elevate candy when starting to swipe
|
|
70
|
-
zIndex.value = 1000;
|
|
71
|
-
scale.value = withSpring(1.1);
|
|
72
|
-
}).onUpdate(event => {
|
|
73
|
-
translateX.value = event.translationX;
|
|
74
|
-
translateY.value = event.translationY;
|
|
75
|
-
}).onEnd(event => {
|
|
76
|
-
const threshold = size * 0.3; // 30% of candy size
|
|
77
|
-
const absX = Math.abs(event.translationX);
|
|
78
|
-
const absY = Math.abs(event.translationY);
|
|
79
|
-
|
|
80
|
-
// Determine swipe direction
|
|
81
|
-
if (absX > threshold || absY > threshold) {
|
|
82
|
-
if (absX > absY) {
|
|
83
|
-
// Horizontal swipe
|
|
84
|
-
if (event.translationX > 0) {
|
|
85
|
-
runOnJS(onSwipe)('right');
|
|
86
|
-
} else {
|
|
87
|
-
runOnJS(onSwipe)('left');
|
|
88
|
-
}
|
|
89
|
-
} else {
|
|
90
|
-
// Vertical swipe
|
|
91
|
-
if (event.translationY > 0) {
|
|
92
|
-
runOnJS(onSwipe)('down');
|
|
93
|
-
} else {
|
|
94
|
-
runOnJS(onSwipe)('up');
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// Reset position and elevation with spring animation
|
|
100
|
-
translateX.value = withSpring(0);
|
|
101
|
-
translateY.value = withSpring(0);
|
|
102
|
-
scale.value = withSpring(1);
|
|
103
|
-
zIndex.value = withTiming(0, {
|
|
104
|
-
duration: 300
|
|
105
|
-
});
|
|
106
|
-
});
|
|
107
|
-
const candyColor = gameService.getCandyColor(candy.type);
|
|
108
|
-
const borderRadius = 8; // Square with slight rounding
|
|
109
|
-
|
|
110
|
-
// Animated style for swipe and other animations
|
|
111
|
-
const animatedStyle = useAnimatedStyle(() => ({
|
|
112
|
-
transform: [{
|
|
113
|
-
translateX: translateX.value
|
|
114
|
-
}, {
|
|
115
|
-
translateY: translateY.value
|
|
116
|
-
}, {
|
|
117
|
-
scale: scale.value
|
|
118
|
-
}],
|
|
119
|
-
opacity: opacity.value,
|
|
120
|
-
zIndex: zIndex.value
|
|
121
|
-
}));
|
|
122
|
-
return /*#__PURE__*/_jsx(GestureDetector, {
|
|
123
|
-
gesture: panGesture,
|
|
124
|
-
children: /*#__PURE__*/_jsx(Animated.View, {
|
|
125
|
-
style: [styles.container, {
|
|
126
|
-
width: size,
|
|
127
|
-
height: size
|
|
128
|
-
}, animatedStyle],
|
|
129
|
-
children: /*#__PURE__*/_jsx(Canvas, {
|
|
130
|
-
style: {
|
|
131
|
-
width: size,
|
|
132
|
-
height: size
|
|
133
|
-
},
|
|
134
|
-
children: /*#__PURE__*/_jsxs(Group, {
|
|
135
|
-
children: [/*#__PURE__*/_jsx(RoundedRect, {
|
|
136
|
-
x: 2,
|
|
137
|
-
y: 2,
|
|
138
|
-
width: size - 4,
|
|
139
|
-
height: size - 4,
|
|
140
|
-
r: borderRadius,
|
|
141
|
-
color: candyColor
|
|
142
|
-
}), /*#__PURE__*/_jsx(RoundedRect, {
|
|
143
|
-
x: size * 0.15,
|
|
144
|
-
y: size * 0.15,
|
|
145
|
-
width: size * 0.35,
|
|
146
|
-
height: size * 0.35,
|
|
147
|
-
r: 6,
|
|
148
|
-
color: "rgba(255, 255, 255, 0.5)"
|
|
149
|
-
}), /*#__PURE__*/_jsx(RoundedRect, {
|
|
150
|
-
x: 6,
|
|
151
|
-
y: 6,
|
|
152
|
-
width: size - 12,
|
|
153
|
-
height: size - 12,
|
|
154
|
-
r: borderRadius - 2,
|
|
155
|
-
color: "rgba(255, 255, 255, 0.2)"
|
|
156
|
-
}), isSelected && /*#__PURE__*/_jsx(RoundedRect, {
|
|
157
|
-
x: 1,
|
|
158
|
-
y: 1,
|
|
159
|
-
width: size - 2,
|
|
160
|
-
height: size - 2,
|
|
161
|
-
r: borderRadius + 1,
|
|
162
|
-
color: "transparent",
|
|
163
|
-
style: "stroke",
|
|
164
|
-
strokeWidth: 3,
|
|
165
|
-
children: /*#__PURE__*/_jsx(Shadow, {
|
|
166
|
-
dx: 0,
|
|
167
|
-
dy: 0,
|
|
168
|
-
blur: 6,
|
|
169
|
-
color: "rgba(255, 255, 255, 1)"
|
|
170
|
-
})
|
|
171
|
-
})]
|
|
172
|
-
})
|
|
173
|
-
})
|
|
174
|
-
})
|
|
175
|
-
});
|
|
176
|
-
};
|
|
177
|
-
|
|
178
|
-
// Memoize with custom comparison for better performance
|
|
179
|
-
// Animation states (isMatched, isFalling) come from props, not candy object
|
|
180
|
-
// This prevents grid mutations from causing unnecessary re-renders
|
|
181
|
-
export const CandyItem = /*#__PURE__*/React.memo(CandyItemComponent, (prevProps, nextProps) => {
|
|
182
|
-
return prevProps.candy.id === nextProps.candy.id && prevProps.candy.type === nextProps.candy.type && prevProps.candy.row === nextProps.candy.row && prevProps.candy.col === nextProps.candy.col && prevProps.isMatched === nextProps.isMatched && prevProps.isFalling === nextProps.isFalling && prevProps.isSelected === nextProps.isSelected && prevProps.size === nextProps.size;
|
|
183
|
-
});
|
|
184
|
-
CandyItem.displayName = 'CandyItem';
|
|
185
|
-
const styles = StyleSheet.create({
|
|
186
|
-
container: {
|
|
187
|
-
justifyContent: 'center',
|
|
188
|
-
alignItems: 'center'
|
|
189
|
-
}
|
|
190
|
-
});
|
|
191
|
-
//# sourceMappingURL=CandyItem.js.map
|
|
1
|
+
"use strict";import React,{useEffect,useRef}from 'react';import{StyleSheet}from 'react-native';import{Gesture,GestureDetector}from 'react-native-gesture-handler';import Animated,{useSharedValue,useAnimatedStyle,withSpring,withTiming,runOnJS}from 'react-native-reanimated';import{Canvas,RoundedRect,Group,Shadow}from '@shopify/react-native-skia';import{CandyCrushService}from "../CandyCrushService.js";import{jsx as _jsx,jsxs as _jsxs}from "react/jsx-runtime";const gameService = new CandyCrushService();const CandyItemComponent =({candy,size,isSelected,isMatched,isFalling,onSwipe})=>{const translateX = useSharedValue(0);const translateY = useSharedValue(0);const scale = useSharedValue(1);const opacity = useSharedValue(1);const zIndex = useSharedValue(0);const prevMatchedRef = useRef(isMatched);const prevFallingRef = useRef(isFalling);const prevRowRef = useRef(candy.row);useEffect(()=>{if(isMatched && !prevMatchedRef.current){scale.value = withTiming(0,{duration:300});opacity.value = withTiming(0,{duration:300});}else if(!isMatched && prevMatchedRef.current){scale.value = 1;opacity.value = 1;}prevMatchedRef.current = isMatched;},[isMatched]);useEffect(()=>{const rowChanged = candy.row !== prevRowRef.current;if(isFalling && !prevFallingRef.current){scale.value = withSpring(1,{damping:8,stiffness:40});}else if(rowChanged && isFalling){scale.value = withSpring(1,{damping:8,stiffness:40});}prevFallingRef.current = isFalling;prevRowRef.current = candy.row;},[isFalling,candy.row]);const panGesture = Gesture.Pan().onStart(()=>{zIndex.value = 1000;scale.value = withSpring(1.1);}).onUpdate(event =>{translateX.value = event.translationX;translateY.value = event.translationY;}).onEnd(event =>{const threshold = size * 0.3;const absX = Math.abs(event.translationX);const absY = Math.abs(event.translationY);if(absX > threshold || absY > threshold){if(absX > absY){if(event.translationX > 0){runOnJS(onSwipe)('right');}else{runOnJS(onSwipe)('left');}}else{if(event.translationY > 0){runOnJS(onSwipe)('down');}else{runOnJS(onSwipe)('up');}}}translateX.value = withSpring(0);translateY.value = withSpring(0);scale.value = withSpring(1);zIndex.value = withTiming(0,{duration:300});});const candyColor = gameService.getCandyColor(candy.type);const borderRadius = 8;const animatedStyle = useAnimatedStyle(()=>({transform:[{translateX:translateX.value},{translateY:translateY.value},{scale:scale.value}],opacity:opacity.value,zIndex:zIndex.value}));return _jsx(GestureDetector,{gesture:panGesture,children:_jsx(Animated.View,{style:[styles.container,{width:size,height:size},animatedStyle],children:_jsx(Canvas,{style:{width:size,height:size},children:_jsxs(Group,{children:[_jsx(RoundedRect,{x:2,y:2,width:size - 4,height:size - 4,r:borderRadius,color:candyColor}),_jsx(RoundedRect,{x:size * 0.15,y:size * 0.15,width:size * 0.35,height:size * 0.35,r:6,color:"rgba(255,255,255,0.5)"}),_jsx(RoundedRect,{x:6,y:6,width:size - 12,height:size - 12,r:borderRadius - 2,color:"rgba(255,255,255,0.2)"}),isSelected && _jsx(RoundedRect,{x:1,y:1,width:size - 2,height:size - 2,r:borderRadius + 1,color:"transparent",style:"stroke",strokeWidth:3,children:_jsx(Shadow,{dx:0,dy:0,blur:6,color:"rgba(255,255,255,1)"})})]})})})});};export const CandyItem = React.memo(CandyItemComponent,(prevProps,nextProps)=>{return prevProps.candy.id === nextProps.candy.id && prevProps.candy.type === nextProps.candy.type && prevProps.candy.row === nextProps.candy.row && prevProps.candy.col === nextProps.candy.col && prevProps.isMatched === nextProps.isMatched && prevProps.isFalling === nextProps.isFalling && prevProps.isSelected === nextProps.isSelected && prevProps.size === nextProps.size;});CandyItem.displayName = 'CandyItem';const styles = StyleSheet.create({container:{justifyContent:'center',alignItems:'center'}});
|
|
@@ -1,85 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
import React from 'react';
|
|
4
|
-
import { Canvas, Rect, LinearGradient, vec, Circle, Path, Skia } from '@shopify/react-native-skia';
|
|
5
|
-
import { Dimensions } from 'react-native';
|
|
6
|
-
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
7
|
-
const {
|
|
8
|
-
width,
|
|
9
|
-
height
|
|
10
|
-
} = Dimensions.get('window');
|
|
11
|
-
|
|
12
|
-
// Memoize star paths outside component for better performance
|
|
13
|
-
const createStarPaths = () => {
|
|
14
|
-
return [...Array(15)].map((_, i) => {
|
|
15
|
-
const x = width * (i * 7 + 3) % width;
|
|
16
|
-
const y = height * (i * 11 + 5) % height;
|
|
17
|
-
const size = 3 + i % 3;
|
|
18
|
-
const starPath = Skia.Path.Make();
|
|
19
|
-
starPath.moveTo(x, y - size);
|
|
20
|
-
starPath.lineTo(x + size * 0.3, y + size * 0.3);
|
|
21
|
-
starPath.lineTo(x + size, y + size * 0.3);
|
|
22
|
-
starPath.lineTo(x + size * 0.5, y + size * 0.8);
|
|
23
|
-
starPath.lineTo(x + size * 0.7, y + size * 1.5);
|
|
24
|
-
starPath.lineTo(x, y + size);
|
|
25
|
-
starPath.lineTo(x - size * 0.7, y + size * 1.5);
|
|
26
|
-
starPath.lineTo(x - size * 0.5, y + size * 0.8);
|
|
27
|
-
starPath.lineTo(x - size, y + size * 0.3);
|
|
28
|
-
starPath.lineTo(x - size * 0.3, y + size * 0.3);
|
|
29
|
-
starPath.close();
|
|
30
|
-
return {
|
|
31
|
-
path: starPath,
|
|
32
|
-
opacity: 0.1 + i % 3 * 0.05
|
|
33
|
-
};
|
|
34
|
-
});
|
|
35
|
-
};
|
|
36
|
-
const starPaths = createStarPaths();
|
|
37
|
-
export const GameBackground = /*#__PURE__*/React.memo(({
|
|
38
|
-
children
|
|
39
|
-
}) => {
|
|
40
|
-
return /*#__PURE__*/_jsxs(_Fragment, {
|
|
41
|
-
children: [/*#__PURE__*/_jsxs(Canvas, {
|
|
42
|
-
style: {
|
|
43
|
-
position: 'absolute',
|
|
44
|
-
width,
|
|
45
|
-
height
|
|
46
|
-
},
|
|
47
|
-
children: [/*#__PURE__*/_jsx(Rect, {
|
|
48
|
-
x: 0,
|
|
49
|
-
y: 0,
|
|
50
|
-
width: width,
|
|
51
|
-
height: height,
|
|
52
|
-
children: /*#__PURE__*/_jsx(LinearGradient, {
|
|
53
|
-
start: vec(0, 0),
|
|
54
|
-
end: vec(0, height),
|
|
55
|
-
colors: ['#667eea', '#764ba2', '#f093fb']
|
|
56
|
-
})
|
|
57
|
-
}), /*#__PURE__*/_jsx(Circle, {
|
|
58
|
-
cx: width * 0.1,
|
|
59
|
-
cy: height * 0.15,
|
|
60
|
-
r: 60,
|
|
61
|
-
color: "rgba(255, 255, 255, 0.05)"
|
|
62
|
-
}), /*#__PURE__*/_jsx(Circle, {
|
|
63
|
-
cx: width * 0.85,
|
|
64
|
-
cy: height * 0.25,
|
|
65
|
-
r: 80,
|
|
66
|
-
color: "rgba(255, 255, 255, 0.05)"
|
|
67
|
-
}), /*#__PURE__*/_jsx(Circle, {
|
|
68
|
-
cx: width * 0.2,
|
|
69
|
-
cy: height * 0.7,
|
|
70
|
-
r: 50,
|
|
71
|
-
color: "rgba(255, 255, 255, 0.05)"
|
|
72
|
-
}), /*#__PURE__*/_jsx(Circle, {
|
|
73
|
-
cx: width * 0.9,
|
|
74
|
-
cy: height * 0.8,
|
|
75
|
-
r: 70,
|
|
76
|
-
color: "rgba(255, 255, 255, 0.05)"
|
|
77
|
-
}), starPaths.map((star, i) => /*#__PURE__*/_jsx(Path, {
|
|
78
|
-
path: star.path,
|
|
79
|
-
color: `rgba(255, 255, 255, ${star.opacity})`
|
|
80
|
-
}, i))]
|
|
81
|
-
}), children]
|
|
82
|
-
});
|
|
83
|
-
});
|
|
84
|
-
GameBackground.displayName = 'GameBackground';
|
|
85
|
-
//# sourceMappingURL=GameBackground.js.map
|
|
1
|
+
"use strict";import React from 'react';import{Canvas,Rect,LinearGradient,vec,Circle,Path,Skia}from '@shopify/react-native-skia';import{Dimensions}from 'react-native';import{jsx as _jsx,jsxs as _jsxs,Fragment as _Fragment}from "react/jsx-runtime";const{width,height}= Dimensions.get('window');const createStarPaths =()=>{return [...Array(15)].map((_,i)=>{const x = width *(i * 7 + 3)% width;const y = height *(i * 11 + 5)% height;const size = 3 + i % 3;const starPath = Skia.Path.Make();starPath.moveTo(x,y - size);starPath.lineTo(x + size * 0.3,y + size * 0.3);starPath.lineTo(x + size,y + size * 0.3);starPath.lineTo(x + size * 0.5,y + size * 0.8);starPath.lineTo(x + size * 0.7,y + size * 1.5);starPath.lineTo(x,y + size);starPath.lineTo(x - size * 0.7,y + size * 1.5);starPath.lineTo(x - size * 0.5,y + size * 0.8);starPath.lineTo(x - size,y + size * 0.3);starPath.lineTo(x - size * 0.3,y + size * 0.3);starPath.close();return{path:starPath,opacity:0.1 + i % 3 * 0.05};});};const starPaths = createStarPaths();export const GameBackground = React.memo(({children})=>{return _jsxs(_Fragment,{children:[_jsxs(Canvas,{style:{position:'absolute',width,height},children:[_jsx(Rect,{x:0,y:0,width:width,height:height,children:_jsx(LinearGradient,{start:vec(0,0),end:vec(0,height),colors:['#667eea','#764ba2','#f093fb']})}),_jsx(Circle,{cx:width * 0.1,cy:height * 0.15,r:60,color:"rgba(255,255,255,0.05)"}),_jsx(Circle,{cx:width * 0.85,cy:height * 0.25,r:80,color:"rgba(255,255,255,0.05)"}),_jsx(Circle,{cx:width * 0.2,cy:height * 0.7,r:50,color:"rgba(255,255,255,0.05)"}),_jsx(Circle,{cx:width * 0.9,cy:height * 0.8,r:70,color:"rgba(255,255,255,0.05)"}),starPaths.map((star,i)=> _jsx(Path,{path:star.path,color:`rgba(255,255,255,${star.opacity})`},i))]}),children]});});GameBackground.displayName = 'GameBackground';
|
|
@@ -1,314 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
import React, { useMemo, useRef, useEffect } from 'react';
|
|
4
|
-
import { View, StyleSheet, Dimensions } from 'react-native';
|
|
5
|
-
import { Canvas, RoundedRect, LinearGradient, vec, Shadow, Circle, Group } from '@shopify/react-native-skia';
|
|
6
|
-
import { useGrid, useSelectedCandy, useCandyCrushStore, useMatchedCandyIds, useFallingCandyIds } from "../CandyCrushStore.js";
|
|
7
|
-
import { CandyItem } from "./CandyItem.js";
|
|
8
|
-
import { CANDY_CRUSH_GAME_CONFIG, CANDY_CRUSH_COLORS } from "../CandyCrushConstants.js";
|
|
9
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
10
|
-
const {
|
|
11
|
-
width: screenWidth
|
|
12
|
-
} = Dimensions.get('window');
|
|
13
|
-
|
|
14
|
-
// Memoized GridRow component to prevent unnecessary re-renders
|
|
15
|
-
|
|
16
|
-
const GridRow = /*#__PURE__*/React.memo(({
|
|
17
|
-
row,
|
|
18
|
-
rowIndex,
|
|
19
|
-
candySize,
|
|
20
|
-
gap,
|
|
21
|
-
selectedCandyId,
|
|
22
|
-
matchedCandyIds,
|
|
23
|
-
fallingCandyIds,
|
|
24
|
-
onSwipe
|
|
25
|
-
}) => {
|
|
26
|
-
return /*#__PURE__*/_jsx(View, {
|
|
27
|
-
style: [styles.row, {
|
|
28
|
-
gap
|
|
29
|
-
}],
|
|
30
|
-
children: row.map((candy, colIndex) => {
|
|
31
|
-
if (!candy) {
|
|
32
|
-
return /*#__PURE__*/_jsx(View, {
|
|
33
|
-
style: [styles.cell, {
|
|
34
|
-
width: candySize,
|
|
35
|
-
height: candySize
|
|
36
|
-
}]
|
|
37
|
-
}, `empty-${rowIndex}-${colIndex}`);
|
|
38
|
-
}
|
|
39
|
-
const isSelected = selectedCandyId === candy.id;
|
|
40
|
-
const isMatched = matchedCandyIds.has(candy.id);
|
|
41
|
-
const isFalling = fallingCandyIds.has(candy.id);
|
|
42
|
-
const handleSwipe = direction => {
|
|
43
|
-
onSwipe(candy, direction);
|
|
44
|
-
};
|
|
45
|
-
return /*#__PURE__*/_jsx(View, {
|
|
46
|
-
style: [styles.cell, {
|
|
47
|
-
width: candySize,
|
|
48
|
-
height: candySize
|
|
49
|
-
}],
|
|
50
|
-
children: /*#__PURE__*/_jsx(CandyItem, {
|
|
51
|
-
candy: candy,
|
|
52
|
-
size: candySize,
|
|
53
|
-
isSelected: isSelected,
|
|
54
|
-
isMatched: isMatched,
|
|
55
|
-
isFalling: isFalling,
|
|
56
|
-
onSwipe: handleSwipe
|
|
57
|
-
})
|
|
58
|
-
}, candy.id);
|
|
59
|
-
})
|
|
60
|
-
}, `row-${rowIndex}`);
|
|
61
|
-
}, (prevProps, nextProps) => {
|
|
62
|
-
// If row array reference is the same, skip all checks (FASTEST PATH)
|
|
63
|
-
if (prevProps.row === nextProps.row) {
|
|
64
|
-
return true;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// Only re-render if row content actually changed
|
|
68
|
-
if (prevProps.row.length !== nextProps.row.length) return false;
|
|
69
|
-
if (prevProps.candySize !== nextProps.candySize) return false;
|
|
70
|
-
if (prevProps.gap !== nextProps.gap) return false;
|
|
71
|
-
|
|
72
|
-
// Only re-render if THIS ROW has the selected candy
|
|
73
|
-
const hadSelectedCandy = prevProps.row.some(c => c?.id === prevProps.selectedCandyId);
|
|
74
|
-
const hasSelectedCandy = nextProps.row.some(c => c?.id === nextProps.selectedCandyId);
|
|
75
|
-
if (hadSelectedCandy !== hasSelectedCandy || hadSelectedCandy && prevProps.selectedCandyId !== nextProps.selectedCandyId) {
|
|
76
|
-
return false;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// Check if any candy in THIS ROW is affected by matched/falling states
|
|
80
|
-
for (let i = 0; i < prevProps.row.length; i++) {
|
|
81
|
-
const candy = prevProps.row[i];
|
|
82
|
-
if (candy) {
|
|
83
|
-
const wasMatched = prevProps.matchedCandyIds.has(candy.id);
|
|
84
|
-
const isMatched = nextProps.matchedCandyIds.has(candy.id);
|
|
85
|
-
const wasFalling = prevProps.fallingCandyIds.has(candy.id);
|
|
86
|
-
const isFalling = nextProps.fallingCandyIds.has(candy.id);
|
|
87
|
-
if (wasMatched !== isMatched || wasFalling !== isFalling) {
|
|
88
|
-
return false;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// Check if any candy in the row changed
|
|
94
|
-
for (let i = 0; i < prevProps.row.length; i++) {
|
|
95
|
-
const prevCandy = prevProps.row[i];
|
|
96
|
-
const nextCandy = nextProps.row[i];
|
|
97
|
-
if (prevCandy?.id !== nextCandy?.id) return false;
|
|
98
|
-
if (prevCandy?.type !== nextCandy?.type) return false;
|
|
99
|
-
if (prevCandy?.row !== nextCandy?.row) return false;
|
|
100
|
-
if (prevCandy?.col !== nextCandy?.col) return false;
|
|
101
|
-
}
|
|
102
|
-
return true;
|
|
103
|
-
});
|
|
104
|
-
export const GameGrid = /*#__PURE__*/React.memo(() => {
|
|
105
|
-
const grid = useGrid();
|
|
106
|
-
const selectedCandy = useSelectedCandy();
|
|
107
|
-
const matchedCandyIds = useMatchedCandyIds();
|
|
108
|
-
const fallingCandyIds = useFallingCandyIds();
|
|
109
|
-
const selectCandy = useCandyCrushStore(state => state.selectCandy);
|
|
110
|
-
const selectedCandyId = selectedCandy?.id || null;
|
|
111
|
-
|
|
112
|
-
// Use ref to store grid without causing re-renders
|
|
113
|
-
const gridRef = useRef(grid);
|
|
114
|
-
useEffect(() => {
|
|
115
|
-
gridRef.current = grid;
|
|
116
|
-
}, [grid]);
|
|
117
|
-
|
|
118
|
-
// Handle swipe with stable reference (doesn't change on grid updates)
|
|
119
|
-
const handleSwipe = React.useCallback((candy, direction) => {
|
|
120
|
-
const currentGrid = gridRef.current;
|
|
121
|
-
let targetRow = candy.row;
|
|
122
|
-
let targetCol = candy.col;
|
|
123
|
-
switch (direction) {
|
|
124
|
-
case 'up':
|
|
125
|
-
targetRow = candy.row - 1;
|
|
126
|
-
break;
|
|
127
|
-
case 'down':
|
|
128
|
-
targetRow = candy.row + 1;
|
|
129
|
-
break;
|
|
130
|
-
case 'left':
|
|
131
|
-
targetCol = candy.col - 1;
|
|
132
|
-
break;
|
|
133
|
-
case 'right':
|
|
134
|
-
targetCol = candy.col + 1;
|
|
135
|
-
break;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// Check if target is within bounds
|
|
139
|
-
if (targetRow >= 0 && targetRow < currentGrid.length && targetCol >= 0 && currentGrid[0] && targetCol < currentGrid[0].length) {
|
|
140
|
-
const targetRowData = currentGrid[targetRow];
|
|
141
|
-
if (targetRowData) {
|
|
142
|
-
const targetCandy = targetRowData[targetCol];
|
|
143
|
-
if (targetCandy) {
|
|
144
|
-
// Simulate selecting source candy then target candy
|
|
145
|
-
selectCandy(candy);
|
|
146
|
-
setTimeout(() => selectCandy(targetCandy), 50);
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
}, [selectCandy]);
|
|
151
|
-
|
|
152
|
-
// Calculate grid dimensions (memoized once)
|
|
153
|
-
const gridCalculations = useMemo(() => {
|
|
154
|
-
const horizontalPadding = 40;
|
|
155
|
-
const availableWidth = screenWidth - horizontalPadding;
|
|
156
|
-
const gridSize = CANDY_CRUSH_GAME_CONFIG.GRID_SIZE;
|
|
157
|
-
const gap = 2;
|
|
158
|
-
const totalGaps = (gridSize - 1) * gap;
|
|
159
|
-
const candySize = (availableWidth - totalGaps) / gridSize;
|
|
160
|
-
const padding = 10; // Adjusted padding
|
|
161
|
-
|
|
162
|
-
// Calculate actual content dimensions
|
|
163
|
-
const contentWidth = Math.floor(candySize) * gridSize + totalGaps;
|
|
164
|
-
const contentHeight = Math.floor(candySize) * gridSize + totalGaps;
|
|
165
|
-
|
|
166
|
-
// Grid dimensions including padding and border
|
|
167
|
-
const gridWidth = contentWidth + padding * 2;
|
|
168
|
-
const gridHeight = contentHeight + padding * 2;
|
|
169
|
-
return {
|
|
170
|
-
candySize: Math.floor(candySize),
|
|
171
|
-
gap,
|
|
172
|
-
gridSize,
|
|
173
|
-
gridWidth,
|
|
174
|
-
gridHeight
|
|
175
|
-
};
|
|
176
|
-
}, []);
|
|
177
|
-
const {
|
|
178
|
-
candySize,
|
|
179
|
-
gap,
|
|
180
|
-
gridWidth,
|
|
181
|
-
gridHeight
|
|
182
|
-
} = gridCalculations;
|
|
183
|
-
|
|
184
|
-
// Generate jelly bubbles
|
|
185
|
-
const jellyBubbles = useMemo(() => {
|
|
186
|
-
const bubbles = [];
|
|
187
|
-
const bubbleCount = 25;
|
|
188
|
-
for (let i = 0; i < bubbleCount; i++) {
|
|
189
|
-
bubbles.push({
|
|
190
|
-
x: Math.random() * gridWidth,
|
|
191
|
-
y: Math.random() * gridHeight,
|
|
192
|
-
radius: Math.random() * 15 + 5,
|
|
193
|
-
opacity: Math.random() * 0.15 + 0.05
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
|
-
return bubbles;
|
|
197
|
-
}, [gridWidth, gridHeight]);
|
|
198
|
-
return /*#__PURE__*/_jsxs(View, {
|
|
199
|
-
style: styles.container,
|
|
200
|
-
children: [/*#__PURE__*/_jsx(View, {
|
|
201
|
-
style: [styles.jellyContainer, {
|
|
202
|
-
width: gridWidth,
|
|
203
|
-
height: gridHeight
|
|
204
|
-
}],
|
|
205
|
-
children: /*#__PURE__*/_jsxs(Canvas, {
|
|
206
|
-
style: {
|
|
207
|
-
width: gridWidth,
|
|
208
|
-
height: gridHeight
|
|
209
|
-
},
|
|
210
|
-
children: [/*#__PURE__*/_jsxs(RoundedRect, {
|
|
211
|
-
x: 0,
|
|
212
|
-
y: 0,
|
|
213
|
-
width: gridWidth,
|
|
214
|
-
height: gridHeight,
|
|
215
|
-
r: 15,
|
|
216
|
-
children: [/*#__PURE__*/_jsx(LinearGradient, {
|
|
217
|
-
start: vec(0, 0),
|
|
218
|
-
end: vec(gridWidth, gridHeight),
|
|
219
|
-
colors: ['rgba(255, 149, 0, 0.35)', 'rgba(255, 120, 0, 0.25)', 'rgba(255, 149, 0, 0.3)']
|
|
220
|
-
}), /*#__PURE__*/_jsx(Shadow, {
|
|
221
|
-
dx: 0,
|
|
222
|
-
dy: 6,
|
|
223
|
-
blur: 12,
|
|
224
|
-
color: "rgba(255, 100, 0, 0.4)",
|
|
225
|
-
inner: true
|
|
226
|
-
})]
|
|
227
|
-
}), /*#__PURE__*/_jsx(Group, {
|
|
228
|
-
children: jellyBubbles.map((bubble, index) => /*#__PURE__*/_jsx(Circle, {
|
|
229
|
-
cx: bubble.x,
|
|
230
|
-
cy: bubble.y,
|
|
231
|
-
r: bubble.radius,
|
|
232
|
-
color: `rgba(255, 255, 255, ${bubble.opacity})`
|
|
233
|
-
}, index))
|
|
234
|
-
}), /*#__PURE__*/_jsx(RoundedRect, {
|
|
235
|
-
x: 5,
|
|
236
|
-
y: 5,
|
|
237
|
-
width: gridWidth - 10,
|
|
238
|
-
height: gridHeight - 10,
|
|
239
|
-
r: 12,
|
|
240
|
-
children: /*#__PURE__*/_jsx(LinearGradient, {
|
|
241
|
-
start: vec(0, 0),
|
|
242
|
-
end: vec(0, gridHeight),
|
|
243
|
-
colors: ['rgba(255, 200, 100, 0.3)', 'rgba(255, 149, 0, 0)', 'rgba(255, 180, 80, 0.2)']
|
|
244
|
-
})
|
|
245
|
-
}), /*#__PURE__*/_jsx(RoundedRect, {
|
|
246
|
-
x: 15,
|
|
247
|
-
y: 15,
|
|
248
|
-
width: gridWidth - 30,
|
|
249
|
-
height: gridHeight * 0.25,
|
|
250
|
-
r: 8,
|
|
251
|
-
children: /*#__PURE__*/_jsx(LinearGradient, {
|
|
252
|
-
start: vec(0, 0),
|
|
253
|
-
end: vec(0, gridHeight * 0.25),
|
|
254
|
-
colors: ['rgba(255, 255, 255, 0.5)', 'rgba(255, 255, 255, 0)']
|
|
255
|
-
})
|
|
256
|
-
}), /*#__PURE__*/_jsx(RoundedRect, {
|
|
257
|
-
x: 15,
|
|
258
|
-
y: gridHeight * 0.75,
|
|
259
|
-
width: gridWidth - 30,
|
|
260
|
-
height: gridHeight * 0.2,
|
|
261
|
-
r: 8,
|
|
262
|
-
children: /*#__PURE__*/_jsx(LinearGradient, {
|
|
263
|
-
start: vec(0, 0),
|
|
264
|
-
end: vec(0, gridHeight * 0.2),
|
|
265
|
-
colors: ['rgba(0, 0, 0, 0)', 'rgba(255, 100, 0, 0.2)']
|
|
266
|
-
})
|
|
267
|
-
})]
|
|
268
|
-
})
|
|
269
|
-
}), /*#__PURE__*/_jsx(View, {
|
|
270
|
-
style: [styles.grid, {
|
|
271
|
-
gap
|
|
272
|
-
}],
|
|
273
|
-
children: grid.map((row, rowIndex) => /*#__PURE__*/_jsx(GridRow, {
|
|
274
|
-
row: row,
|
|
275
|
-
rowIndex: rowIndex,
|
|
276
|
-
candySize: candySize,
|
|
277
|
-
gap: gap,
|
|
278
|
-
selectedCandyId: selectedCandyId,
|
|
279
|
-
matchedCandyIds: matchedCandyIds,
|
|
280
|
-
fallingCandyIds: fallingCandyIds,
|
|
281
|
-
onSwipe: handleSwipe
|
|
282
|
-
}, rowIndex))
|
|
283
|
-
})]
|
|
284
|
-
});
|
|
285
|
-
});
|
|
286
|
-
GameGrid.displayName = 'GameGrid';
|
|
287
|
-
const styles = StyleSheet.create({
|
|
288
|
-
container: {
|
|
289
|
-
flex: 1,
|
|
290
|
-
justifyContent: 'center',
|
|
291
|
-
alignItems: 'center',
|
|
292
|
-
position: 'relative'
|
|
293
|
-
},
|
|
294
|
-
jellyContainer: {
|
|
295
|
-
position: 'absolute',
|
|
296
|
-
borderRadius: 15,
|
|
297
|
-
borderWidth: 3,
|
|
298
|
-
borderColor: CANDY_CRUSH_COLORS.GRID_BORDER,
|
|
299
|
-
overflow: 'hidden'
|
|
300
|
-
},
|
|
301
|
-
grid: {
|
|
302
|
-
padding: 13,
|
|
303
|
-
// 10px padding + 3px border
|
|
304
|
-
zIndex: 1
|
|
305
|
-
},
|
|
306
|
-
row: {
|
|
307
|
-
flexDirection: 'row'
|
|
308
|
-
},
|
|
309
|
-
cell: {
|
|
310
|
-
justifyContent: 'center',
|
|
311
|
-
alignItems: 'center'
|
|
312
|
-
}
|
|
313
|
-
});
|
|
314
|
-
//# sourceMappingURL=GameGrid.js.map
|
|
1
|
+
"use strict";import React,{useMemo,useRef,useEffect}from 'react';import{View,StyleSheet,Dimensions}from 'react-native';import{Canvas,RoundedRect,LinearGradient,vec,Shadow,Circle,Group}from '@shopify/react-native-skia';import{useGrid,useSelectedCandy,useCandyCrushStore,useMatchedCandyIds,useFallingCandyIds}from "../CandyCrushStore.js";import{CandyItem}from "./CandyItem.js";import{CANDY_CRUSH_GAME_CONFIG,CANDY_CRUSH_COLORS}from "../CandyCrushConstants.js";import{jsx as _jsx,jsxs as _jsxs}from "react/jsx-runtime";const{width:screenWidth}= Dimensions.get('window');const GridRow = React.memo(({row,rowIndex,candySize,gap,selectedCandyId,matchedCandyIds,fallingCandyIds,onSwipe})=>{return _jsx(View,{style:[styles.row,{gap}],children:row.map((candy,colIndex)=>{if(!candy){return _jsx(View,{style:[styles.cell,{width:candySize,height:candySize}]},`empty-${rowIndex}-${colIndex}`);}const isSelected = selectedCandyId === candy.id;const isMatched = matchedCandyIds.has(candy.id);const isFalling = fallingCandyIds.has(candy.id);const handleSwipe = direction =>{onSwipe(candy,direction);};return _jsx(View,{style:[styles.cell,{width:candySize,height:candySize}],children:_jsx(CandyItem,{candy:candy,size:candySize,isSelected:isSelected,isMatched:isMatched,isFalling:isFalling,onSwipe:handleSwipe})},candy.id);})},`row-${rowIndex}`);},(prevProps,nextProps)=>{if(prevProps.row === nextProps.row){return true;}if(prevProps.row.length !== nextProps.row.length)return false;if(prevProps.candySize !== nextProps.candySize)return false;if(prevProps.gap !== nextProps.gap)return false;const hadSelectedCandy = prevProps.row.some(c => c?.id === prevProps.selectedCandyId);const hasSelectedCandy = nextProps.row.some(c => c?.id === nextProps.selectedCandyId);if(hadSelectedCandy !== hasSelectedCandy || hadSelectedCandy && prevProps.selectedCandyId !== nextProps.selectedCandyId){return false;}for(let i = 0;i < prevProps.row.length;i++){const candy = prevProps.row[i];if(candy){const wasMatched = prevProps.matchedCandyIds.has(candy.id);const isMatched = nextProps.matchedCandyIds.has(candy.id);const wasFalling = prevProps.fallingCandyIds.has(candy.id);const isFalling = nextProps.fallingCandyIds.has(candy.id);if(wasMatched !== isMatched || wasFalling !== isFalling){return false;}}}for(let i = 0;i < prevProps.row.length;i++){const prevCandy = prevProps.row[i];const nextCandy = nextProps.row[i];if(prevCandy?.id !== nextCandy?.id)return false;if(prevCandy?.type !== nextCandy?.type)return false;if(prevCandy?.row !== nextCandy?.row)return false;if(prevCandy?.col !== nextCandy?.col)return false;}return true;});export const GameGrid = React.memo(()=>{const grid = useGrid();const selectedCandy = useSelectedCandy();const matchedCandyIds = useMatchedCandyIds();const fallingCandyIds = useFallingCandyIds();const selectCandy = useCandyCrushStore(state => state.selectCandy);const selectedCandyId = selectedCandy?.id || null;const gridRef = useRef(grid);useEffect(()=>{gridRef.current = grid;},[grid]);const handleSwipe = React.useCallback((candy,direction)=>{const currentGrid = gridRef.current;let targetRow = candy.row;let targetCol = candy.col;switch(direction){case 'up':targetRow = candy.row - 1;break;case 'down':targetRow = candy.row + 1;break;case 'left':targetCol = candy.col - 1;break;case 'right':targetCol = candy.col + 1;break;}if(targetRow >= 0 && targetRow < currentGrid.length && targetCol >= 0 && currentGrid[0] && targetCol < currentGrid[0].length){const targetRowData = currentGrid[targetRow];if(targetRowData){const targetCandy = targetRowData[targetCol];if(targetCandy){selectCandy(candy);setTimeout(()=> selectCandy(targetCandy),50);}}}},[selectCandy]);const gridCalculations = useMemo(()=>{const horizontalPadding = 40;const availableWidth = screenWidth - horizontalPadding;const gridSize = CANDY_CRUSH_GAME_CONFIG.GRID_SIZE;const gap = 2;const totalGaps =(gridSize - 1)* gap;const candySize =(availableWidth - totalGaps)/ gridSize;const padding = 10;const contentWidth = Math.floor(candySize)* gridSize + totalGaps;const contentHeight = Math.floor(candySize)* gridSize + totalGaps;const gridWidth = contentWidth + padding * 2;const gridHeight = contentHeight + padding * 2;return{candySize:Math.floor(candySize),gap,gridSize,gridWidth,gridHeight};},[]);const{candySize,gap,gridWidth,gridHeight}= gridCalculations;const jellyBubbles = useMemo(()=>{const bubbles = [];const bubbleCount = 25;for(let i = 0;i < bubbleCount;i++){bubbles.push({x:Math.random()* gridWidth,y:Math.random()* gridHeight,radius:Math.random()* 15 + 5,opacity:Math.random()* 0.15 + 0.05});}return bubbles;},[gridWidth,gridHeight]);return _jsxs(View,{style:styles.container,children:[_jsx(View,{style:[styles.jellyContainer,{width:gridWidth,height:gridHeight}],children:_jsxs(Canvas,{style:{width:gridWidth,height:gridHeight},children:[_jsxs(RoundedRect,{x:0,y:0,width:gridWidth,height:gridHeight,r:15,children:[_jsx(LinearGradient,{start:vec(0,0),end:vec(gridWidth,gridHeight),colors:['rgba(255,149,0,0.35)','rgba(255,120,0,0.25)','rgba(255,149,0,0.3)']}),_jsx(Shadow,{dx:0,dy:6,blur:12,color:"rgba(255,100,0,0.4)",inner:true})]}),_jsx(Group,{children:jellyBubbles.map((bubble,index)=> _jsx(Circle,{cx:bubble.x,cy:bubble.y,r:bubble.radius,color:`rgba(255,255,255,${bubble.opacity})`},index))}),_jsx(RoundedRect,{x:5,y:5,width:gridWidth - 10,height:gridHeight - 10,r:12,children:_jsx(LinearGradient,{start:vec(0,0),end:vec(0,gridHeight),colors:['rgba(255,200,100,0.3)','rgba(255,149,0,0)','rgba(255,180,80,0.2)']})}),_jsx(RoundedRect,{x:15,y:15,width:gridWidth - 30,height:gridHeight * 0.25,r:8,children:_jsx(LinearGradient,{start:vec(0,0),end:vec(0,gridHeight * 0.25),colors:['rgba(255,255,255,0.5)','rgba(255,255,255,0)']})}),_jsx(RoundedRect,{x:15,y:gridHeight * 0.75,width:gridWidth - 30,height:gridHeight * 0.2,r:8,children:_jsx(LinearGradient,{start:vec(0,0),end:vec(0,gridHeight * 0.2),colors:['rgba(0,0,0,0)','rgba(255,100,0,0.2)']})})]})}),_jsx(View,{style:[styles.grid,{gap}],children:grid.map((row,rowIndex)=> _jsx(GridRow,{row:row,rowIndex:rowIndex,candySize:candySize,gap:gap,selectedCandyId:selectedCandyId,matchedCandyIds:matchedCandyIds,fallingCandyIds:fallingCandyIds,onSwipe:handleSwipe},rowIndex))})]});});GameGrid.displayName = 'GameGrid';const styles = StyleSheet.create({container:{flex:1,justifyContent:'center',alignItems:'center',position:'relative'},jellyContainer:{position:'absolute',borderRadius:15,borderWidth:3,borderColor:CANDY_CRUSH_COLORS.GRID_BORDER,overflow:'hidden'},grid:{padding:13,zIndex:1},row:{flexDirection:'row'},cell:{justifyContent:'center',alignItems:'center'}});
|