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.
Files changed (212) hide show
  1. package/README.md +80 -368
  2. package/lib/module/games/balloon-blaster/BalloonBlaster.js +1 -167
  3. package/lib/module/games/balloon-blaster/BalloonBlaster.js.map +1 -1
  4. package/lib/module/games/balloon-blaster/BalloonBlasterConstants.js +1 -182
  5. package/lib/module/games/balloon-blaster/BalloonBlasterConstants.js.map +1 -1
  6. package/lib/module/games/balloon-blaster/BalloonBlasterService.js +1 -318
  7. package/lib/module/games/balloon-blaster/BalloonBlasterStore.js +1 -183
  8. package/lib/module/games/balloon-blaster/components/BalloonComponent.js +1 -237
  9. package/lib/module/games/balloon-blaster/components/GameArea.js +1 -156
  10. package/lib/module/games/balloon-blaster/components/GameBackground.js +1 -476
  11. package/lib/module/games/balloon-blaster/components/ScoreBoard.js +1 -112
  12. package/lib/module/games/balloon-blaster/components/ScoreBoard.js.map +1 -1
  13. package/lib/module/games/balloon-blaster/components/index.js +1 -7
  14. package/lib/module/games/candy-crush/CandyCrush.js +1 -131
  15. package/lib/module/games/candy-crush/CandyCrush.js.map +1 -1
  16. package/lib/module/games/candy-crush/CandyCrushConstants.js +1 -125
  17. package/lib/module/games/candy-crush/CandyCrushConstants.js.map +1 -1
  18. package/lib/module/games/candy-crush/CandyCrushService.js +1 -370
  19. package/lib/module/games/candy-crush/CandyCrushStore.js +1 -303
  20. package/lib/module/games/candy-crush/components/CandyItem.js +1 -191
  21. package/lib/module/games/candy-crush/components/GameBackground.js +1 -85
  22. package/lib/module/games/candy-crush/components/GameGrid.js +1 -314
  23. package/lib/module/games/candy-crush/components/ScoreBoard.js +1 -79
  24. package/lib/module/games/candy-crush/components/index.js +1 -7
  25. package/lib/module/games/candy-crush/index.js +1 -6
  26. package/lib/module/games/colors-sort/ColorsSort.js +1 -143
  27. package/lib/module/games/colors-sort/ColorsSort.js.map +1 -1
  28. package/lib/module/games/colors-sort/ColorsSortConstants.js +1 -72
  29. package/lib/module/games/colors-sort/ColorsSortConstants.js.map +1 -1
  30. package/lib/module/games/colors-sort/ColorsSortService.js +1 -255
  31. package/lib/module/games/colors-sort/ColorsSortStore.js +1 -257
  32. package/lib/module/games/colors-sort/ColorsSortStore.js.map +1 -1
  33. package/lib/module/games/colors-sort/components/ColorContainer.js +1 -140
  34. package/lib/module/games/colors-sort/components/GameBackground.js +1 -135
  35. package/lib/module/games/colors-sort/components/ScoreBoard.js +1 -70
  36. package/lib/module/games/colors-sort/components/index.js +1 -6
  37. package/lib/module/games/dino-jump/DinoJump.js +1 -209
  38. package/lib/module/games/dino-jump/DinoJump.js.map +1 -1
  39. package/lib/module/games/dino-jump/DinoJumpConstants.js +1 -189
  40. package/lib/module/games/dino-jump/DinoJumpConstants.js.map +1 -1
  41. package/lib/module/games/dino-jump/DinoJumpService.js +1 -270
  42. package/lib/module/games/dino-jump/DinoJumpStore.js +1 -381
  43. package/lib/module/games/dino-jump/components/DinoSprite.js +1 -418
  44. package/lib/module/games/dino-jump/components/DinoSprite.js.map +1 -1
  45. package/lib/module/games/dino-jump/components/GameArea.js +1 -68
  46. package/lib/module/games/dino-jump/components/GameBackground.js +1 -444
  47. package/lib/module/games/dino-jump/components/ObstacleSprite.js +1 -306
  48. package/lib/module/games/dino-jump/components/ScoreBoard.js +1 -105
  49. package/lib/module/games/dino-jump/components/ScoreBoard.js.map +1 -1
  50. package/lib/module/games/dino-jump/components/StarSprite.js +1 -45
  51. package/lib/module/games/dino-jump/components/index.js +1 -9
  52. package/lib/module/games/flappy-bird/FlappyBird.js +1 -126
  53. package/lib/module/games/flappy-bird/FlappyBird.js.map +1 -1
  54. package/lib/module/games/flappy-bird/FlappyBirdConstants.js +1 -90
  55. package/lib/module/games/flappy-bird/FlappyBirdConstants.js.map +1 -1
  56. package/lib/module/games/flappy-bird/FlappyBirdStore.js +1 -300
  57. package/lib/module/games/flappy-bird/components/Bird.js +1 -87
  58. package/lib/module/games/flappy-bird/components/GameArea.js +1 -87
  59. package/lib/module/games/flappy-bird/components/GameBackground.js +1 -79
  60. package/lib/module/games/flappy-bird/components/Pipes.js +1 -172
  61. package/lib/module/games/flappy-bird/components/ScoreBoard.js +1 -73
  62. package/lib/module/games/flappy-bird/components/index.js +1 -8
  63. package/lib/module/games/fruit-merger/FruitMerger.js +1 -120
  64. package/lib/module/games/fruit-merger/FruitMerger.js.map +1 -1
  65. package/lib/module/games/fruit-merger/FruitMergerConstants.js +1 -119
  66. package/lib/module/games/fruit-merger/FruitMergerConstants.js.map +1 -1
  67. package/lib/module/games/fruit-merger/FruitMergerService.js +1 -13
  68. package/lib/module/games/fruit-merger/FruitMergerStore.js +1 -315
  69. package/lib/module/games/fruit-merger/components/FruitItem.js +1 -102
  70. package/lib/module/games/fruit-merger/components/GameArea.js +1 -103
  71. package/lib/module/games/fruit-merger/components/GameBackground.js +1 -498
  72. package/lib/module/games/fruit-merger/components/ScoreBoard.js +1 -58
  73. package/lib/module/games/fruit-merger/components/index.js +1 -7
  74. package/lib/module/games/fruit-ninja/FruitNinja.js +1 -134
  75. package/lib/module/games/fruit-ninja/FruitNinja.js.map +1 -1
  76. package/lib/module/games/fruit-ninja/FruitNinjaConstants.js +1 -148
  77. package/lib/module/games/fruit-ninja/FruitNinjaConstants.js.map +1 -1
  78. package/lib/module/games/fruit-ninja/FruitNinjaService.js +1 -311
  79. package/lib/module/games/fruit-ninja/FruitNinjaStore.js +1 -191
  80. package/lib/module/games/fruit-ninja/FruitNinjaStore.js.map +1 -1
  81. package/lib/module/games/fruit-ninja/components/FruitComponent.js +1 -99
  82. package/lib/module/games/fruit-ninja/components/GameArea.js +1 -215
  83. package/lib/module/games/fruit-ninja/components/GameBackground.js +1 -1267
  84. package/lib/module/games/fruit-ninja/components/ScoreBoard.js +1 -92
  85. package/lib/module/games/fruit-ninja/components/ScoreBoard.js.map +1 -1
  86. package/lib/module/games/fruit-ninja/components/index.js +1 -7
  87. package/lib/module/games/game-2048/Game2048.js +1 -149
  88. package/lib/module/games/game-2048/Game2048.js.map +1 -1
  89. package/lib/module/games/game-2048/Game2048Constants.js +1 -263
  90. package/lib/module/games/game-2048/Game2048Constants.js.map +1 -1
  91. package/lib/module/games/game-2048/Game2048Service.js +1 -457
  92. package/lib/module/games/game-2048/Game2048Store.js +1 -236
  93. package/lib/module/games/game-2048/components/GameBackground.js +1 -247
  94. package/lib/module/games/game-2048/components/GameGrid.js +1 -139
  95. package/lib/module/games/game-2048/components/GameTile.js +1 -72
  96. package/lib/module/games/game-2048/components/ScoreBoard.js +1 -52
  97. package/lib/module/games/game-2048/components/index.js +1 -7
  98. package/lib/module/games/maze-runner/MazeRunner.js +1 -267
  99. package/lib/module/games/maze-runner/MazeRunner.js.map +1 -1
  100. package/lib/module/games/maze-runner/MazeRunnerConstants.js +1 -100
  101. package/lib/module/games/maze-runner/MazeRunnerConstants.js.map +1 -1
  102. package/lib/module/games/maze-runner/MazeRunnerService.js +1 -586
  103. package/lib/module/games/maze-runner/components/EnhancedBallComponent.js +1 -150
  104. package/lib/module/games/maze-runner/components/EnhancedGameArea.js +1 -370
  105. package/lib/module/games/maze-runner/components/GameBackground.js +1 -175
  106. package/lib/module/games/maze-runner/components/ScoreBoard.js +1 -61
  107. package/lib/module/games/maze-runner/components/SkiaPipeComponent.js +1 -209
  108. package/lib/module/games/maze-runner/components/StaticGameBackground.js +1 -169
  109. package/lib/module/games/maze-runner/components/WallComponent.js +1 -91
  110. package/lib/module/games/maze-runner/components/index.js +1 -8
  111. package/lib/module/games/popit-fidget/PopitFidget.js +1 -285
  112. package/lib/module/games/popit-fidget/PopitFidget.js.map +1 -1
  113. package/lib/module/games/popit-fidget/PopitFidgetConstants.js +1 -113
  114. package/lib/module/games/popit-fidget/PopitFidgetConstants.js.map +1 -1
  115. package/lib/module/games/popit-fidget/PopitFidgetService.js +1 -132
  116. package/lib/module/games/popit-fidget/PopitFidgetStore.js +1 -125
  117. package/lib/module/games/popit-fidget/components/BubbleComponent.js +1 -198
  118. package/lib/module/games/popit-fidget/components/FidgetGrid.js +1 -165
  119. package/lib/module/games/popit-fidget/components/GameBackground.js +1 -177
  120. package/lib/module/games/popit-fidget/components/ScoreBoard.js +1 -61
  121. package/lib/module/games/popit-fidget/components/index.js +1 -7
  122. package/lib/module/games/sliding-numbers/SlidingNumbers.js +1 -159
  123. package/lib/module/games/sliding-numbers/SlidingNumbers.js.map +1 -1
  124. package/lib/module/games/sliding-numbers/SlidingNumbersConstants.js +1 -207
  125. package/lib/module/games/sliding-numbers/SlidingNumbersConstants.js.map +1 -1
  126. package/lib/module/games/sliding-numbers/SlidingNumbersService.js +1 -248
  127. package/lib/module/games/sliding-numbers/SlidingNumbersStore.js +1 -274
  128. package/lib/module/games/sliding-numbers/components/GameBackground.js +1 -259
  129. package/lib/module/games/sliding-numbers/components/NumbersGrid.js +1 -174
  130. package/lib/module/games/sliding-numbers/components/NumbersTile.js +1 -116
  131. package/lib/module/games/sliding-numbers/components/ScoreBoard.js +1 -64
  132. package/lib/module/games/sliding-numbers/components/index.js +1 -7
  133. package/lib/module/games/snake/Snake.js +1 -189
  134. package/lib/module/games/snake/Snake.js.map +1 -1
  135. package/lib/module/games/snake/SnakeConstants.js +1 -138
  136. package/lib/module/games/snake/SnakeConstants.js.map +1 -1
  137. package/lib/module/games/snake/SnakeService.js +1 -148
  138. package/lib/module/games/snake/SnakeStore.js +1 -182
  139. package/lib/module/games/snake/components/GameBackground.js +1 -221
  140. package/lib/module/games/snake/components/GameGrid.js +1 -153
  141. package/lib/module/games/snake/components/ScoreBoard.js +1 -51
  142. package/lib/module/games/snake/components/index.js +1 -6
  143. package/lib/module/games/snake/index.js +1 -6
  144. package/lib/module/games/space-fighter/SpaceFighter.js +1 -165
  145. package/lib/module/games/space-fighter/SpaceFighter.js.map +1 -1
  146. package/lib/module/games/space-fighter/SpaceFighterConstants.js +1 -108
  147. package/lib/module/games/space-fighter/SpaceFighterConstants.js.map +1 -1
  148. package/lib/module/games/space-fighter/SpaceFighterService.js +1 -326
  149. package/lib/module/games/space-fighter/SpaceFighterStore.js +1 -209
  150. package/lib/module/games/space-fighter/components/AsteroidComponent.js +1 -113
  151. package/lib/module/games/space-fighter/components/GameArea.js +1 -289
  152. package/lib/module/games/space-fighter/components/GameBackground.js +1 -239
  153. package/lib/module/games/space-fighter/components/ScoreBoard.js +1 -136
  154. package/lib/module/games/space-fighter/components/Spacecraft3D.js +1 -202
  155. package/lib/module/games/space-fighter/components/SpacecraftPath.js +1 -52
  156. package/lib/module/games/space-fighter/components/index.js +1 -9
  157. package/lib/module/games/whack-a-mole/WhackAMole.js +1 -270
  158. package/lib/module/games/whack-a-mole/WhackAMole.js.map +1 -1
  159. package/lib/module/games/whack-a-mole/WhackAMoleConstants.js +1 -115
  160. package/lib/module/games/whack-a-mole/WhackAMoleConstants.js.map +1 -1
  161. package/lib/module/games/whack-a-mole/WhackAMoleService.js +1 -120
  162. package/lib/module/games/whack-a-mole/WhackAMoleStore.js +1 -172
  163. package/lib/module/games/whack-a-mole/components/GameBackground.js +1 -477
  164. package/lib/module/games/whack-a-mole/components/GameGrid.js +1 -97
  165. package/lib/module/games/whack-a-mole/components/GameHole.js +1 -196
  166. package/lib/module/games/whack-a-mole/components/MoleCharacter.js +1 -241
  167. package/lib/module/games/whack-a-mole/components/ScoreBoard.js +1 -67
  168. package/lib/module/games/whack-a-mole/components/ScoreBoard.js.map +1 -1
  169. package/lib/module/games/whack-a-mole/components/index.js +1 -8
  170. package/lib/module/helpers/AnimationFrame.js +1 -120
  171. package/lib/module/helpers/AnimationTracker.js +1 -89
  172. package/lib/module/helpers/ErrorHandler.js +1 -269
  173. package/lib/module/helpers/GameControlButton.js +1 -219
  174. package/lib/module/helpers/GameOverModal.js +1 -144
  175. package/lib/module/helpers/GameOverModal.js.map +1 -1
  176. package/lib/module/helpers/GameSettingsModal.js +1 -287
  177. package/lib/module/helpers/ParticleBlast.js +1 -134
  178. package/lib/module/helpers/ScoreBoardContainer.js +1 -34
  179. package/lib/module/helpers/index.js +1 -12
  180. package/lib/module/index.js +1 -22
  181. package/lib/module/services/GamesConstants.js +1 -178
  182. package/lib/module/services/GamesService.js +1 -112
  183. package/lib/module/services/GamesService.js.map +1 -1
  184. package/lib/module/services/HapticsService.js +1 -77
  185. package/lib/module/services/SoundsService.js +1 -302
  186. package/lib/module/services/UtilsService.js +1 -32
  187. package/lib/typescript/src/games/balloon-blaster/BalloonBlaster.d.ts.map +1 -1
  188. package/lib/typescript/src/games/balloon-blaster/BalloonBlasterConstants.d.ts +1 -1
  189. package/lib/typescript/src/games/balloon-blaster/components/ScoreBoard.d.ts.map +1 -1
  190. package/lib/typescript/src/games/candy-crush/CandyCrushConstants.d.ts +7 -7
  191. package/lib/typescript/src/games/colors-sort/ColorsSort.d.ts.map +1 -1
  192. package/lib/typescript/src/games/colors-sort/ColorsSortStore.d.ts.map +1 -1
  193. package/lib/typescript/src/games/dino-jump/DinoJump.d.ts.map +1 -1
  194. package/lib/typescript/src/games/dino-jump/components/DinoSprite.d.ts.map +1 -1
  195. package/lib/typescript/src/games/flappy-bird/FlappyBird.d.ts.map +1 -1
  196. package/lib/typescript/src/games/flappy-bird/FlappyBirdConstants.d.ts.map +1 -1
  197. package/lib/typescript/src/games/fruit-merger/FruitMerger.d.ts.map +1 -1
  198. package/lib/typescript/src/games/fruit-merger/FruitMergerConstants.d.ts.map +1 -1
  199. package/lib/typescript/src/games/fruit-ninja/FruitNinja.d.ts.map +1 -1
  200. package/lib/typescript/src/games/fruit-ninja/components/ScoreBoard.d.ts.map +1 -1
  201. package/lib/typescript/src/games/game-2048/Game2048.d.ts.map +1 -1
  202. package/lib/typescript/src/games/maze-runner/MazeRunner.d.ts.map +1 -1
  203. package/lib/typescript/src/games/popit-fidget/PopitFidget.d.ts.map +1 -1
  204. package/lib/typescript/src/games/sliding-numbers/SlidingNumbers.d.ts.map +1 -1
  205. package/lib/typescript/src/games/space-fighter/SpaceFighter.d.ts.map +1 -1
  206. package/lib/typescript/src/games/whack-a-mole/WhackAMole.d.ts.map +1 -1
  207. package/lib/typescript/src/games/whack-a-mole/WhackAMoleConstants.d.ts +1 -1
  208. package/lib/typescript/src/games/whack-a-mole/components/ScoreBoard.d.ts.map +1 -1
  209. package/lib/typescript/src/helpers/GameOverModal.d.ts +3 -0
  210. package/lib/typescript/src/helpers/GameOverModal.d.ts.map +1 -1
  211. package/lib/typescript/src/services/GamesConstants.d.ts +7 -7
  212. package/package.json +2 -2
@@ -1,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'}});