diff --git a/public/particles/smokes/smoke_01.png b/public/particles/smokes/smoke_01.png
new file mode 100644
index 0000000..1cd418e
Binary files /dev/null and b/public/particles/smokes/smoke_01.png differ
diff --git a/public/particles/smokes/smoke_02.png b/public/particles/smokes/smoke_02.png
new file mode 100644
index 0000000..d866368
Binary files /dev/null and b/public/particles/smokes/smoke_02.png differ
diff --git a/public/particles/smokes/smoke_03.png b/public/particles/smokes/smoke_03.png
new file mode 100644
index 0000000..909717a
Binary files /dev/null and b/public/particles/smokes/smoke_03.png differ
diff --git a/public/particles/smokes/smoke_04.png b/public/particles/smokes/smoke_04.png
new file mode 100644
index 0000000..74a2695
Binary files /dev/null and b/public/particles/smokes/smoke_04.png differ
diff --git a/public/particles/smokes/smoke_05.png b/public/particles/smokes/smoke_05.png
new file mode 100644
index 0000000..0ac46dc
Binary files /dev/null and b/public/particles/smokes/smoke_05.png differ
diff --git a/public/particles/smokes/smoke_06.png b/public/particles/smokes/smoke_06.png
new file mode 100644
index 0000000..300c5fa
Binary files /dev/null and b/public/particles/smokes/smoke_06.png differ
diff --git a/public/particles/smokes/smoke_07.png b/public/particles/smokes/smoke_07.png
new file mode 100644
index 0000000..fb78c0f
Binary files /dev/null and b/public/particles/smokes/smoke_07.png differ
diff --git a/public/particles/smokes/smoke_08.png b/public/particles/smokes/smoke_08.png
new file mode 100644
index 0000000..feec49e
Binary files /dev/null and b/public/particles/smokes/smoke_08.png differ
diff --git a/src/App.jsx b/src/App.jsx
index 6a7b1a5..3201e8a 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -38,7 +38,7 @@ function App() {
const { actions } = useStore();
const start = async () => {
- await insertCoin();
+ await insertCoin({ skipLobby: true});
onPlayerJoin((state) => {
actions.addPlayer(state);
diff --git a/src/components/Dust.jsx b/src/components/Dust.jsx
new file mode 100644
index 0000000..a0c21cb
--- /dev/null
+++ b/src/components/Dust.jsx
@@ -0,0 +1,86 @@
+import { Euler, Object3D, Vector3, Matrix4, DoubleSide, Quaternion, TextureLoader, BackSide } from 'three'
+import { useRef, useLayoutEffect } from 'react'
+import { useFrame, useLoader } from '@react-three/fiber'
+import { vec3 } from '@react-three/rapier'
+
+
+import { useStore } from './store'
+
+
+const e = new Euler()
+const m = new Matrix4()
+const o = new Object3D()
+const v = new Vector3()
+const q = new Quaternion()
+
+
+
+export function Dust({ count = 500, opacity = 0.1, size = 0.6 }) {
+ const smoke01 = useLoader(TextureLoader, './particles/smokes/smoke_01.png');
+ const smoke02 = useLoader(TextureLoader, './particles/smokes/smoke_02.png');
+ const smoke03 = useLoader(TextureLoader, './particles/smokes/smoke_03.png');
+ const smoke04 = useLoader(TextureLoader, './particles/smokes/smoke_04.png');
+ const smoke05 = useLoader(TextureLoader, './particles/smokes/smoke_05.png');
+ const smoke06 = useLoader(TextureLoader, './particles/smokes/smoke_06.png');
+ const smoke07 = useLoader(TextureLoader, './particles/smokes/smoke_07.png');
+ const smoke08 = useLoader(TextureLoader, './particles/smokes/smoke_08.png');
+
+ const texture = [smoke01, smoke02, smoke03, smoke04, smoke05, smoke06, smoke07, smoke08]
+ const ref = useRef(null);
+ const { leftWheel, rightWheel } = useStore();
+ let index = 0
+ let time = 0
+ let i = 0
+ useFrame((state,delta ) => {
+ const rotation = leftWheel.kartRotation;
+ if (state.clock.getElapsedTime() - time > 0.02 && leftWheel && rightWheel && ref.current && leftWheel.isSpinning) {
+ time = state.clock.getElapsedTime()
+ setItemAt(ref.current, rotation, leftWheel, index++);
+ setItemAt(ref.current, rotation, rightWheel, index++);
+
+ if (index === count) index = 0
+ } else {
+ // Shrink old one
+ for (i = 0; i < count; i++) {
+ const direction = new Vector3(Math.sin(time * 6 + i * 10) , 2, 0);
+ ref.current.getMatrixAt(i, m)
+ m.decompose(o.position, q, v)
+ o.scale.setScalar(Math.max(0, v.x - 0.005))
+ o.position.addScaledVector(direction, 0.01)
+ o.updateMatrix()
+ ref.current.setMatrixAt(i, o.matrix)
+ ref.current.instanceMatrix.needsUpdate = true
+ }
+ }
+ })
+
+ useLayoutEffect(() => {
+ if(ref.current){
+ ref.current.geometry.rotateY(-Math.PI / 2)
+ return () => {
+ ref.current.geometry.rotateY(Math.PI / 2)
+ }
+ }
+ })
+
+ return (
+
+
+
+
+ )
+}
+
+function setItemAt(instances, rotation, body, index) {
+ const randomOffset = (Math.random() - 0.5) * 0.3 ;
+ const pos = body.getWorldPosition(v);
+ o.rotation.set(0, rotation + Math.PI / 2, 0);
+ pos.x += randomOffset
+ // pos.y += randomOffset
+ pos.z += randomOffset
+ o.position.copy(pos);
+ o.scale.setScalar(1)
+ o.updateMatrix()
+ instances.setMatrixAt(index, o.matrix)
+ instances.instanceMatrix.needsUpdate = true
+}
diff --git a/src/components/Experience.jsx b/src/components/Experience.jsx
index 511e0cc..13d734e 100644
--- a/src/components/Experience.jsx
+++ b/src/components/Experience.jsx
@@ -42,6 +42,8 @@ import { useFrame, useLoader } from "@react-three/fiber";
import { LUTPass, LUTCubeLoader } from "three-stdlib";
import { useCurvedPathPoints } from "./useCurvedPath";
import { ParisBis } from "./models/tracks/Paris-bis";
+import { Skid } from "./Skid";
+import { Dust } from "./Dust";
export const Experience = () => {
const onCollide = (event) => {};
@@ -151,10 +153,11 @@ export const Experience = () => {
+
+
-
{networkBananas.map((banana) => (
{
+ if (leftWheel.current && rightWheel.current && body.current) {
+ actions.setLeftWheel(leftWheel.current);
+ actions.setRightWheel(rightWheel.current);
+ }
+ }, [body.current]);
useFrame(({ pointer, clock }, delta) => {
if (player.id !== id) return;
const time = clock.getElapsedTime();
@@ -115,11 +124,13 @@ export const PlayerController = ({
0,
-Math.cos(kartRotation)
);
-
+
if (escPressed) {
actions.setGameStarted(false);
}
-
+ if(kartRotation){
+ leftWheel.current.kartRotation = kartRotation;
+ }
if (leftPressed && currentSpeed > 0) {
steeringAngle = currentSteeringSpeed;
targetXPosition = -camMaxOffset;
@@ -179,6 +190,8 @@ export const PlayerController = ({
}
}
if (shouldSlow) {
+ rightWheel.current.isSpinning = true;
+
setCurrentSpeed(
Math.max(currentSpeed - decceleration * 2 * delta * 144, 0)
);
@@ -186,6 +199,7 @@ export const PlayerController = ({
slowDownDuration.current -= 1500 * delta;
setShouldLaunch(true);
if (slowDownDuration.current <= 1) {
+ rightWheel.current.isSpinning = false;
actions.setShouldSlowDown(false);
slowDownDuration.current = 1500;
setShouldLaunch(false);
@@ -311,7 +325,11 @@ export const PlayerController = ({
steeringAngle * 25 + 0.4,
0.05 * delta * 144
);
- accumulatedDriftPower.current += 0.1 * (steeringAngle + 1) * delta * 144;
+ if (isOnFloor.current) {
+ leftWheel.current.isSpinning = true;
+ accumulatedDriftPower.current +=
+ 0.1 * (steeringAngle + 1) * delta * 144;
+ }
}
if (driftRight.current) {
driftDirection.current = -1;
@@ -321,7 +339,11 @@ export const PlayerController = ({
-(-steeringAngle * 25 + 0.4),
0.05 * delta * 144
);
- accumulatedDriftPower.current += 0.1 * (-steeringAngle + 1) * delta * 144;
+ if(isOnFloor.current){
+ leftWheel.current.isSpinning = true;
+ accumulatedDriftPower.current += 0.1 * (-steeringAngle + 1) * delta * 144;
+
+ }
}
if (!driftLeft.current && !driftRight.current) {
mario.current.rotation.y = THREE.MathUtils.lerp(
@@ -330,6 +352,11 @@ export const PlayerController = ({
0.05 * delta * 144
);
setScale(0);
+ if((pointer.x > 0.8 || pointer.x < -0.8) && currentSpeed > 20 && isOnFloor.current){
+ leftWheel.current.isSpinning = true;
+ } else {
+ leftWheel.current.isSpinning = false;
+ }
}
if (accumulatedDriftPower.current > blueTurboThreshold) {
setTurboColor(0x00ffff);
@@ -559,6 +586,8 @@ export const PlayerController = ({
opacity={0.4}
/>
+
+
*/}
-
+
{
-
const [isOnGround, setIsOnGround] = useState(false);
const body = useRef();
const kart = useRef();
@@ -84,14 +82,28 @@ export const PlayerControllerGamepad = ({
const effectiveBoost = useRef(0);
const text = useRef();
- const { actions, shouldSlowDown, item, bananas, coins, id, controls } = useStore();
+ const { actions, shouldSlowDown, item, bananas, coins, id, controls } =
+ useStore();
const slowDownDuration = useRef(1500);
const { buttonA, buttonB, RB, LB, joystick, select, start } = useGamepad();
+ const skidRotation = useRef(0);
+
+ const rightWheel = useRef();
+ const leftWheel = useRef();
+ const isDrifting = useRef(false);
+ useEffect(() => {
+ if (leftWheel.current && rightWheel.current && body.current) {
+ actions.setLeftWheel(leftWheel.current);
+ actions.setRightWheel(rightWheel.current);
+ }
+ }, [body.current]);
+
useFrame(({ pointer, clock }, delta) => {
if (player.id !== id) return;
const time = clock.getElapsedTime();
if (!body.current && !mario.current) return;
+ isDrifting.current = driftLeft.current || driftRight.current;
engineSound.current.setVolume(currentSpeed / 300 + 0.2);
engineSound.current.setPlaybackRate(currentSpeed / 10 + 0.1);
jumpSound.current.setPlaybackRate(1.5);
@@ -113,8 +125,7 @@ export const PlayerControllerGamepad = ({
if (start) {
actions.setGameStarted(false);
}
-
- // mouse steering
+ leftWheel.current.kartRotation = kartRotation ;
if (!driftLeft.current && !driftRight.current) {
steeringAngle = currentSteeringSpeed * -joystick[0];
@@ -155,6 +166,7 @@ export const PlayerControllerGamepad = ({
}
}
if (shouldSlow) {
+ rightWheel.current.isSpinning = true;
setCurrentSpeed(
Math.max(currentSpeed - decceleration * 2 * delta * 144, 0)
);
@@ -162,6 +174,7 @@ export const PlayerControllerGamepad = ({
slowDownDuration.current -= 1500 * delta;
setShouldLaunch(true);
if (slowDownDuration.current <= 1) {
+ rightWheel.current.isSpinning = false;
actions.setShouldSlowDown(false);
slowDownDuration.current = 1500;
setShouldLaunch(false);
@@ -285,9 +298,13 @@ export const PlayerControllerGamepad = ({
steeringAngle * 25 + 0.4,
0.05 * delta * 144
);
- accumulatedDriftPower.current += 0.1 * (steeringAngle + 1) * delta * 144;
+ if(isOnFloor.current){
+ leftWheel.current.isSpinning = true;
+ accumulatedDriftPower.current += 0.1 * (steeringAngle + 1) * delta * 144;
+
+ }
}
- if (driftRight.current) {
+ if (driftRight.current ) {
driftDirection.current = -1;
driftForce.current = 0.4;
mario.current.rotation.y = THREE.MathUtils.lerp(
@@ -295,7 +312,11 @@ export const PlayerControllerGamepad = ({
-(-steeringAngle * 25 + 0.4),
0.05 * delta * 144
);
- accumulatedDriftPower.current += 0.1 * (-steeringAngle + 1) * delta * 144;
+ if(isOnFloor.current){
+ leftWheel.current.isSpinning = true;
+ accumulatedDriftPower.current += 0.1 * (-steeringAngle + 1) * delta * 144;
+
+ }
}
if (!driftLeft.current && !driftRight.current) {
mario.current.rotation.y = THREE.MathUtils.lerp(
@@ -304,6 +325,12 @@ export const PlayerControllerGamepad = ({
0.05 * delta * 144
);
setScale(0);
+
+ if((joystick[0] > 0.8 || joystick[0] < -0.8) && currentSpeed > 20 && isOnFloor.current){
+ leftWheel.current.isSpinning = true;
+ } else {
+ leftWheel.current.isSpinning = false;
+ }
}
if (accumulatedDriftPower.current > blueTurboThreshold) {
setTurboColor(0x00ffff);
@@ -373,6 +400,7 @@ export const PlayerControllerGamepad = ({
0.01 * delta * 144
);
+
cam.current.position.z = THREE.MathUtils.lerp(
cam.current.position.z,
targetZPosition,
@@ -466,6 +494,8 @@ export const PlayerControllerGamepad = ({
player.setState("turboColor", turboColor);
player.setState("scale", scale);
player.setState("bananas", bananas);
+
+ skidRotation.current = kartRotation + mario.current.rotation.y;
});
return player.id === id ? (
@@ -504,7 +534,7 @@ export const PlayerControllerGamepad = ({
/>
-
+
+
+
{/* */}
-
{
+ if (leftWheel.current && rightWheel.current && body.current) {
+ actions.setLeftWheel(leftWheel.current);
+ actions.setRightWheel(rightWheel.current);
+ }
+ }, [body.current]);
+
useFrame(({ pointer, clock }, delta) => {
if (player.id !== id) return;
const time = clock.getElapsedTime();
@@ -116,7 +127,7 @@ export const PlayerControllerKeyboard = ({
0,
-Math.cos(kartRotation)
);
-
+ leftWheel.current.kartRotation = kartRotation;
if (escPressed) {
actions.setGameStarted(false);
}
@@ -168,6 +179,7 @@ export const PlayerControllerKeyboard = ({
}
}
if (shouldSlow) {
+ rightWheel.current.isSpinning = true;
setCurrentSpeed(
Math.max(currentSpeed - decceleration * 2 * delta * 144, 0)
);
@@ -175,6 +187,7 @@ export const PlayerControllerKeyboard = ({
slowDownDuration.current -= 1500 * delta;
setShouldLaunch(true);
if (slowDownDuration.current <= 1) {
+ rightWheel.current.isSpinning = false;
actions.setShouldSlowDown(false);
slowDownDuration.current = 1500;
setShouldLaunch(false);
@@ -300,7 +313,11 @@ export const PlayerControllerKeyboard = ({
steeringAngle * 25 + 0.4,
0.05 * delta * 144
);
- accumulatedDriftPower.current += 0.1 * (steeringAngle + 1) * delta * 144;
+ if (isOnFloor.current) {
+ leftWheel.current.isSpinning = true;
+ accumulatedDriftPower.current +=
+ 0.1 * (steeringAngle + 1) * delta * 144;
+ }
}
if (driftRight.current) {
driftDirection.current = -1;
@@ -310,7 +327,11 @@ export const PlayerControllerKeyboard = ({
-(-steeringAngle * 25 + 0.4),
0.05 * delta * 144
);
- accumulatedDriftPower.current += 0.1 * (-steeringAngle + 1) * delta * 144;
+ if (isOnFloor.current) {
+ leftWheel.current.isSpinning = true;
+ accumulatedDriftPower.current +=
+ 0.1 * (-steeringAngle + 1) * delta * 144;
+ }
}
if (!driftLeft.current && !driftRight.current) {
mario.current.rotation.y = THREE.MathUtils.lerp(
@@ -319,6 +340,11 @@ export const PlayerControllerKeyboard = ({
0.05 * delta * 144
);
setScale(0);
+ if((leftPressed || rightPressed) && currentSpeed > 20 && isOnFloor.current){
+ leftWheel.current.isSpinning = true;
+ } else {
+ leftWheel.current.isSpinning = false;
+ }
}
if (accumulatedDriftPower.current > blueTurboThreshold) {
setTurboColor(0x00ffff);
@@ -529,6 +555,8 @@ export const PlayerControllerKeyboard = ({
opacity={0.4}
/>
+
+
+
*/}
-
+
{
+ if (leftWheel.current && rightWheel.current && body.current) {
+ actions.setLeftWheel(leftWheel.current);
+ actions.setRightWheel(rightWheel.current);
+ }
+ }, [body.current]);
useFrame(({ pointer, clock }, delta) => {
if (player.id !== id) return;
@@ -108,7 +117,7 @@ export const PlayerControllerTouch = ({
0,
-Math.cos(kartRotation)
);
-
+ leftWheel.current.kartRotation = kartRotation;
if (menuButton) {
actions.setGameStarted(false);
}
@@ -153,6 +162,8 @@ export const PlayerControllerTouch = ({
);
}
if (shouldSlow) {
+ rightWheel.current.isSpinning = true;
+
setCurrentSpeed(
Math.max(currentSpeed - decceleration * 2 * delta * 144, 0)
);
@@ -160,6 +171,8 @@ export const PlayerControllerTouch = ({
slowDownDuration.current -= 1500 * delta;
setShouldLaunch(true);
if (slowDownDuration.current <= 1) {
+ rightWheel.current.isSpinning = false;
+
actions.setShouldSlowDown(false);
slowDownDuration.current = 1500;
setShouldLaunch(false);
@@ -252,7 +265,11 @@ export const PlayerControllerTouch = ({
steeringAngle * 25 + 0.4,
0.05 * delta * 144
);
- accumulatedDriftPower.current += 0.1 * (steeringAngle + 1) * delta * 144;
+ if(isOnFloor.current){
+ leftWheel.current.isSpinning = true;
+ accumulatedDriftPower.current += 0.1 * (steeringAngle + 1) * delta * 144;
+
+ }
}
if (driftRight.current) {
driftDirection.current = -1;
@@ -262,7 +279,11 @@ export const PlayerControllerTouch = ({
-(-steeringAngle * 25 + 0.4),
0.05 * delta * 144
);
- accumulatedDriftPower.current += 0.1 * (-steeringAngle + 1) * delta * 144;
+ if(isOnFloor.current){
+ leftWheel.current.isSpinning = true;
+ accumulatedDriftPower.current += 0.1 * (-steeringAngle + 1) * delta * 144;
+
+ }
}
if (!driftLeft.current && !driftRight.current) {
mario.current.rotation.y = THREE.MathUtils.lerp(
@@ -271,6 +292,11 @@ export const PlayerControllerTouch = ({
0.05 * delta * 144
);
setScale(0);
+ if((joystickX > 0.8 || joystickX < -0.8) && currentSpeed > 20 && isOnFloor.current){
+ leftWheel.current.isSpinning = true;
+ } else {
+ leftWheel.current.isSpinning = false;
+ }
}
if (accumulatedDriftPower.current > blueTurboThreshold) {
setTurboColor(0x00ffff);
@@ -466,6 +492,8 @@ export const PlayerControllerTouch = ({
opacity={0.4}
/>
+
+
{
+ const rotation = leftWheel.kartRotation;
+ if (leftWheel && rightWheel && ref.current && (leftWheel.isSpinning || rightWheel.isSpinning)) {
+ setItemAt(ref.current, rotation, leftWheel, index++);
+ setItemAt(ref.current, rotation, rightWheel, index++);
+
+ if (index === count) index = 0
+ }
+ })
+
+ useLayoutEffect(() => {
+ if(ref.current){
+ ref.current.geometry.rotateX(-Math.PI / 2)
+ return () => {
+ ref.current.geometry.rotateX(Math.PI / 2)
+ }
+ }
+ })
+
+ return (
+
+
+
+
+ )
+}
+
+function setItemAt(instances, rotation, body, index) {
+ o.position.copy(body.getWorldPosition(v));
+ o.rotation.set(0, rotation, 0);
+ o.scale.setScalar(1)
+ o.updateMatrix()
+ instances.setMatrixAt(index, o.matrix)
+ instances.instanceMatrix.needsUpdate = true
+}
diff --git a/src/components/store.jsx b/src/components/store.jsx
index dd0d05f..6be91ad 100644
--- a/src/components/store.jsx
+++ b/src/components/store.jsx
@@ -13,12 +13,13 @@ export const items = [
]
export const useStore = create((set, get) => ({
- gameStarted: false,
- controls: "",
+ gameStarted: true,
+ controls: "gamepad",
particles1: [],
particles2: [],
- bodyPosition: [0, 0, 0],
- bodyRotation: [0, 0, 0],
+ leftWheel: null,
+ rightWheel: null,
+ bodyRotation: null,
pastPositions: [],
shouldSlowdown: false,
bananas: [],
@@ -28,11 +29,13 @@ export const useStore = create((set, get) => ({
skids: [],
coins : 0,
players : [],
+ body: null,
id : "",
joystickX: 0,
driftButton: false,
itemButton: false,
menuButton: false,
+ isDrifting: false,
addPastPosition: (position) => {
set((state) => ({
pastPositions: [position, ...state.pastPositions.slice(0, 499)],
@@ -63,7 +66,7 @@ export const useStore = create((set, get) => ({
set({ bodyPosition: position });
},
setBodyRotation: (rotation) => {
- set({ bodyRotation: rotation });
+ set({ rotation });
},
getBodyPosition: () => {
return get().bodyPosition;
@@ -164,6 +167,21 @@ export const useStore = create((set, get) => ({
setMenuButton: (menuButton) => {
set({ menuButton });
},
+ setBody: (body) => {
+ set({ body });
+ },
+ setLeftWheel: (leftWheel) => {
+ set({ leftWheel });
+ },
+ setRightWheel: (rightWheel) => {
+ set({ rightWheel });
+ },
+ setIsDrifting: (isDrifting) => {
+ set({ isDrifting });
+ },
+ getIsDrifting: () => {
+ return get().isDrifting;
+ },
},
}));