diff --git a/package-lock.json b/package-lock.json index 6fa0e9c..8fa5443 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,7 +16,8 @@ "leva": "^0.9.35", "react": "^18.2.0", "react-dom": "^18.2.0", - "three": "^0.160.0" + "three": "^0.160.0", + "zustand": "^4.5.0" }, "devDependencies": { "@types/react": "^18.0.28", @@ -972,6 +973,22 @@ } } }, + "node_modules/@react-three/drei/node_modules/zustand": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-3.7.2.tgz", + "integrity": "sha512-PIJDIZKtokhof+9+60cpockVOq05sJzHCriyvaLBmEJixseQ1a5Kdov6fWZfWOu5SK9c+FhH1jU0tntLxRJYMA==", + "engines": { + "node": ">=12.7.0" + }, + "peerDependencies": { + "react": ">=16.8" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + } + } + }, "node_modules/@react-three/fiber": { "version": "8.15.13", "resolved": "https://registry.npmjs.org/@react-three/fiber/-/fiber-8.15.13.tgz", @@ -1028,6 +1045,22 @@ "loose-envify": "^1.1.0" } }, + "node_modules/@react-three/fiber/node_modules/zustand": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-3.7.2.tgz", + "integrity": "sha512-PIJDIZKtokhof+9+60cpockVOq05sJzHCriyvaLBmEJixseQ1a5Kdov6fWZfWOu5SK9c+FhH1jU0tntLxRJYMA==", + "engines": { + "node": ">=12.7.0" + }, + "peerDependencies": { + "react": ">=16.8" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + } + } + }, "node_modules/@react-three/postprocessing": { "version": "2.15.11", "resolved": "https://registry.npmjs.org/@react-three/postprocessing/-/postprocessing-2.15.11.tgz", @@ -2140,6 +2173,22 @@ "react-dom": ">=16.8.0" } }, + "node_modules/leva/node_modules/zustand": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-3.7.2.tgz", + "integrity": "sha512-PIJDIZKtokhof+9+60cpockVOq05sJzHCriyvaLBmEJixseQ1a5Kdov6fWZfWOu5SK9c+FhH1jU0tntLxRJYMA==", + "engines": { + "node": ">=12.7.0" + }, + "peerDependencies": { + "react": ">=16.8" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + } + } + }, "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", @@ -2948,6 +2997,14 @@ "react": ">=17.0" } }, + "node_modules/use-sync-external-store": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", + "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/utility-types": { "version": "3.10.0", "resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.10.0.tgz", @@ -3074,16 +3131,27 @@ "integrity": "sha512-DCo0oxvcvOTGP/f5FA6tz2Z6wF+FIcEApSTu0zV5sQgn9hoT5lZ9YRAKUraxt9oP7l4e8TnNdi8IZTCX6WCkwA==" }, "node_modules/zustand": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/zustand/-/zustand-3.7.2.tgz", - "integrity": "sha512-PIJDIZKtokhof+9+60cpockVOq05sJzHCriyvaLBmEJixseQ1a5Kdov6fWZfWOu5SK9c+FhH1jU0tntLxRJYMA==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.0.tgz", + "integrity": "sha512-zlVFqS5TQ21nwijjhJlx4f9iGrXSL0o/+Dpy4txAP22miJ8Ti6c1Ol1RLNN98BMib83lmDH/2KmLwaNXpjrO1A==", + "dependencies": { + "use-sync-external-store": "1.2.0" + }, "engines": { "node": ">=12.7.0" }, "peerDependencies": { + "@types/react": ">=16.8", + "immer": ">=9.0.6", "react": ">=16.8" }, "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "immer": { + "optional": true + }, "react": { "optional": true } diff --git a/package.json b/package.json index 607d87b..9f8af88 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,8 @@ "leva": "^0.9.35", "react": "^18.2.0", "react-dom": "^18.2.0", - "three": "^0.160.0" + "three": "^0.160.0", + "zustand": "^4.5.0" }, "devDependencies": { "@types/react": "^18.0.28", diff --git a/src/App.jsx b/src/App.jsx index d94e99a..ca5c783 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -44,8 +44,10 @@ function App() { + {/* */} + ); } diff --git a/src/components/DriftParticlesLeft.jsx b/src/components/DriftParticlesLeft.jsx new file mode 100644 index 0000000..b6de039 --- /dev/null +++ b/src/components/DriftParticlesLeft.jsx @@ -0,0 +1,28 @@ +import { Particles1 } from "./Particles1"; +import { Particles3 } from "./Particles3"; + +export const DriftParticlesLeft = ({turboColor,scale, ...props}) => { + + if(scale < 0.5) { + return null; + } + + return ( + + + + + + + + + + + + + + + + + ) +} \ No newline at end of file diff --git a/src/components/DriftParticlesRight.jsx b/src/components/DriftParticlesRight.jsx new file mode 100644 index 0000000..4ef8a28 --- /dev/null +++ b/src/components/DriftParticlesRight.jsx @@ -0,0 +1,28 @@ +import { Particles2 } from "./Particles2"; +import { Particles4 } from "./Particles4"; + +export const DriftParticlesRight = ({turboColor,scale, ...props}) => { + + if(scale < 0.5) { + return null; + } + + return ( + + + + + + + + + + + + + + + + + ) +} \ No newline at end of file diff --git a/src/components/Experience.jsx b/src/components/Experience.jsx index de8093b..49391b6 100644 --- a/src/components/Experience.jsx +++ b/src/components/Experience.jsx @@ -9,7 +9,7 @@ import { RigidBody } from "@react-three/rapier"; import { PlayerController } from "./PlayerController"; import { Track } from "./models/Spafrancorchamps-REALISTIC"; import { Paris } from "./models/Tour_paris_promenade"; -import { EffectComposer, N8AO, Bloom, DepthOfField, TiltShift2, HueSaturation} from '@react-three/postprocessing' +import { EffectComposer, N8AO, Bloom, DepthOfField, TiltShift2, HueSaturation, SMAA} from '@react-three/postprocessing' export const Experience = () => { return ( @@ -34,7 +34,8 @@ export const Experience = () => { {/* */} {/* */} - + + {/* */} diff --git a/src/components/Particles1.jsx b/src/components/Particles1.jsx index 8c82078..33ebc3e 100644 --- a/src/components/Particles1.jsx +++ b/src/components/Particles1.jsx @@ -1,2 +1,47 @@ -export const Particles1 = () => { -} \ No newline at end of file +import { useRef } from "react"; +import { useFrame } from "@react-three/fiber"; + +export const Particles1 = ({ turboColor, scale, ...props }) => { + const ref = useRef(); + const frame = useRef(0); + + const velocity = useRef({ + x: -Math.random() * 0.1, + y: Math.random() * 0.05, + z: Math.random() * 0.05, + }); + const gravity = -0.003; + + useFrame(() => { + frame.current += 1; + let position = ref.current.position; + + velocity.current.y += gravity; + + position.x += velocity.current.x; + position.y += velocity.current.y; + position.z += velocity.current.z; + + if (position.y < 0) { + position.set(-0.6, 0.05, 0.5); + velocity.current = { + x: -Math.random() * 0.1, + y: Math.random() * 0.05, + z: Math.random() * 0.05, + }; + } + + ref.current.position.set(position.x, position.y, position.z); + }); + + return ( + + + + + ); +}; diff --git a/src/components/Particles2.jsx b/src/components/Particles2.jsx new file mode 100644 index 0000000..69d86a8 --- /dev/null +++ b/src/components/Particles2.jsx @@ -0,0 +1,47 @@ +import { useRef } from "react"; +import { useFrame } from "@react-three/fiber"; + +export const Particles2 = ({ turboColor, scale, ...props }) => { + const ref = useRef(); + const frame = useRef(0); + + const velocity = useRef({ + x: Math.random() * 0.1, + y: Math.random() * 0.05, + z: Math.random() * 0.05, + }); + const gravity = -0.003; + + useFrame(() => { + frame.current += 1; + let position = ref.current.position; + + velocity.current.y += gravity; + + position.x += velocity.current.x; + position.y += velocity.current.y; + position.z += velocity.current.z; + + if (position.y < 0) { + position.set(0.6, 0.05, 0.5); + velocity.current = { + x: Math.random() * 0.1, + y: Math.random() * 0.05, + z: Math.random() * 0.05, + }; + } + + ref.current.position.set(position.x, position.y, position.z); + }); + + return ( + + + + + ); +}; diff --git a/src/components/Particles3.jsx b/src/components/Particles3.jsx new file mode 100644 index 0000000..038b569 --- /dev/null +++ b/src/components/Particles3.jsx @@ -0,0 +1,48 @@ +import { useRef } from "react"; +import { useFrame } from "@react-three/fiber"; +import { Trail } from "@react-three/drei"; + +export const Particles3 = ({ turboColor, scale, ...props }) => { + const ref = useRef(); + const frame = useRef(0); + + const velocity = useRef({ + x: -Math.random() * 0.1, + y: Math.random() * 0.1, + z: Math.random() * 0.05, + }); + const gravity = -0.003; + + useFrame(() => { + frame.current += 1; + let position = ref.current.position; + + velocity.current.y += gravity; + + position.x += velocity.current.x; + position.y += velocity.current.y; + position.z += velocity.current.z; + + if (position.y < 0) { + position.set(-0.6, 0.05, 0.5); + velocity.current = { + x: -Math.random() * 0.1, + y: Math.random() * 0.1, + z: Math.random() * 0.05, + }; + } + + ref.current.position.set(position.x, position.y, position.z); + }); + + return ( + + + + + ); +}; diff --git a/src/components/Particles4.jsx b/src/components/Particles4.jsx new file mode 100644 index 0000000..0dbe041 --- /dev/null +++ b/src/components/Particles4.jsx @@ -0,0 +1,48 @@ +import { useRef } from "react"; +import { useFrame } from "@react-three/fiber"; +import { Trail } from "@react-three/drei"; + +export const Particles4 = ({ turboColor, scale, ...props }) => { + const ref = useRef(); + const frame = useRef(0); + + const velocity = useRef({ + x: Math.random() * 0.1, + y: Math.random() * 0.2, + z: Math.random() * 0.05, + }); + const gravity = -0.003; + + useFrame(() => { + frame.current += 1; + let position = ref.current.position; + + velocity.current.y += gravity; + + position.x += velocity.current.x; + position.y += velocity.current.y; + position.z += velocity.current.z; + + if (position.y < 0) { + position.set(0.6, 0.05, 0.5); + velocity.current = { + x: Math.random() * 0.1, + y: Math.random() * 0.1, + z: Math.random() * 0.05, + }; + } + + ref.current.position.set(position.x, position.y, position.z); + }); + + return ( + + + + + ); +}; diff --git a/src/components/PlayerController.jsx b/src/components/PlayerController.jsx index a679fdf..b2e71a6 100644 --- a/src/components/PlayerController.jsx +++ b/src/components/PlayerController.jsx @@ -14,6 +14,9 @@ import { FrontLeftWheel } from "./models/Front_Left_Wheel"; import { RearWheels } from "./models/Rear_wheels"; import gsap from "gsap"; import { Mario } from "./models/Mario_kart"; +import { Particles1 } from "./Particles1"; +import { DriftParticlesLeft } from "./DriftParticlesLeft"; +import { DriftParticlesRight } from "./DriftParticlesRight"; export const PlayerController = () => { const upPressed = useKeyboardControls((state) => state[Controls.up]); @@ -91,9 +94,13 @@ export const PlayerController = () => { if (upPressed && currentSpeed < maxSpeed) { // Accelerate the kart within the maximum speed limit setCurrentSpeed(Math.min(currentSpeed + acceleration, maxSpeed)); - } else if (upPressed && currentSpeed > maxSpeed && boostDuration.current > 0){ + } else if ( + upPressed && + currentSpeed > maxSpeed && + boostDuration.current > 0 + ) { setCurrentSpeed(Math.max(currentSpeed - decceleration, maxSpeed)); - } + } if (upPressed) { if (currentSteeringSpeed < MaxSteeringSpeed) { @@ -116,7 +123,6 @@ export const PlayerController = () => { setCurrentSpeed(Math.max(currentSpeed - decceleration, 0)); } - // Update the kart's rotation based on the steering angle kart.current.rotation.y += steeringAngle; @@ -179,7 +185,6 @@ export const PlayerController = () => { ); setTurboColor(0xffffff); accumulatedDriftPower.current = 0; - } if (driftLeft.current) { @@ -187,7 +192,7 @@ export const PlayerController = () => { driftForce.current = 0.4; mario.current.rotation.y = THREE.MathUtils.lerp( mario.current.rotation.y, - (steeringAngle * 50 + 0.5), + steeringAngle * 50 + 0.5, 0.1 ); accumulatedDriftPower.current += 0.1 * (steeringAngle + 1); @@ -223,22 +228,21 @@ export const PlayerController = () => { boostDuration.current = 250; } - if(driftLeft.current || driftRight.current){ + if (driftLeft.current || driftRight.current) { const oscillation = Math.sin(time * 1000) * 0.1; const vibration = oscillation + 0.9; setScale(vibration); } - // RELEASING DRIFT + // RELEASING DRIFT if (boostDuration.current > 1 && !jumpIsHeld.current) { setCurrentSpeed(boostSpeed); boostDuration.current -= 1; targetZPosition = 10; - } else if (boostDuration.current <= 1) { + } else if (boostDuration.current <= 1) { targetZPosition = 8; } - // CAMERA WORK @@ -249,7 +253,7 @@ export const PlayerController = () => { targetXPosition, 0.01 ); - + cam.current.position.z = THREE.MathUtils.lerp( cam.current.position.z, targetZPosition, @@ -268,7 +272,6 @@ export const PlayerController = () => { // Update the kart's rotation based on the steering angle setSteeringAngleWheels(steeringAngle * 25); - console.log(scale) }); return ( @@ -276,7 +279,7 @@ export const PlayerController = () => { { @@ -291,29 +294,44 @@ export const PlayerController = () => { - + - + - + - + + + {/* */} diff --git a/src/components/store.jsx b/src/components/store.jsx new file mode 100644 index 0000000..bb1e5be --- /dev/null +++ b/src/components/store.jsx @@ -0,0 +1,33 @@ +import { create } from "zustand"; + +export const useStore = create((set, get) => ({ + return : { + particles1: [], + particles2: [], + actions : { + addParticle1: (particle) => { + set((state) => ({ + particles1: [...state.particles1, particle], + })); + }, + removeParticle1: (particle) => { + set((state) => ({ + particles1: state.particles1.filter((p) => p.id !== particle.id), + })); + }, + addParticle2: (particle) => { + set((state) => ({ + particles2: [...state.particles2, particle], + })); + }, + removeParticle2: (particle) => { + set((state) => ({ + particles2: state.particles2.filter((p) => p.id !== particle.id), + })); + }, + }, + + + + } +})); \ No newline at end of file