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,150 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
import React from 'react';
|
|
4
|
-
import { Canvas, Circle, RadialGradient, vec, Shadow } from '@shopify/react-native-skia';
|
|
5
|
-
import { useSharedValue, useAnimatedStyle, withRepeat, withTiming, withSequence } from 'react-native-reanimated';
|
|
6
|
-
import Animated from 'react-native-reanimated';
|
|
7
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
8
|
-
// Memoized EnhancedBallComponent to prevent unnecessary re-renders
|
|
9
|
-
export const EnhancedBallComponent = /*#__PURE__*/React.memo(({
|
|
10
|
-
position,
|
|
11
|
-
size,
|
|
12
|
-
isDragging,
|
|
13
|
-
isCompleted
|
|
14
|
-
}) => {
|
|
15
|
-
// Animation values
|
|
16
|
-
const rotation = useSharedValue(0);
|
|
17
|
-
const glowIntensity = useSharedValue(0.6);
|
|
18
|
-
const pulseScale = useSharedValue(1);
|
|
19
|
-
const completionGlow = useSharedValue(0);
|
|
20
|
-
React.useEffect(() => {
|
|
21
|
-
// Continuous rotation
|
|
22
|
-
rotation.value = withRepeat(withTiming(360, {
|
|
23
|
-
duration: 4000
|
|
24
|
-
}), -1, false);
|
|
25
|
-
|
|
26
|
-
// Glow intensity animation
|
|
27
|
-
glowIntensity.value = withRepeat(withSequence(withTiming(0.3, {
|
|
28
|
-
duration: 1500
|
|
29
|
-
}), withTiming(0.8, {
|
|
30
|
-
duration: 1500
|
|
31
|
-
})), -1, true);
|
|
32
|
-
}, []);
|
|
33
|
-
React.useEffect(() => {
|
|
34
|
-
if (isDragging) {
|
|
35
|
-
pulseScale.value = withTiming(1.05, {
|
|
36
|
-
duration: 200
|
|
37
|
-
}); // Reduced from 1.2 to 1.05 for subtle effect
|
|
38
|
-
} else {
|
|
39
|
-
pulseScale.value = withTiming(1, {
|
|
40
|
-
duration: 200
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
}, [isDragging]);
|
|
44
|
-
React.useEffect(() => {
|
|
45
|
-
if (isCompleted) {
|
|
46
|
-
completionGlow.value = withRepeat(withSequence(withTiming(1, {
|
|
47
|
-
duration: 300
|
|
48
|
-
}), withTiming(0.3, {
|
|
49
|
-
duration: 300
|
|
50
|
-
})), 5, true);
|
|
51
|
-
} else {
|
|
52
|
-
completionGlow.value = withTiming(0, {
|
|
53
|
-
duration: 200
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
}, [isCompleted]);
|
|
57
|
-
const animatedStyle = useAnimatedStyle(() => {
|
|
58
|
-
const scale = pulseScale.value;
|
|
59
|
-
const rotationDegrees = rotation.value;
|
|
60
|
-
return {
|
|
61
|
-
position: 'absolute',
|
|
62
|
-
left: position.x - size / 2,
|
|
63
|
-
top: position.y - size / 2,
|
|
64
|
-
width: size * 1.5,
|
|
65
|
-
height: size * 1.5,
|
|
66
|
-
transform: [{
|
|
67
|
-
scale
|
|
68
|
-
}, {
|
|
69
|
-
rotate: `${rotationDegrees}deg`
|
|
70
|
-
}]
|
|
71
|
-
};
|
|
72
|
-
});
|
|
73
|
-
const canvasSize = size * 1.5;
|
|
74
|
-
const ballRadius = size / 2;
|
|
75
|
-
const centerX = canvasSize / 2;
|
|
76
|
-
const centerY = canvasSize / 2;
|
|
77
|
-
return /*#__PURE__*/_jsx(Animated.View, {
|
|
78
|
-
style: animatedStyle,
|
|
79
|
-
children: /*#__PURE__*/_jsxs(Canvas, {
|
|
80
|
-
style: {
|
|
81
|
-
width: canvasSize,
|
|
82
|
-
height: canvasSize
|
|
83
|
-
},
|
|
84
|
-
children: [/*#__PURE__*/_jsx(Circle, {
|
|
85
|
-
cx: centerX,
|
|
86
|
-
cy: centerY,
|
|
87
|
-
r: ballRadius * 1.3,
|
|
88
|
-
opacity: glowIntensity,
|
|
89
|
-
children: /*#__PURE__*/_jsx(RadialGradient, {
|
|
90
|
-
c: vec(centerX, centerY),
|
|
91
|
-
r: ballRadius * 1.3,
|
|
92
|
-
colors: isDragging ? ['#ff6b6b', '#ff8e8e', 'transparent'] : ['#4ecdc4', '#45b7b8', 'transparent']
|
|
93
|
-
})
|
|
94
|
-
}), isCompleted && /*#__PURE__*/_jsx(Circle, {
|
|
95
|
-
cx: centerX,
|
|
96
|
-
cy: centerY,
|
|
97
|
-
r: ballRadius * 1.6,
|
|
98
|
-
opacity: completionGlow,
|
|
99
|
-
children: /*#__PURE__*/_jsx(RadialGradient, {
|
|
100
|
-
c: vec(centerX, centerY),
|
|
101
|
-
r: ballRadius * 1.6,
|
|
102
|
-
colors: ['#ffd700', '#ffed4e', '#fff9c4', 'transparent']
|
|
103
|
-
})
|
|
104
|
-
}), /*#__PURE__*/_jsxs(Circle, {
|
|
105
|
-
cx: centerX,
|
|
106
|
-
cy: centerY,
|
|
107
|
-
r: ballRadius,
|
|
108
|
-
children: [/*#__PURE__*/_jsx(RadialGradient, {
|
|
109
|
-
c: vec(centerX - ballRadius * 0.3, centerY - ballRadius * 0.3),
|
|
110
|
-
r: ballRadius * 1.2,
|
|
111
|
-
colors: isDragging ? ['#ff6b6b', '#e55656', '#cc4545'] : ['#4ecdc4', '#45b7b8', '#3ca6a6']
|
|
112
|
-
}), /*#__PURE__*/_jsx(Shadow, {
|
|
113
|
-
dx: 2,
|
|
114
|
-
dy: 2,
|
|
115
|
-
blur: 4,
|
|
116
|
-
color: "rgba(0,0,0,0.3)"
|
|
117
|
-
})]
|
|
118
|
-
}), /*#__PURE__*/_jsx(Circle, {
|
|
119
|
-
cx: centerX - ballRadius * 0.3,
|
|
120
|
-
cy: centerY - ballRadius * 0.3,
|
|
121
|
-
r: ballRadius * 0.3,
|
|
122
|
-
opacity: 0.8,
|
|
123
|
-
children: /*#__PURE__*/_jsx(RadialGradient, {
|
|
124
|
-
c: vec(centerX - ballRadius * 0.3, centerY - ballRadius * 0.3),
|
|
125
|
-
r: ballRadius * 0.3,
|
|
126
|
-
colors: ['rgba(255,255,255,0.9)', 'rgba(255,255,255,0.3)', 'transparent']
|
|
127
|
-
})
|
|
128
|
-
}), /*#__PURE__*/_jsx(Circle, {
|
|
129
|
-
cx: centerX,
|
|
130
|
-
cy: centerY,
|
|
131
|
-
r: ballRadius * 0.4,
|
|
132
|
-
opacity: 0.7,
|
|
133
|
-
children: /*#__PURE__*/_jsx(RadialGradient, {
|
|
134
|
-
c: vec(centerX, centerY),
|
|
135
|
-
r: ballRadius * 0.4,
|
|
136
|
-
colors: ['rgba(255,255,255,0.8)', 'rgba(255,255,255,0.2)', 'transparent']
|
|
137
|
-
})
|
|
138
|
-
}), /*#__PURE__*/_jsx(Circle, {
|
|
139
|
-
cx: centerX,
|
|
140
|
-
cy: centerY,
|
|
141
|
-
r: ballRadius * 0.8,
|
|
142
|
-
opacity: 0.4,
|
|
143
|
-
style: "stroke",
|
|
144
|
-
strokeWidth: 2,
|
|
145
|
-
color: isDragging ? '#ff8e8e' : '#7dd3d8'
|
|
146
|
-
})]
|
|
147
|
-
})
|
|
148
|
-
});
|
|
149
|
-
});
|
|
150
|
-
//# sourceMappingURL=EnhancedBallComponent.js.map
|
|
1
|
+
"use strict";import React from 'react';import{Canvas,Circle,RadialGradient,vec,Shadow}from '@shopify/react-native-skia';import{useSharedValue,useAnimatedStyle,withRepeat,withTiming,withSequence}from 'react-native-reanimated';import Animated from 'react-native-reanimated';import{jsx as _jsx,jsxs as _jsxs}from "react/jsx-runtime";export const EnhancedBallComponent = React.memo(({position,size,isDragging,isCompleted})=>{const rotation = useSharedValue(0);const glowIntensity = useSharedValue(0.6);const pulseScale = useSharedValue(1);const completionGlow = useSharedValue(0);React.useEffect(()=>{rotation.value = withRepeat(withTiming(360,{duration:4000}),-1,false);glowIntensity.value = withRepeat(withSequence(withTiming(0.3,{duration:1500}),withTiming(0.8,{duration:1500})),-1,true);},[]);React.useEffect(()=>{if(isDragging){pulseScale.value = withTiming(1.05,{duration:200});}else{pulseScale.value = withTiming(1,{duration:200});}},[isDragging]);React.useEffect(()=>{if(isCompleted){completionGlow.value = withRepeat(withSequence(withTiming(1,{duration:300}),withTiming(0.3,{duration:300})),5,true);}else{completionGlow.value = withTiming(0,{duration:200});}},[isCompleted]);const animatedStyle = useAnimatedStyle(()=>{const scale = pulseScale.value;const rotationDegrees = rotation.value;return{position:'absolute',left:position.x - size / 2,top:position.y - size / 2,width:size * 1.5,height:size * 1.5,transform:[{scale},{rotate:`${rotationDegrees}deg`}]};});const canvasSize = size * 1.5;const ballRadius = size / 2;const centerX = canvasSize / 2;const centerY = canvasSize / 2;return _jsx(Animated.View,{style:animatedStyle,children:_jsxs(Canvas,{style:{width:canvasSize,height:canvasSize},children:[_jsx(Circle,{cx:centerX,cy:centerY,r:ballRadius * 1.3,opacity:glowIntensity,children:_jsx(RadialGradient,{c:vec(centerX,centerY),r:ballRadius * 1.3,colors:isDragging ? ['#ff6b6b','#ff8e8e','transparent']:['#4ecdc4','#45b7b8','transparent']})}),isCompleted && _jsx(Circle,{cx:centerX,cy:centerY,r:ballRadius * 1.6,opacity:completionGlow,children:_jsx(RadialGradient,{c:vec(centerX,centerY),r:ballRadius * 1.6,colors:['#ffd700','#ffed4e','#fff9c4','transparent']})}),_jsxs(Circle,{cx:centerX,cy:centerY,r:ballRadius,children:[_jsx(RadialGradient,{c:vec(centerX - ballRadius * 0.3,centerY - ballRadius * 0.3),r:ballRadius * 1.2,colors:isDragging ? ['#ff6b6b','#e55656','#cc4545']:['#4ecdc4','#45b7b8','#3ca6a6']}),_jsx(Shadow,{dx:2,dy:2,blur:4,color:"rgba(0,0,0,0.3)"})]}),_jsx(Circle,{cx:centerX - ballRadius * 0.3,cy:centerY - ballRadius * 0.3,r:ballRadius * 0.3,opacity:0.8,children:_jsx(RadialGradient,{c:vec(centerX - ballRadius * 0.3,centerY - ballRadius * 0.3),r:ballRadius * 0.3,colors:['rgba(255,255,255,0.9)','rgba(255,255,255,0.3)','transparent']})}),_jsx(Circle,{cx:centerX,cy:centerY,r:ballRadius * 0.4,opacity:0.7,children:_jsx(RadialGradient,{c:vec(centerX,centerY),r:ballRadius * 0.4,colors:['rgba(255,255,255,0.8)','rgba(255,255,255,0.2)','transparent']})}),_jsx(Circle,{cx:centerX,cy:centerY,r:ballRadius * 0.8,opacity:0.4,style:"stroke",strokeWidth:2,color:isDragging ? '#ff8e8e':'#7dd3d8'})]})});});
|
|
@@ -1,370 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
import React from 'react';
|
|
4
|
-
import { View, StyleSheet } from 'react-native';
|
|
5
|
-
import { Gesture, GestureDetector } from 'react-native-gesture-handler';
|
|
6
|
-
import Animated, { useSharedValue, useAnimatedStyle, runOnJS, withSpring } from 'react-native-reanimated';
|
|
7
|
-
import { playHaptic, HapticType } from "../../../services/HapticsService.js";
|
|
8
|
-
import { EnhancedBallComponent } from "./EnhancedBallComponent.js";
|
|
9
|
-
import { WallComponent } from "./WallComponent.js";
|
|
10
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
11
|
-
// Memoized EnhancedGameArea component to prevent unnecessary re-renders
|
|
12
|
-
export const EnhancedGameArea = /*#__PURE__*/React.memo(({
|
|
13
|
-
gameState,
|
|
14
|
-
gameConfig,
|
|
15
|
-
walls,
|
|
16
|
-
onBallPositionChange,
|
|
17
|
-
hapticEnabled
|
|
18
|
-
}) => {
|
|
19
|
-
const translateX = useSharedValue(gameState.ballPosition.x);
|
|
20
|
-
const translateY = useSharedValue(gameState.ballPosition.y);
|
|
21
|
-
const isDragging = useSharedValue(false);
|
|
22
|
-
|
|
23
|
-
// Create shared values for walls to use in worklet
|
|
24
|
-
const wallsSharedValue = useSharedValue(walls);
|
|
25
|
-
|
|
26
|
-
// Update ball position when game state changes - use smoother spring config
|
|
27
|
-
React.useEffect(() => {
|
|
28
|
-
translateX.value = withSpring(gameState.ballPosition.x, {
|
|
29
|
-
damping: 15,
|
|
30
|
-
stiffness: 150,
|
|
31
|
-
mass: 1
|
|
32
|
-
});
|
|
33
|
-
translateY.value = withSpring(gameState.ballPosition.y, {
|
|
34
|
-
damping: 15,
|
|
35
|
-
stiffness: 150,
|
|
36
|
-
mass: 1
|
|
37
|
-
});
|
|
38
|
-
}, [gameState.ballPosition]);
|
|
39
|
-
|
|
40
|
-
// Update walls when they change
|
|
41
|
-
React.useEffect(() => {
|
|
42
|
-
wallsSharedValue.value = walls;
|
|
43
|
-
}, [walls]);
|
|
44
|
-
|
|
45
|
-
// Memoized haptic callback functions
|
|
46
|
-
const triggerMoveHaptic = React.useCallback(() => {
|
|
47
|
-
playHaptic(HapticType.LIGHT, hapticEnabled);
|
|
48
|
-
}, [hapticEnabled]);
|
|
49
|
-
const triggerCollisionHaptic = React.useCallback(() => {
|
|
50
|
-
playHaptic(HapticType.MEDIUM, hapticEnabled);
|
|
51
|
-
}, [hapticEnabled]);
|
|
52
|
-
|
|
53
|
-
// Store the initial position when gesture starts
|
|
54
|
-
const startPosition = useSharedValue({
|
|
55
|
-
x: 0,
|
|
56
|
-
y: 0
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
// Worklet function to check collision with walls
|
|
60
|
-
const checkWallCollision = (ballX, ballY, ballRadius) => {
|
|
61
|
-
'worklet';
|
|
62
|
-
|
|
63
|
-
const currentWalls = wallsSharedValue.value;
|
|
64
|
-
|
|
65
|
-
// Use even smaller margin for smoother movement
|
|
66
|
-
const collisionMargin = 0.1; // Further reduced for smoother gameplay
|
|
67
|
-
const effectiveRadius = ballRadius + collisionMargin;
|
|
68
|
-
for (let i = 0; i < currentWalls.length; i++) {
|
|
69
|
-
const wall = currentWalls[i];
|
|
70
|
-
|
|
71
|
-
// Calculate the closest point on the wall rectangle to the ball center
|
|
72
|
-
const closestX = Math.max(wall.x, Math.min(ballX, wall.x + wall.width));
|
|
73
|
-
const closestY = Math.max(wall.y, Math.min(ballY, wall.y + wall.height));
|
|
74
|
-
|
|
75
|
-
// Calculate the distance from the ball center to this closest point
|
|
76
|
-
const distanceX = ballX - closestX;
|
|
77
|
-
const distanceY = ballY - closestY;
|
|
78
|
-
const distanceSquared = distanceX * distanceX + distanceY * distanceY;
|
|
79
|
-
|
|
80
|
-
// Check if the distance is less than the effective radius
|
|
81
|
-
if (distanceSquared < effectiveRadius * effectiveRadius) {
|
|
82
|
-
return true; // Collision detected
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
return false; // No collision
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
// Worklet function to check path collision (prevents jumping over walls)
|
|
89
|
-
const checkPathCollision = (fromX, fromY, toX, toY, ballRadius) => {
|
|
90
|
-
'worklet';
|
|
91
|
-
|
|
92
|
-
// Calculate the distance of the movement
|
|
93
|
-
const deltaX = toX - fromX;
|
|
94
|
-
const deltaY = toY - fromY;
|
|
95
|
-
const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
|
|
96
|
-
|
|
97
|
-
// If movement is very small, just check the destination
|
|
98
|
-
if (distance < 3) {
|
|
99
|
-
return checkWallCollision(toX, toY, ballRadius);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// For larger movements, check fewer points but more strategically
|
|
103
|
-
// Only check path collision for fast movements that could jump over walls
|
|
104
|
-
if (distance > 10) {
|
|
105
|
-
const steps = Math.ceil(distance / 4); // Check every 4 pixels for performance
|
|
106
|
-
|
|
107
|
-
for (let i = 1; i < steps; i++) {
|
|
108
|
-
// Skip start and end points
|
|
109
|
-
const t = i / steps;
|
|
110
|
-
const checkX = fromX + deltaX * t;
|
|
111
|
-
const checkY = fromY + deltaY * t;
|
|
112
|
-
if (checkWallCollision(checkX, checkY, ballRadius)) {
|
|
113
|
-
return true; // Collision detected along the path
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// Always check the final destination
|
|
119
|
-
return checkWallCollision(toX, toY, ballRadius);
|
|
120
|
-
};
|
|
121
|
-
const panGesture = Gesture.Pan().onStart(() => {
|
|
122
|
-
if (!gameState.isPlaying || gameState.isPaused) return;
|
|
123
|
-
|
|
124
|
-
// Store the current ball position when gesture starts
|
|
125
|
-
startPosition.value = {
|
|
126
|
-
x: gameState.ballPosition.x,
|
|
127
|
-
y: gameState.ballPosition.y
|
|
128
|
-
};
|
|
129
|
-
isDragging.value = true;
|
|
130
|
-
runOnJS(triggerMoveHaptic)();
|
|
131
|
-
}).onUpdate(event => {
|
|
132
|
-
if (!gameState.isPlaying || gameState.isPaused) return;
|
|
133
|
-
|
|
134
|
-
// Calculate new position based on gesture translation from start position
|
|
135
|
-
const newX = startPosition.value.x + event.translationX;
|
|
136
|
-
const newY = startPosition.value.y + event.translationY;
|
|
137
|
-
|
|
138
|
-
// Boundary checks
|
|
139
|
-
const ballRadius = gameConfig.BALL_SIZE / 2;
|
|
140
|
-
const clampedX = Math.max(ballRadius, Math.min(gameConfig.GAME_AREA_WIDTH - ballRadius, newX));
|
|
141
|
-
const clampedY = Math.max(ballRadius, Math.min(gameConfig.GAME_AREA_HEIGHT - ballRadius, newY));
|
|
142
|
-
|
|
143
|
-
// Get current ball position
|
|
144
|
-
const currentX = translateX.value;
|
|
145
|
-
const currentY = translateY.value;
|
|
146
|
-
|
|
147
|
-
// Calculate movement distance to determine collision strategy
|
|
148
|
-
const deltaX = clampedX - currentX;
|
|
149
|
-
const deltaY = clampedY - currentY;
|
|
150
|
-
const movementDistance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
|
|
151
|
-
let finalX = clampedX;
|
|
152
|
-
let finalY = clampedY;
|
|
153
|
-
let hasCollision = false;
|
|
154
|
-
|
|
155
|
-
// Use different collision detection strategies based on movement distance
|
|
156
|
-
if (movementDistance < 8) {
|
|
157
|
-
// For small movements, just check destination for smooth gameplay
|
|
158
|
-
hasCollision = checkWallCollision(clampedX, clampedY, ballRadius);
|
|
159
|
-
} else {
|
|
160
|
-
// For larger movements, use path collision detection to prevent wall jumping
|
|
161
|
-
hasCollision = checkPathCollision(currentX, currentY, clampedX, clampedY, ballRadius);
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
// If there's a collision, try to slide along walls more carefully
|
|
165
|
-
if (hasCollision) {
|
|
166
|
-
let foundValidPosition = false;
|
|
167
|
-
|
|
168
|
-
// Try moving only horizontally (slide along vertical walls)
|
|
169
|
-
// Allow more generous horizontal sliding for smoother movement
|
|
170
|
-
const horizontalOnlyX = clampedX;
|
|
171
|
-
const horizontalOnlyY = currentY;
|
|
172
|
-
const horizontalDistance = Math.abs(horizontalOnlyX - currentX);
|
|
173
|
-
if (horizontalDistance < ballRadius * 3 && !checkWallCollision(horizontalOnlyX, horizontalOnlyY, ballRadius)) {
|
|
174
|
-
// Also check that we're not jumping over a wall by testing intermediate points
|
|
175
|
-
const steps = Math.max(2, Math.ceil(horizontalDistance / 2));
|
|
176
|
-
let canSlideHorizontally = true;
|
|
177
|
-
for (let i = 1; i <= steps; i++) {
|
|
178
|
-
const t = i / steps;
|
|
179
|
-
const testX = currentX + (horizontalOnlyX - currentX) * t;
|
|
180
|
-
if (checkWallCollision(testX, horizontalOnlyY, ballRadius)) {
|
|
181
|
-
canSlideHorizontally = false;
|
|
182
|
-
break;
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
if (canSlideHorizontally) {
|
|
186
|
-
finalX = horizontalOnlyX;
|
|
187
|
-
finalY = horizontalOnlyY;
|
|
188
|
-
foundValidPosition = true;
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
// Try moving only vertically (slide along horizontal walls) if horizontal sliding failed
|
|
193
|
-
if (!foundValidPosition) {
|
|
194
|
-
const verticalOnlyX = currentX;
|
|
195
|
-
const verticalOnlyY = clampedY;
|
|
196
|
-
const verticalDistance = Math.abs(verticalOnlyY - currentY);
|
|
197
|
-
if (verticalDistance < ballRadius * 3 && !checkWallCollision(verticalOnlyX, verticalOnlyY, ballRadius)) {
|
|
198
|
-
// Also check that we're not jumping over a wall by testing intermediate points
|
|
199
|
-
const steps = Math.max(2, Math.ceil(verticalDistance / 2));
|
|
200
|
-
let canSlideVertically = true;
|
|
201
|
-
for (let i = 1; i <= steps; i++) {
|
|
202
|
-
const t = i / steps;
|
|
203
|
-
const testY = currentY + (verticalOnlyY - currentY) * t;
|
|
204
|
-
if (checkWallCollision(verticalOnlyX, testY, ballRadius)) {
|
|
205
|
-
canSlideVertically = false;
|
|
206
|
-
break;
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
if (canSlideVertically) {
|
|
210
|
-
finalX = verticalOnlyX;
|
|
211
|
-
finalY = verticalOnlyY;
|
|
212
|
-
foundValidPosition = true;
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
hasCollision = !foundValidPosition;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
// Update position if we found a valid position (either original or sliding)
|
|
220
|
-
if (!hasCollision) {
|
|
221
|
-
translateX.value = finalX;
|
|
222
|
-
translateY.value = finalY;
|
|
223
|
-
|
|
224
|
-
// Update game state on the JS thread
|
|
225
|
-
runOnJS(onBallPositionChange)({
|
|
226
|
-
x: finalX,
|
|
227
|
-
y: finalY
|
|
228
|
-
});
|
|
229
|
-
} else {
|
|
230
|
-
// If still collision after trying to slide, trigger haptic feedback
|
|
231
|
-
runOnJS(triggerCollisionHaptic)();
|
|
232
|
-
}
|
|
233
|
-
}).onEnd(() => {
|
|
234
|
-
isDragging.value = false;
|
|
235
|
-
});
|
|
236
|
-
const animatedBallStyle = useAnimatedStyle(() => ({
|
|
237
|
-
transform: [{
|
|
238
|
-
translateX: translateX.value - gameConfig.BALL_SIZE / 2
|
|
239
|
-
}, {
|
|
240
|
-
translateY: translateY.value - gameConfig.BALL_SIZE / 2
|
|
241
|
-
}]
|
|
242
|
-
}));
|
|
243
|
-
const renderStartMarker = () => {
|
|
244
|
-
const startPos = {
|
|
245
|
-
x: gameConfig.CELL_SIZE / 2,
|
|
246
|
-
y: gameConfig.CELL_SIZE / 2
|
|
247
|
-
};
|
|
248
|
-
return /*#__PURE__*/_jsx(View, {
|
|
249
|
-
style: [styles.marker, styles.startMarker, {
|
|
250
|
-
left: startPos.x - 15,
|
|
251
|
-
top: startPos.y - 15
|
|
252
|
-
}],
|
|
253
|
-
children: /*#__PURE__*/_jsx(View, {
|
|
254
|
-
style: styles.startMarkerInner
|
|
255
|
-
})
|
|
256
|
-
});
|
|
257
|
-
};
|
|
258
|
-
const renderEndMarker = () => {
|
|
259
|
-
const endPos = {
|
|
260
|
-
x: (gameConfig.GRID_SIZE - 1) * gameConfig.CELL_SIZE + gameConfig.CELL_SIZE / 2,
|
|
261
|
-
y: (gameConfig.GRID_SIZE - 1) * gameConfig.CELL_SIZE + gameConfig.CELL_SIZE / 2
|
|
262
|
-
};
|
|
263
|
-
return /*#__PURE__*/_jsx(View, {
|
|
264
|
-
style: [styles.marker, styles.endMarker, {
|
|
265
|
-
left: endPos.x - 15,
|
|
266
|
-
// Half of 30px marker size
|
|
267
|
-
top: endPos.y - 15
|
|
268
|
-
}],
|
|
269
|
-
children: /*#__PURE__*/_jsx(View, {
|
|
270
|
-
style: styles.endMarkerInner
|
|
271
|
-
})
|
|
272
|
-
});
|
|
273
|
-
};
|
|
274
|
-
return /*#__PURE__*/_jsx(View, {
|
|
275
|
-
style: [styles.container, {
|
|
276
|
-
width: gameConfig.GAME_AREA_WIDTH,
|
|
277
|
-
height: gameConfig.GAME_AREA_HEIGHT
|
|
278
|
-
}],
|
|
279
|
-
children: /*#__PURE__*/_jsxs(View, {
|
|
280
|
-
style: [styles.gameArea, {
|
|
281
|
-
width: gameConfig.GRID_SIZE * gameConfig.CELL_SIZE,
|
|
282
|
-
height: gameConfig.GRID_SIZE * gameConfig.CELL_SIZE
|
|
283
|
-
}],
|
|
284
|
-
children: [/*#__PURE__*/_jsx(WallComponent, {
|
|
285
|
-
walls: walls,
|
|
286
|
-
width: gameConfig.GRID_SIZE * gameConfig.CELL_SIZE,
|
|
287
|
-
height: gameConfig.GRID_SIZE * gameConfig.CELL_SIZE
|
|
288
|
-
}), renderStartMarker(), renderEndMarker(), /*#__PURE__*/_jsx(GestureDetector, {
|
|
289
|
-
gesture: panGesture,
|
|
290
|
-
children: /*#__PURE__*/_jsx(Animated.View, {
|
|
291
|
-
style: [styles.ballContainer, animatedBallStyle],
|
|
292
|
-
children: /*#__PURE__*/_jsx(EnhancedBallComponent, {
|
|
293
|
-
position: {
|
|
294
|
-
x: gameConfig.BALL_SIZE / 2,
|
|
295
|
-
y: gameConfig.BALL_SIZE / 2
|
|
296
|
-
},
|
|
297
|
-
size: gameConfig.BALL_SIZE,
|
|
298
|
-
isDragging: isDragging.value,
|
|
299
|
-
isCompleted: gameState.isCompleted
|
|
300
|
-
})
|
|
301
|
-
})
|
|
302
|
-
})]
|
|
303
|
-
})
|
|
304
|
-
});
|
|
305
|
-
});
|
|
306
|
-
const styles = StyleSheet.create({
|
|
307
|
-
container: {
|
|
308
|
-
backgroundColor: 'transparent',
|
|
309
|
-
// Make transparent so walls are visible
|
|
310
|
-
overflow: 'hidden',
|
|
311
|
-
justifyContent: 'center',
|
|
312
|
-
alignItems: 'center'
|
|
313
|
-
},
|
|
314
|
-
gameArea: {
|
|
315
|
-
position: 'relative',
|
|
316
|
-
backgroundColor: 'transparent' // Ensure game area is also transparent
|
|
317
|
-
},
|
|
318
|
-
ballContainer: {
|
|
319
|
-
position: 'absolute',
|
|
320
|
-
width: 40,
|
|
321
|
-
// Fixed size for the ball container
|
|
322
|
-
height: 40,
|
|
323
|
-
top: 0,
|
|
324
|
-
left: 0
|
|
325
|
-
},
|
|
326
|
-
marker: {
|
|
327
|
-
position: 'absolute',
|
|
328
|
-
width: 30,
|
|
329
|
-
// Revert to original size for proper collision detection
|
|
330
|
-
height: 30,
|
|
331
|
-
borderRadius: 15,
|
|
332
|
-
justifyContent: 'center',
|
|
333
|
-
alignItems: 'center',
|
|
334
|
-
elevation: 5,
|
|
335
|
-
shadowColor: '#000',
|
|
336
|
-
shadowOffset: {
|
|
337
|
-
width: 0,
|
|
338
|
-
height: 2
|
|
339
|
-
},
|
|
340
|
-
shadowOpacity: 0.3,
|
|
341
|
-
shadowRadius: 4
|
|
342
|
-
},
|
|
343
|
-
startMarker: {
|
|
344
|
-
backgroundColor: '#4CAF50',
|
|
345
|
-
borderWidth: 3,
|
|
346
|
-
// Revert to original border width
|
|
347
|
-
borderColor: '#2E7D32'
|
|
348
|
-
},
|
|
349
|
-
startMarkerInner: {
|
|
350
|
-
width: 12,
|
|
351
|
-
// Revert to original size
|
|
352
|
-
height: 12,
|
|
353
|
-
borderRadius: 6,
|
|
354
|
-
backgroundColor: '#81C784'
|
|
355
|
-
},
|
|
356
|
-
endMarker: {
|
|
357
|
-
backgroundColor: '#FF5722',
|
|
358
|
-
borderWidth: 3,
|
|
359
|
-
// Revert to original border width
|
|
360
|
-
borderColor: '#D84315'
|
|
361
|
-
},
|
|
362
|
-
endMarkerInner: {
|
|
363
|
-
width: 12,
|
|
364
|
-
// Revert to original size
|
|
365
|
-
height: 12,
|
|
366
|
-
borderRadius: 6,
|
|
367
|
-
backgroundColor: '#FF8A65'
|
|
368
|
-
}
|
|
369
|
-
});
|
|
370
|
-
//# sourceMappingURL=EnhancedGameArea.js.map
|
|
1
|
+
"use strict";import React from 'react';import{View,StyleSheet}from 'react-native';import{Gesture,GestureDetector}from 'react-native-gesture-handler';import Animated,{useSharedValue,useAnimatedStyle,runOnJS,withSpring}from 'react-native-reanimated';import{playHaptic,HapticType}from "../../../services/HapticsService.js";import{EnhancedBallComponent}from "./EnhancedBallComponent.js";import{WallComponent}from "./WallComponent.js";import{jsx as _jsx,jsxs as _jsxs}from "react/jsx-runtime";export const EnhancedGameArea = React.memo(({gameState,gameConfig,walls,onBallPositionChange,hapticEnabled})=>{const translateX = useSharedValue(gameState.ballPosition.x);const translateY = useSharedValue(gameState.ballPosition.y);const isDragging = useSharedValue(false);const wallsSharedValue = useSharedValue(walls);React.useEffect(()=>{translateX.value = withSpring(gameState.ballPosition.x,{damping:15,stiffness:150,mass:1});translateY.value = withSpring(gameState.ballPosition.y,{damping:15,stiffness:150,mass:1});},[gameState.ballPosition]);React.useEffect(()=>{wallsSharedValue.value = walls;},[walls]);const triggerMoveHaptic = React.useCallback(()=>{playHaptic(HapticType.LIGHT,hapticEnabled);},[hapticEnabled]);const triggerCollisionHaptic = React.useCallback(()=>{playHaptic(HapticType.MEDIUM,hapticEnabled);},[hapticEnabled]);const startPosition = useSharedValue({x:0,y:0});const checkWallCollision =(ballX,ballY,ballRadius)=>{'worklet';const currentWalls = wallsSharedValue.value;const collisionMargin = 0.1;const effectiveRadius = ballRadius + collisionMargin;for(let i = 0;i < currentWalls.length;i++){const wall = currentWalls[i];const closestX = Math.max(wall.x,Math.min(ballX,wall.x + wall.width));const closestY = Math.max(wall.y,Math.min(ballY,wall.y + wall.height));const distanceX = ballX - closestX;const distanceY = ballY - closestY;const distanceSquared = distanceX * distanceX + distanceY * distanceY;if(distanceSquared < effectiveRadius * effectiveRadius){return true;}}return false;};const checkPathCollision =(fromX,fromY,toX,toY,ballRadius)=>{'worklet';const deltaX = toX - fromX;const deltaY = toY - fromY;const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);if(distance < 3){return checkWallCollision(toX,toY,ballRadius);}if(distance > 10){const steps = Math.ceil(distance / 4);for(let i = 1;i < steps;i++){const t = i / steps;const checkX = fromX + deltaX * t;const checkY = fromY + deltaY * t;if(checkWallCollision(checkX,checkY,ballRadius)){return true;}}}return checkWallCollision(toX,toY,ballRadius);};const panGesture = Gesture.Pan().onStart(()=>{if(!gameState.isPlaying || gameState.isPaused)return;startPosition.value ={x:gameState.ballPosition.x,y:gameState.ballPosition.y};isDragging.value = true;runOnJS(triggerMoveHaptic)();}).onUpdate(event =>{if(!gameState.isPlaying || gameState.isPaused)return;const newX = startPosition.value.x + event.translationX;const newY = startPosition.value.y + event.translationY;const ballRadius = gameConfig.BALL_SIZE / 2;const clampedX = Math.max(ballRadius,Math.min(gameConfig.GAME_AREA_WIDTH - ballRadius,newX));const clampedY = Math.max(ballRadius,Math.min(gameConfig.GAME_AREA_HEIGHT - ballRadius,newY));const currentX = translateX.value;const currentY = translateY.value;const deltaX = clampedX - currentX;const deltaY = clampedY - currentY;const movementDistance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);let finalX = clampedX;let finalY = clampedY;let hasCollision = false;if(movementDistance < 8){hasCollision = checkWallCollision(clampedX,clampedY,ballRadius);}else{hasCollision = checkPathCollision(currentX,currentY,clampedX,clampedY,ballRadius);}if(hasCollision){let foundValidPosition = false;const horizontalOnlyX = clampedX;const horizontalOnlyY = currentY;const horizontalDistance = Math.abs(horizontalOnlyX - currentX);if(horizontalDistance < ballRadius * 3 && !checkWallCollision(horizontalOnlyX,horizontalOnlyY,ballRadius)){const steps = Math.max(2,Math.ceil(horizontalDistance / 2));let canSlideHorizontally = true;for(let i = 1;i <= steps;i++){const t = i / steps;const testX = currentX +(horizontalOnlyX - currentX)* t;if(checkWallCollision(testX,horizontalOnlyY,ballRadius)){canSlideHorizontally = false;break;}}if(canSlideHorizontally){finalX = horizontalOnlyX;finalY = horizontalOnlyY;foundValidPosition = true;}}if(!foundValidPosition){const verticalOnlyX = currentX;const verticalOnlyY = clampedY;const verticalDistance = Math.abs(verticalOnlyY - currentY);if(verticalDistance < ballRadius * 3 && !checkWallCollision(verticalOnlyX,verticalOnlyY,ballRadius)){const steps = Math.max(2,Math.ceil(verticalDistance / 2));let canSlideVertically = true;for(let i = 1;i <= steps;i++){const t = i / steps;const testY = currentY +(verticalOnlyY - currentY)* t;if(checkWallCollision(verticalOnlyX,testY,ballRadius)){canSlideVertically = false;break;}}if(canSlideVertically){finalX = verticalOnlyX;finalY = verticalOnlyY;foundValidPosition = true;}}}hasCollision = !foundValidPosition;}if(!hasCollision){translateX.value = finalX;translateY.value = finalY;runOnJS(onBallPositionChange)({x:finalX,y:finalY});}else{runOnJS(triggerCollisionHaptic)();}}).onEnd(()=>{isDragging.value = false;});const animatedBallStyle = useAnimatedStyle(()=>({transform:[{translateX:translateX.value - gameConfig.BALL_SIZE / 2},{translateY:translateY.value - gameConfig.BALL_SIZE / 2}]}));const renderStartMarker =()=>{const startPos ={x:gameConfig.CELL_SIZE / 2,y:gameConfig.CELL_SIZE / 2};return _jsx(View,{style:[styles.marker,styles.startMarker,{left:startPos.x - 15,top:startPos.y - 15}],children:_jsx(View,{style:styles.startMarkerInner})});};const renderEndMarker =()=>{const endPos ={x:(gameConfig.GRID_SIZE - 1)* gameConfig.CELL_SIZE + gameConfig.CELL_SIZE / 2,y:(gameConfig.GRID_SIZE - 1)* gameConfig.CELL_SIZE + gameConfig.CELL_SIZE / 2};return _jsx(View,{style:[styles.marker,styles.endMarker,{left:endPos.x - 15,top:endPos.y - 15}],children:_jsx(View,{style:styles.endMarkerInner})});};return _jsx(View,{style:[styles.container,{width:gameConfig.GAME_AREA_WIDTH,height:gameConfig.GAME_AREA_HEIGHT}],children:_jsxs(View,{style:[styles.gameArea,{width:gameConfig.GRID_SIZE * gameConfig.CELL_SIZE,height:gameConfig.GRID_SIZE * gameConfig.CELL_SIZE}],children:[_jsx(WallComponent,{walls:walls,width:gameConfig.GRID_SIZE * gameConfig.CELL_SIZE,height:gameConfig.GRID_SIZE * gameConfig.CELL_SIZE}),renderStartMarker(),renderEndMarker(),_jsx(GestureDetector,{gesture:panGesture,children:_jsx(Animated.View,{style:[styles.ballContainer,animatedBallStyle],children:_jsx(EnhancedBallComponent,{position:{x:gameConfig.BALL_SIZE / 2,y:gameConfig.BALL_SIZE / 2},size:gameConfig.BALL_SIZE,isDragging:isDragging.value,isCompleted:gameState.isCompleted})})})]})});});const styles = StyleSheet.create({container:{backgroundColor:'transparent',overflow:'hidden',justifyContent:'center',alignItems:'center'},gameArea:{position:'relative',backgroundColor:'transparent'},ballContainer:{position:'absolute',width:40,height:40,top:0,left:0},marker:{position:'absolute',width:30,height:30,borderRadius:15,justifyContent:'center',alignItems:'center',elevation:5,shadowColor:'#000',shadowOffset:{width:0,height:2},shadowOpacity:0.3,shadowRadius:4},startMarker:{backgroundColor:'#4CAF50',borderWidth:3,borderColor:'#2E7D32'},startMarkerInner:{width:12,height:12,borderRadius:6,backgroundColor:'#81C784'},endMarker:{backgroundColor:'#FF5722',borderWidth:3,borderColor:'#D84315'},endMarkerInner:{width:12,height:12,borderRadius:6,backgroundColor:'#FF8A65'}});
|