Skip to content

Instantly share code, notes, and snippets.

@flunder
Created January 26, 2024 01:25
Show Gist options
  • Save flunder/84ab1be381d58d0c05f3d751bf2a1cb8 to your computer and use it in GitHub Desktop.
Save flunder/84ab1be381d58d0c05f3d751bf2a1cb8 to your computer and use it in GitHub Desktop.
ReactNative Reanimated Ball Bouncing of Walls
import React, { useEffect } from "react";
import { StyleSheet, View } from "react-native";
import Animated, {
useAnimatedStyle,
useSharedValue
} from "react-native-reanimated";
import { viewPort } from "@project/utils";
const BALL_SIZE = 20;
const Bounce = () => {
const locationX = useSharedValue(15);
const locationY = useSharedValue(255);
const speed = useSharedValue(10);
const angle = useSharedValue(60);
const min_X = useSharedValue(0);
const max_X = useSharedValue(viewPort.width - BALL_SIZE);
const min_Y = useSharedValue(0);
const max_Y = useSharedValue(viewPort.height - BALL_SIZE);
const degToRad = (degrees: number) => {
var pi = Math.PI;
return degrees * (pi / 180);
};
const angleReflect = (incidenceAngle: number, surfaceAngle: number) => {
var a = surfaceAngle * 2 - incidenceAngle;
return a >= 360 ? a - 360 : a < 0 ? a + 360 : a;
};
const progress = () => {
locationX.value += speed.value * Math.sin(degToRad(angle.value));
locationY.value += speed.value * Math.cos(degToRad(angle.value));
if (locationX.value > max_X.value) {
angle.value = angleReflect(angle.value, 0);
locationX.value = max_X.value;
} else if (locationX.value < min_X.value) {
angle.value = angleReflect(angle.value, 0);
locationX.value = min_X.value;
}
if (locationY.value > max_Y.value) {
angle.value = angleReflect(angle.value, 90);
locationY.value = max_Y.value;
} else if (locationY.value < min_Y.value) {
angle.value = angleReflect(angle.value, 90);
locationY.value = min_Y.value;
}
setTimeout(progress, 10);
};
const start = () => {
setTimeout(progress, 100);
};
const animatedStyle = useAnimatedStyle(() => {
return {
transform: [
{ translateX: locationX.value },
{ translateY: locationY.value }
]
};
});
useEffect(() => {
start();
}, []);
return (
<View style={{ flex: 1 }}>
<Animated.View style={animatedStyle}>
<View style={styles.ball} />
</Animated.View>
</View>
);
};
const styles = StyleSheet.create({
ball: {
backgroundColor: "red",
position: "absolute",
borderRadius: 100,
width: BALL_SIZE,
height: BALL_SIZE
}
});
export { Bounce };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment