Replies: 2 comments
|
This requirement has been fulfilled,Click the link to view. |
0 replies
|
The clean approach is to treat each joystick as its own gesture area with its own shared values, then compose them simultaneously. So instead of one big pan handler for the whole screen, do something like:
That lets both thumbs move at the same time without one gesture stealing the other. Also clamp each joystick to a fixed radius: const r = Math.min(MAX_RADIUS, Math.hypot(dx, dy));
const angle = Math.atan2(dy, dx);
x.value = Math.cos(angle) * r;
y.value = Math.sin(angle) * r; |
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
I'm a beginner in rn and this is my first time using this library. I want to implement dual joystick control. The left and right joysticks do not affect each other and can be controlled simultaneously. I asked the AI but couldn't find a feasible solution, Does anyone know how to achieve this? Here is the code .
----- index.tsx
import React, { useCallback, useRef } from "react";
import { StyleSheet, View, Dimensions } from "react-native";
import { GestureHandlerRootView } from "react-native-gesture-handler";
import { useSharedValue } from "react-native-reanimated";
import { Joystick } from "@/components/game/Joystick";
const { width, height } = Dimensions.get("window");
export default function GameScreen() {
const leftJoystickX = useSharedValue(0);
const leftJoystickY = useSharedValue(0);
const rightJoystickX = useSharedValue(0);
const rightJoystickY = useSharedValue(0);
const lastLeftValues = useRef({ x: 0, y: 0 });
const lastRightValues = useRef({ x: 0, y: 0 });
// Left_joystick
const handleLeftJoystickMove = useCallback((x: number, y: number) => {
const hasChanged =
Math.abs(x - lastLeftValues.current.x) > 0.001 ||
Math.abs(y - lastLeftValues.current.y) > 0.001;
}, []);
// Right_joystick
const handleRightJoystickMove = useCallback((x: number, y: number) => {
const hasChanged =
Math.abs(x - lastRightValues.current.x) > 0.001 ||
Math.abs(y - lastRightValues.current.y) > 0.001;
}, []);
return (
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#E8F5E9",
},
controls: {
position: "absolute",
bottom: 400,
left: 20,
},
rightControls: {
position: "absolute",
bottom: 400,
right: 20,
},
});
----- Joystick.tsx
import React from "react";
import { StyleSheet, View } from "react-native";
import { Gesture, GestureDetector } from "react-native-gesture-handler";
import Animated, { useAnimatedStyle, useSharedValue, withSpring } from "react-native-reanimated";
import { scheduleOnRN } from "react-native-worklets";
interface JoystickProps {
onMove?: (x: number, y: number) => void;
size?: number;
stickSize?: number;
baseColor?: string;
stickColor?: string;
}
export const Joystick: React.FC = ({
onMove,
size = 150,
stickSize = 60,
baseColor = "rgba(0, 0, 0, 0.3)",
stickColor = "rgba(0, 0, 0, 0.6)",
}) => {
const translateX = useSharedValue(0);
const translateY = useSharedValue(0);
const maxDistance = (size - stickSize) / 2;
const reportMove = (x: number, y: number) => {
"worklet";
if (onMove) {
const normalizedX = x / maxDistance;
const normalizedY = y / maxDistance;
scheduleOnRN(onMove, normalizedX, normalizedY);
}
};
const panGesture = Gesture.Pan()
.onUpdate((event) => {
const animatedStyle = useAnimatedStyle(() => ({
transform: [
{ translateX: translateX.value },
{ translateY: translateY.value }
],
}));
return (
);
};
const styles = StyleSheet.create({
base: {
justifyContent: "center",
alignItems: "center",
},
stick: {
position: "absolute",
},
});
All reactions