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,237 +1 @@
1
- "use strict";
2
-
3
- import React, { useEffect, useMemo, useCallback } from 'react';
4
- import { TouchableOpacity, Dimensions } from 'react-native';
5
- import { Canvas, vec, Path, Skia, Oval, Circle } from '@shopify/react-native-skia';
6
- import Animated, { useSharedValue, useAnimatedStyle, withSpring, withTiming } from 'react-native-reanimated';
7
- import { GAME_CONFIG, ANIMATION_CONFIG } from "../BalloonBlasterService.js";
8
-
9
- // Constants for better maintainability
10
- import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
11
- const BALLOON_HEIGHT_MULTIPLIER = 1.2;
12
- const STRING_LENGTH = 25;
13
- const HIGHLIGHT_OPACITY = 0.5;
14
- const BALLOON_OPACITY = 0.8;
15
- const DANGER_CIRCLE_RADIUS = 8;
16
- const GLOW_RADIUS_MULTIPLIER = 0.6;
17
- const GLOW_OPACITY = 0.3;
18
-
19
- // Types for better type safety
20
-
21
- export const BalloonComponent = /*#__PURE__*/React.memo(({
22
- balloon,
23
- onPop
24
- }) => {
25
- // Get screen dimensions
26
- const {
27
- height
28
- } = Dimensions.get('window');
29
-
30
- // FORCE all balloons to start from bottom - override any wrong positions
31
- const initialY = balloon.position.y > height ? balloon.position.y : height - 30;
32
-
33
- // Animated values for smooth movement
34
- const translateX = useSharedValue(balloon.position.x);
35
- const translateY = useSharedValue(initialY); // Force bottom start
36
- const rotation = useSharedValue(balloon.rotation);
37
- const scale = useSharedValue(balloon.isPopped ? 0 : 1);
38
- const opacity = useSharedValue(balloon.isPopped ? 0 : 1);
39
-
40
- // Update animated values when balloon properties change
41
- useEffect(() => {
42
- translateX.value = withSpring(balloon.position.x, ANIMATION_CONFIG.BALLOON_SPRING);
43
- translateY.value = withSpring(balloon.position.y, ANIMATION_CONFIG.BALLOON_SPRING);
44
- rotation.value = withSpring(balloon.rotation, ANIMATION_CONFIG.BALLOON_SPRING);
45
- }, [balloon.position.x, balloon.position.y, balloon.rotation]);
46
-
47
- // Handle popped state with animation
48
- useEffect(() => {
49
- if (balloon.isPopped) {
50
- scale.value = withTiming(0, ANIMATION_CONFIG.SLICE_TIMING);
51
- opacity.value = withTiming(0, ANIMATION_CONFIG.SLICE_TIMING);
52
- } else {
53
- scale.value = withSpring(1, ANIMATION_CONFIG.BALLOON_SPRING);
54
- opacity.value = withSpring(1, ANIMATION_CONFIG.BALLOON_SPRING);
55
- }
56
- }, [balloon.isPopped]);
57
-
58
- // Animated style
59
- const animatedStyle = useAnimatedStyle(() => {
60
- return {
61
- transform: [{
62
- translateX: translateX.value
63
- }, {
64
- translateY: translateY.value
65
- }, {
66
- rotate: `${rotation.value}rad`
67
- }, {
68
- scale: scale.value
69
- }],
70
- opacity: opacity.value
71
- };
72
- });
73
- const containerStyle = {
74
- position: 'absolute',
75
- width: GAME_CONFIG.BALLOON_SIZE,
76
- height: GAME_CONFIG.BALLOON_SIZE,
77
- zIndex: balloon.isBomb ? 10 : 5
78
- };
79
-
80
- // Optimized color manipulation functions
81
- const lightenColor = useCallback((color, amount) => {
82
- const hex = color.replace('#', '');
83
- const r = Math.min(255, parseInt(hex.substring(0, 2), 16) + Math.round(255 * amount));
84
- const g = Math.min(255, parseInt(hex.substring(2, 4), 16) + Math.round(255 * amount));
85
- const b = Math.min(255, parseInt(hex.substring(4, 6), 16) + Math.round(255 * amount));
86
- return `#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b.toString(16).padStart(2, '0')}`;
87
- }, []);
88
- const darkenColor = useCallback((color, amount) => {
89
- const hex = color.replace('#', '');
90
- const r = Math.max(0, parseInt(hex.substring(0, 2), 16) - Math.round(255 * amount));
91
- const g = Math.max(0, parseInt(hex.substring(2, 4), 16) - Math.round(255 * amount));
92
- const b = Math.max(0, parseInt(hex.substring(4, 6), 16) - Math.round(255 * amount));
93
- return `#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b.toString(16).padStart(2, '0')}`;
94
- }, []);
95
-
96
- // Optimized balloon color calculation with proper memoization
97
- const colors = useMemo(() => {
98
- if (balloon.isBomb) {
99
- return {
100
- primary: '#1a1a1a',
101
- secondary: '#333333',
102
- highlight: '#555555',
103
- shadow: '#000000'
104
- };
105
- }
106
- if (balloon.isBonus) {
107
- return {
108
- primary: '#FFD700',
109
- secondary: '#FFEB3B',
110
- highlight: '#FFF59D',
111
- shadow: '#CC8800'
112
- };
113
- }
114
-
115
- // Regular balloon colors with optimized calculation
116
- const baseColor = balloon.type.color || '#FF0080';
117
- return {
118
- primary: baseColor,
119
- secondary: lightenColor(baseColor, 0.3),
120
- highlight: lightenColor(baseColor, 0.5),
121
- shadow: darkenColor(baseColor, 0.3)
122
- };
123
- }, [balloon.isBomb, balloon.isBonus, balloon.type.color, lightenColor, darkenColor]);
124
-
125
- // Memoized dimensions for better performance
126
- const dimensions = useMemo(() => {
127
- const balloonWidth = GAME_CONFIG.BALLOON_SIZE;
128
- const balloonHeight = GAME_CONFIG.BALLOON_SIZE * BALLOON_HEIGHT_MULTIPLIER;
129
- const totalHeight = balloonHeight + STRING_LENGTH;
130
- const center = vec(balloonWidth / 2, balloonHeight / 2);
131
- return {
132
- balloonWidth,
133
- balloonHeight,
134
- totalHeight,
135
- center
136
- };
137
- }, []);
138
-
139
- // Optimized curved string path generation with better memoization
140
- const curvedStringPath = useMemo(() => {
141
- const path = Skia.Path.Make();
142
- const startX = dimensions.center.x;
143
- const startY = dimensions.balloonHeight - 2;
144
-
145
- // Optimized seed generation for consistent random curves
146
- const seed = balloon.id.split('').reduce((acc, char) => acc + char.charCodeAt(0), 0);
147
- const random = index => (seed + index * 17) % 100 / 100;
148
- path.moveTo(startX, startY);
149
-
150
- // Optimized string generation with minimal segments
151
- const segments = 2;
152
- const segmentHeight = STRING_LENGTH / segments;
153
- for (let i = 1; i <= segments; i++) {
154
- const y = startY + segmentHeight * i;
155
- const waveAmplitude = 2 + random(i) * 2;
156
- const waveOffset = (random(i + 10) - 0.5) * waveAmplitude;
157
- const x = startX + waveOffset;
158
- const controlX1 = startX + (random(i + 20) - 0.5) * waveAmplitude * 0.5;
159
- const controlY1 = y - segmentHeight * 0.5;
160
- path.quadTo(controlX1, controlY1, x, y);
161
- }
162
- return path;
163
- }, [balloon.id, dimensions.center.x, dimensions.balloonHeight]);
164
-
165
- // Memoized tap handler for better performance
166
- const handleTap = useCallback(() => {
167
- onPop?.(balloon.id);
168
- }, [onPop, balloon.id]);
169
- return /*#__PURE__*/_jsx(Animated.View, {
170
- style: [containerStyle, animatedStyle],
171
- children: /*#__PURE__*/_jsx(TouchableOpacity, {
172
- onPress: handleTap,
173
- activeOpacity: 0.8,
174
- style: {
175
- width: dimensions.balloonWidth,
176
- height: dimensions.totalHeight
177
- },
178
- children: /*#__PURE__*/_jsxs(Canvas, {
179
- style: {
180
- width: dimensions.balloonWidth,
181
- height: dimensions.totalHeight
182
- },
183
- pointerEvents: "none",
184
- children: [/*#__PURE__*/_jsx(Oval, {
185
- x: 0,
186
- y: 0,
187
- width: dimensions.balloonWidth,
188
- height: dimensions.balloonHeight,
189
- color: colors.primary,
190
- opacity: BALLOON_OPACITY
191
- }), /*#__PURE__*/_jsx(Oval, {
192
- x: dimensions.balloonWidth * 0.2,
193
- y: dimensions.balloonHeight * 0.15,
194
- width: dimensions.balloonWidth * 0.3,
195
- height: dimensions.balloonHeight * 0.2,
196
- color: colors.highlight,
197
- opacity: HIGHLIGHT_OPACITY
198
- }), balloon.isBomb && /*#__PURE__*/_jsxs(_Fragment, {
199
- children: [/*#__PURE__*/_jsx(Circle, {
200
- cx: dimensions.center.x,
201
- cy: dimensions.center.y,
202
- r: DANGER_CIRCLE_RADIUS,
203
- color: "#FF0000",
204
- opacity: 0.9
205
- }), /*#__PURE__*/_jsx(Path, {
206
- path: Skia.Path.Make().moveTo(dimensions.center.x, dimensions.center.y - 4).lineTo(dimensions.center.x, dimensions.center.y + 1),
207
- color: "#FFFFFF",
208
- style: "stroke",
209
- strokeWidth: 2,
210
- strokeCap: "round"
211
- }), /*#__PURE__*/_jsx(Circle, {
212
- cx: dimensions.center.x,
213
- cy: dimensions.center.y + 3,
214
- r: 1,
215
- color: "#FFFFFF"
216
- })]
217
- }), !balloon.isBonus && /*#__PURE__*/_jsx(Path, {
218
- path: curvedStringPath,
219
- color: "#8B4513",
220
- style: "stroke",
221
- strokeWidth: 1.5,
222
- strokeCap: "round"
223
- }), balloon.isBonus && /*#__PURE__*/_jsx(Circle, {
224
- cx: dimensions.center.x,
225
- cy: dimensions.center.y,
226
- r: dimensions.balloonWidth * GLOW_RADIUS_MULTIPLIER,
227
- color: "#FFD700",
228
- opacity: GLOW_OPACITY
229
- })]
230
- })
231
- })
232
- });
233
- }, (prevProps, nextProps) => {
234
- // Custom comparison for React.memo - only re-render if essential props change
235
- return prevProps.balloon.id === nextProps.balloon.id && prevProps.balloon.position.x === nextProps.balloon.position.x && prevProps.balloon.position.y === nextProps.balloon.position.y && prevProps.balloon.rotation === nextProps.balloon.rotation && prevProps.balloon.isPopped === nextProps.balloon.isPopped && prevProps.balloon.isBomb === nextProps.balloon.isBomb && prevProps.balloon.isBonus === nextProps.balloon.isBonus;
236
- });
237
- //# sourceMappingURL=BalloonComponent.js.map
1
+ "use strict";import React,{useEffect,useMemo,useCallback}from 'react';import{TouchableOpacity,Dimensions}from 'react-native';import{Canvas,vec,Path,Skia,Oval,Circle}from '@shopify/react-native-skia';import Animated,{useSharedValue,useAnimatedStyle,withSpring,withTiming}from 'react-native-reanimated';import{GAME_CONFIG,ANIMATION_CONFIG}from "../BalloonBlasterService.js";import{jsx as _jsx,Fragment as _Fragment,jsxs as _jsxs}from "react/jsx-runtime";const BALLOON_HEIGHT_MULTIPLIER = 1.2;const STRING_LENGTH = 25;const HIGHLIGHT_OPACITY = 0.5;const BALLOON_OPACITY = 0.8;const DANGER_CIRCLE_RADIUS = 8;const GLOW_RADIUS_MULTIPLIER = 0.6;const GLOW_OPACITY = 0.3;export const BalloonComponent = React.memo(({balloon,onPop})=>{const{height}= Dimensions.get('window');const initialY = balloon.position.y > height ? balloon.position.y:height - 30;const translateX = useSharedValue(balloon.position.x);const translateY = useSharedValue(initialY);const rotation = useSharedValue(balloon.rotation);const scale = useSharedValue(balloon.isPopped ? 0:1);const opacity = useSharedValue(balloon.isPopped ? 0:1);useEffect(()=>{translateX.value = withSpring(balloon.position.x,ANIMATION_CONFIG.BALLOON_SPRING);translateY.value = withSpring(balloon.position.y,ANIMATION_CONFIG.BALLOON_SPRING);rotation.value = withSpring(balloon.rotation,ANIMATION_CONFIG.BALLOON_SPRING);},[balloon.position.x,balloon.position.y,balloon.rotation]);useEffect(()=>{if(balloon.isPopped){scale.value = withTiming(0,ANIMATION_CONFIG.SLICE_TIMING);opacity.value = withTiming(0,ANIMATION_CONFIG.SLICE_TIMING);}else{scale.value = withSpring(1,ANIMATION_CONFIG.BALLOON_SPRING);opacity.value = withSpring(1,ANIMATION_CONFIG.BALLOON_SPRING);}},[balloon.isPopped]);const animatedStyle = useAnimatedStyle(()=>{return{transform:[{translateX:translateX.value},{translateY:translateY.value},{rotate:`${rotation.value}rad`},{scale:scale.value}],opacity:opacity.value};});const containerStyle ={position:'absolute',width:GAME_CONFIG.BALLOON_SIZE,height:GAME_CONFIG.BALLOON_SIZE,zIndex:balloon.isBomb ? 10:5};const lightenColor = useCallback((color,amount)=>{const hex = color.replace('#','');const r = Math.min(255,parseInt(hex.substring(0,2),16)+ Math.round(255 * amount));const g = Math.min(255,parseInt(hex.substring(2,4),16)+ Math.round(255 * amount));const b = Math.min(255,parseInt(hex.substring(4,6),16)+ Math.round(255 * amount));return `#${r.toString(16).padStart(2,'0')}${g.toString(16).padStart(2,'0')}${b.toString(16).padStart(2,'0')}`;},[]);const darkenColor = useCallback((color,amount)=>{const hex = color.replace('#','');const r = Math.max(0,parseInt(hex.substring(0,2),16)- Math.round(255 * amount));const g = Math.max(0,parseInt(hex.substring(2,4),16)- Math.round(255 * amount));const b = Math.max(0,parseInt(hex.substring(4,6),16)- Math.round(255 * amount));return `#${r.toString(16).padStart(2,'0')}${g.toString(16).padStart(2,'0')}${b.toString(16).padStart(2,'0')}`;},[]);const colors = useMemo(()=>{if(balloon.isBomb){return{primary:'#1a1a1a',secondary:'#333333',highlight:'#555555',shadow:'#000000'};}if(balloon.isBonus){return{primary:'#FFD700',secondary:'#FFEB3B',highlight:'#FFF59D',shadow:'#CC8800'};}const baseColor = balloon.type.color || '#FF0080';return{primary:baseColor,secondary:lightenColor(baseColor,0.3),highlight:lightenColor(baseColor,0.5),shadow:darkenColor(baseColor,0.3)};},[balloon.isBomb,balloon.isBonus,balloon.type.color,lightenColor,darkenColor]);const dimensions = useMemo(()=>{const balloonWidth = GAME_CONFIG.BALLOON_SIZE;const balloonHeight = GAME_CONFIG.BALLOON_SIZE * BALLOON_HEIGHT_MULTIPLIER;const totalHeight = balloonHeight + STRING_LENGTH;const center = vec(balloonWidth / 2,balloonHeight / 2);return{balloonWidth,balloonHeight,totalHeight,center};},[]);const curvedStringPath = useMemo(()=>{const path = Skia.Path.Make();const startX = dimensions.center.x;const startY = dimensions.balloonHeight - 2;const seed = balloon.id.split('').reduce((acc,char)=> acc + char.charCodeAt(0),0);const random = index =>(seed + index * 17)% 100 / 100;path.moveTo(startX,startY);const segments = 2;const segmentHeight = STRING_LENGTH / segments;for(let i = 1;i <= segments;i++){const y = startY + segmentHeight * i;const waveAmplitude = 2 + random(i)* 2;const waveOffset =(random(i + 10)- 0.5)* waveAmplitude;const x = startX + waveOffset;const controlX1 = startX +(random(i + 20)- 0.5)* waveAmplitude * 0.5;const controlY1 = y - segmentHeight * 0.5;path.quadTo(controlX1,controlY1,x,y);}return path;},[balloon.id,dimensions.center.x,dimensions.balloonHeight]);const handleTap = useCallback(()=>{onPop?.(balloon.id);},[onPop,balloon.id]);return _jsx(Animated.View,{style:[containerStyle,animatedStyle],children:_jsx(TouchableOpacity,{onPress:handleTap,activeOpacity:0.8,style:{width:dimensions.balloonWidth,height:dimensions.totalHeight},children:_jsxs(Canvas,{style:{width:dimensions.balloonWidth,height:dimensions.totalHeight},pointerEvents:"none",children:[_jsx(Oval,{x:0,y:0,width:dimensions.balloonWidth,height:dimensions.balloonHeight,color:colors.primary,opacity:BALLOON_OPACITY}),_jsx(Oval,{x:dimensions.balloonWidth * 0.2,y:dimensions.balloonHeight * 0.15,width:dimensions.balloonWidth * 0.3,height:dimensions.balloonHeight * 0.2,color:colors.highlight,opacity:HIGHLIGHT_OPACITY}),balloon.isBomb && _jsxs(_Fragment,{children:[_jsx(Circle,{cx:dimensions.center.x,cy:dimensions.center.y,r:DANGER_CIRCLE_RADIUS,color:"#FF0000",opacity:0.9}),_jsx(Path,{path:Skia.Path.Make().moveTo(dimensions.center.x,dimensions.center.y - 4).lineTo(dimensions.center.x,dimensions.center.y + 1),color:"#FFFFFF",style:"stroke",strokeWidth:2,strokeCap:"round"}),_jsx(Circle,{cx:dimensions.center.x,cy:dimensions.center.y + 3,r:1,color:"#FFFFFF"})]}),!balloon.isBonus && _jsx(Path,{path:curvedStringPath,color:"#8B4513",style:"stroke",strokeWidth:1.5,strokeCap:"round"}),balloon.isBonus && _jsx(Circle,{cx:dimensions.center.x,cy:dimensions.center.y,r:dimensions.balloonWidth * GLOW_RADIUS_MULTIPLIER,color:"#FFD700",opacity:GLOW_OPACITY})]})})});},(prevProps,nextProps)=>{return prevProps.balloon.id === nextProps.balloon.id && prevProps.balloon.position.x === nextProps.balloon.position.x && prevProps.balloon.position.y === nextProps.balloon.position.y && prevProps.balloon.rotation === nextProps.balloon.rotation && prevProps.balloon.isPopped === nextProps.balloon.isPopped && prevProps.balloon.isBomb === nextProps.balloon.isBomb && prevProps.balloon.isBonus === nextProps.balloon.isBonus;});
@@ -1,156 +1 @@
1
- "use strict";
2
-
3
- import React, { useEffect, useState, useCallback, useMemo } from 'react';
4
- import { View, StyleSheet } from 'react-native';
5
- import { useBalloonBlasterStore } from "../BalloonBlasterStore.js";
6
- import { GAME_CONFIG } from "../BalloonBlasterService.js";
7
- import { playSound, GAME_SOUNDS } from "../../../services/SoundsService.js";
8
- import { playHaptic, HapticType } from "../../../services/HapticsService.js";
9
- import { ParticleBlast, useAnimationTracker } from "../../../helpers/index.js";
10
- import { BalloonComponent } from "./BalloonComponent.js";
11
-
12
- // Constants for better maintainability
13
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
14
- const BALLOON_REMOVAL_DELAY = 500; // ms
15
- const PARTICLE_COUNT = 8;
16
- const PARTICLE_DURATION = 1000; // ms
17
-
18
- // Types for better type safety
19
-
20
- export const GameArea = /*#__PURE__*/React.memo(() => {
21
- // Optimized store subscriptions - only subscribe to what we need
22
- const balloons = useBalloonBlasterStore(state => state.balloons);
23
- const isPlaying = useBalloonBlasterStore(state => state.isPlaying);
24
- const gameOver = useBalloonBlasterStore(state => state.gameOver);
25
-
26
- // Get store actions (these don't cause re-renders)
27
- const {
28
- popBalloon,
29
- removeBalloon,
30
- updateBalloon,
31
- resetCombo,
32
- loseLife,
33
- addLife
34
- } = useBalloonBlasterStore();
35
-
36
- // Animation tracking for balloons using shared utility
37
- const balloonAnimations = useAnimationTracker();
38
-
39
- // State for managing active particle blasts with proper typing
40
- const [activeBlasts, setActiveBlasts] = useState([]);
41
-
42
- // Memoized sound and haptic feedback functions (using default enabled state)
43
- const playPopSound = useCallback(() => {
44
- playSound(GAME_SOUNDS.BALLOON_BLASTER.POP, true);
45
- playHaptic(HapticType.LIGHT, true);
46
- }, []);
47
- const playBombSound = useCallback(() => {
48
- playSound(GAME_SOUNDS.BALLOON_BLASTER.BOMB, true);
49
- playHaptic(HapticType.HEAVY, true);
50
- }, []);
51
-
52
- // Optimized blast particle creation
53
- const createBlastParticles = useCallback(balloon => {
54
- const blastX = balloon.position.x + GAME_CONFIG.BALLOON_SIZE / 2;
55
- const blastY = balloon.position.y + GAME_CONFIG.BALLOON_SIZE / 2;
56
- const blastId = `blast_${Date.now()}_${Math.random()}`;
57
- setActiveBlasts(prev => [...prev, {
58
- id: blastId,
59
- x: blastX,
60
- y: blastY
61
- }]);
62
- }, []);
63
-
64
- // Optimized blast completion handler
65
- const handleBlastComplete = useCallback(blastId => {
66
- setActiveBlasts(prev => prev.filter(blast => blast.id !== blastId));
67
- }, []);
68
-
69
- // Optimized balloon popping logic with better error handling
70
- const handleBalloonPop = useCallback(balloonId => {
71
- // Early exit if game is not active
72
- if (!isPlaying || gameOver) return;
73
-
74
- // Get current balloon state
75
- const currentBalloons = useBalloonBlasterStore.getState().balloons;
76
- const balloon = currentBalloons.find(b => b.id === balloonId);
77
-
78
- // Validate balloon exists and is not already popped
79
- if (!balloon || balloon.isPopped) return;
80
-
81
- // Handle different balloon types with optimized logic
82
- if (balloon.isBomb) {
83
- // Bomb balloon - lose life and reset combo
84
- playBombSound();
85
- loseLife();
86
- resetCombo();
87
- updateBalloon(balloonId, {
88
- isPopped: true
89
- });
90
- } else if (balloon.isBonus) {
91
- // Bonus balloon - add life
92
- playPopSound();
93
- addLife();
94
- updateBalloon(balloonId, {
95
- isPopped: true
96
- });
97
- } else {
98
- // Regular balloon - add points (popBalloon handles marking as popped)
99
- playPopSound();
100
- popBalloon(balloonId);
101
- }
102
-
103
- // Create visual blast effect
104
- createBlastParticles(balloon);
105
-
106
- // Schedule balloon removal after animation completes
107
- setTimeout(() => {
108
- removeBalloon(balloonId);
109
- balloonAnimations.delete(balloonId);
110
- }, BALLOON_REMOVAL_DELAY);
111
- }, [isPlaying, gameOver, playBombSound, playPopSound, loseLife, resetCombo, addLife, popBalloon, updateBalloon, createBlastParticles, removeBalloon, balloonAnimations]);
112
-
113
- // Optimized balloon animation tracking
114
- useEffect(() => {
115
- balloons.forEach(balloon => {
116
- if (!balloonAnimations.has(balloon.id)) {
117
- balloonAnimations.initialize(balloon.id);
118
- }
119
- });
120
- }, [balloons, balloonAnimations]);
121
-
122
- // Memoized balloon components for better performance
123
- const balloonComponents = useMemo(() => {
124
- return balloons.map(balloon => {
125
- const animation = balloonAnimations.get(balloon.id);
126
- return /*#__PURE__*/_jsx(BalloonComponent, {
127
- balloon: balloon,
128
- animation: animation,
129
- onPop: handleBalloonPop
130
- }, balloon.id);
131
- });
132
- }, [balloons, balloonAnimations, handleBalloonPop]);
133
-
134
- // Memoized particle blast components
135
- const blastComponents = useMemo(() => {
136
- return activeBlasts.map(blast => /*#__PURE__*/_jsx(ParticleBlast, {
137
- x: blast.x,
138
- y: blast.y,
139
- particleCount: PARTICLE_COUNT,
140
- duration: PARTICLE_DURATION,
141
- onComplete: () => handleBlastComplete(blast.id)
142
- }, blast.id));
143
- }, [activeBlasts, handleBlastComplete]);
144
- return /*#__PURE__*/_jsxs(View, {
145
- style: styles.gameArea,
146
- children: [balloonComponents, blastComponents]
147
- });
148
- });
149
- const styles = StyleSheet.create({
150
- gameArea: {
151
- flex: 1,
152
- position: 'relative',
153
- overflow: 'hidden'
154
- }
155
- });
156
- //# sourceMappingURL=GameArea.js.map
1
+ "use strict";import React,{useEffect,useState,useCallback,useMemo}from 'react';import{View,StyleSheet}from 'react-native';import{useBalloonBlasterStore}from "../BalloonBlasterStore.js";import{GAME_CONFIG}from "../BalloonBlasterService.js";import{playSound,GAME_SOUNDS}from "../../../services/SoundsService.js";import{playHaptic,HapticType}from "../../../services/HapticsService.js";import{ParticleBlast,useAnimationTracker}from "../../../helpers/index.js";import{BalloonComponent}from "./BalloonComponent.js";import{jsx as _jsx,jsxs as _jsxs}from "react/jsx-runtime";const BALLOON_REMOVAL_DELAY = 500;const PARTICLE_COUNT = 8;const PARTICLE_DURATION = 1000;export const GameArea = React.memo(()=>{const balloons = useBalloonBlasterStore(state => state.balloons);const isPlaying = useBalloonBlasterStore(state => state.isPlaying);const gameOver = useBalloonBlasterStore(state => state.gameOver);const{popBalloon,removeBalloon,updateBalloon,resetCombo,loseLife,addLife}= useBalloonBlasterStore();const balloonAnimations = useAnimationTracker();const [activeBlasts,setActiveBlasts] = useState([]);const playPopSound = useCallback(()=>{playSound(GAME_SOUNDS.BALLOON_BLASTER.POP,true);playHaptic(HapticType.LIGHT,true);},[]);const playBombSound = useCallback(()=>{playSound(GAME_SOUNDS.BALLOON_BLASTER.BOMB,true);playHaptic(HapticType.HEAVY,true);},[]);const createBlastParticles = useCallback(balloon =>{const blastX = balloon.position.x + GAME_CONFIG.BALLOON_SIZE / 2;const blastY = balloon.position.y + GAME_CONFIG.BALLOON_SIZE / 2;const blastId = `blast_${Date.now()}_${Math.random()}`;setActiveBlasts(prev => [...prev,{id:blastId,x:blastX,y:blastY}]);},[]);const handleBlastComplete = useCallback(blastId =>{setActiveBlasts(prev => prev.filter(blast => blast.id !== blastId));},[]);const handleBalloonPop = useCallback(balloonId =>{if(!isPlaying || gameOver)return;const currentBalloons = useBalloonBlasterStore.getState().balloons;const balloon = currentBalloons.find(b => b.id === balloonId);if(!balloon || balloon.isPopped)return;if(balloon.isBomb){playBombSound();loseLife();resetCombo();updateBalloon(balloonId,{isPopped:true});}else if(balloon.isBonus){playPopSound();addLife();updateBalloon(balloonId,{isPopped:true});}else{playPopSound();popBalloon(balloonId);}createBlastParticles(balloon);setTimeout(()=>{removeBalloon(balloonId);balloonAnimations.delete(balloonId);},BALLOON_REMOVAL_DELAY);},[isPlaying,gameOver,playBombSound,playPopSound,loseLife,resetCombo,addLife,popBalloon,updateBalloon,createBlastParticles,removeBalloon,balloonAnimations]);useEffect(()=>{balloons.forEach(balloon =>{if(!balloonAnimations.has(balloon.id)){balloonAnimations.initialize(balloon.id);}});},[balloons,balloonAnimations]);const balloonComponents = useMemo(()=>{return balloons.map(balloon =>{const animation = balloonAnimations.get(balloon.id);return _jsx(BalloonComponent,{balloon:balloon,animation:animation,onPop:handleBalloonPop},balloon.id);});},[balloons,balloonAnimations,handleBalloonPop]);const blastComponents = useMemo(()=>{return activeBlasts.map(blast => _jsx(ParticleBlast,{x:blast.x,y:blast.y,particleCount:PARTICLE_COUNT,duration:PARTICLE_DURATION,onComplete:()=> handleBlastComplete(blast.id)},blast.id));},[activeBlasts,handleBlastComplete]);return _jsxs(View,{style:styles.gameArea,children:[balloonComponents,blastComponents]});});const styles = StyleSheet.create({gameArea:{flex:1,position:'relative',overflow:'hidden'}});