Author SHA1 Message Date
Alex faad40aa9d sanitized the project, deleted unused assets and added a real yet simple file system 2024-01-26 04:58:47 +01:00
Lunakepio bfccc00f4d Merge pull request #1 from Lunakepio/instancedMeshParticles
Instanced mesh particles
2024-01-26 04:40:06 +01:00
Alex 54810a73cd fix(game): fixed state management causing a rerender stuttered trigger when boosting with flame Particles 2024-01-25 12:14:23 +01:00
Alex fdd821e630 fix(game): fixed state management causing a rerender stuttered trigger when drifting 2024-01-25 11:49:42 +01:00
Alex 2d9230b8ea fix(game): implemented the InstancedMesh principle on the particle system for drifting 2024-01-25 11:02:20 +01:00
Alex b1b93043f8 bug(game): tried to add skid according to 0xc0a 's racing game 2024-01-25 10:04:19 +01:00
Alex 73343a8739 fix:(game) just fixed a small issue causing gained boost to stop if the player is drifting 2024-01-25 04:19:06 +01:00
Alex be364fca25 fix:(game) GAME IS FIXED, CAN CONTINUE DEV SAFELY 2024-01-24 15:51:51 +01:00
Alex 83d7e6c16b fix:(game) Fixed small issue with pointParticle causing the particle to go negative 2024-01-24 14:55:30 +01:00
Anderson Mancini 934c26491c Added small physics improvments 2024-01-24 09:44:28 -03:00
Anderson Mancini 6232bf9498 Fixed FakeGlowMaterial
+Added Flames Material :)
2024-01-24 09:40:02 -03:00
Alex 2753ec7127 fix:(game) Fixed constant refresh rate behavior 2024-01-24 11:15:25 +01:00
Alex a819fcae4c fix:(game) Fixed constant refresh rate behavior 2024-01-24 11:04:23 +01:00
Alex f5ebee224c fix:(game) Fixed constant refresh rate behavior 2024-01-24 11:02:05 +01:00
Alex 7daaf262aa feat:(game) set a real starting pose 2024-01-23 15:02:38 +01:00
Alex 16b2bbb93a feat:(game) added flame particles for boosting 2024-01-23 12:56:30 +01:00
Alex 6d4032d9c7 feat:(game) improved particle system for drifting again 2024-01-23 11:49:50 +01:00
Alex e1c11b3d74 feat:(game) improved particle system for drifting 2024-01-23 10:44:10 +01:00
Alex cb8052e1d3 feat:(game) fixed drifting mechanics and improved postprocessing effects 2024-01-22 19:46:07 +01:00
Alex 602536bc23 feat(game) : added ui base for steering 2024-01-22 18:39:20 +01:00
63 changed files with 1476 additions and 990 deletions

No files matched your search

+2 -2
View File
@@ -2,9 +2,9 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<link rel="icon" type="image/svg+xml" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React</title>
<title>Mario Kart 3.js</title>
</head>
<body>
<div id="root"></div>
+49 -49
View File
@@ -8,15 +8,16 @@
"name": "vite-starter",
"version": "0.0.0",
"dependencies": {
"@react-three/drei": "^9.93.0",
"@react-three/fiber": "^8.15.13",
"@react-three/drei": "^9.96.4",
"@react-three/fiber": "^8.15.15",
"@react-three/postprocessing": "^2.15.11",
"@react-three/rapier": "^1.2.1",
"gsap": "^3.12.4",
"gsap": "^3.12.5",
"leva": "^0.9.35",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"three": "^0.160.0",
"react-gamepad": "^1.0.3",
"three": "^0.160.1",
"zustand": "^4.5.0"
},
"devDependencies": {
@@ -932,9 +933,9 @@
"integrity": "sha512-POu8Mk0hIU3lRXB3bGIGe4VHIwwDsQyoD1F394OK7STTiX9w4dG3cTLljjYswkQN+hDSHRrj4O36kuVa7KPU8Q=="
},
"node_modules/@react-three/drei": {
"version": "9.93.0",
"resolved": "https://registry.npmjs.org/@react-three/drei/-/drei-9.93.0.tgz",
"integrity": "sha512-G59IZqPzpIZPvVLmzdCITXJQB+mnKMtFv7FvSRFogeelLzOFkyfnkED9QiY0WQCBMFOFLnSx6vb5xzmbQjHyQA==",
"version": "9.96.4",
"resolved": "https://registry.npmjs.org/@react-three/drei/-/drei-9.96.4.tgz",
"integrity": "sha512-Zmy5felOamD7DkD5EeLfijNkohDxHNtXomGAf3C/0G6ml/ocf1+VrJ6mLDQRE+DhRnF1RDHV+WC6nuvpPPkx1w==",
"dependencies": {
"@babel/runtime": "^7.11.2",
"@mediapipe/tasks-vision": "0.10.8",
@@ -944,9 +945,6 @@
"cross-env": "^7.0.3",
"detect-gpu": "^5.0.28",
"glsl-noise": "^0.0.0",
"lodash.clamp": "^4.0.3",
"lodash.omit": "^4.5.0",
"lodash.pick": "^4.4.0",
"maath": "^0.10.7",
"meshline": "^3.1.6",
"react-composer": "^5.0.3",
@@ -954,12 +952,13 @@
"stats-gl": "^2.0.0",
"stats.js": "^0.17.0",
"suspend-react": "^0.1.3",
"three-mesh-bvh": "^0.6.7",
"three-stdlib": "^2.28.0",
"three-mesh-bvh": "^0.7.0",
"three-stdlib": "^2.29.4",
"troika-three-text": "^0.47.2",
"tunnel-rat": "^0.1.2",
"utility-types": "^3.10.0",
"uuid": "^9.0.1",
"zustand": "^3.5.13"
"zustand": "^3.7.1"
},
"peerDependencies": {
"@react-three/fiber": ">=8.0",
@@ -990,9 +989,9 @@
}
},
"node_modules/@react-three/fiber": {
"version": "8.15.13",
"resolved": "https://registry.npmjs.org/@react-three/fiber/-/fiber-8.15.13.tgz",
"integrity": "sha512-FS6F/k69q2KEf7nxdce1Rzd5qyp6VHtTgjouTMfiotWNiNwlhfQQeAxfcnDg0i2XVaOUGkLaD9BK8LBVnpfzUA==",
"version": "8.15.15",
"resolved": "https://registry.npmjs.org/@react-three/fiber/-/fiber-8.15.15.tgz",
"integrity": "sha512-Z5POnzgpYxrgnYuiCv+8t7lpynEcGcn0/323kV1NtE7Cwq16aMqEuC6nF2Y/tK+crJpKNEqsRtvng/eJy0xxOA==",
"dependencies": {
"@babel/runtime": "^7.17.8",
"@types/react-reconciler": "^0.26.7",
@@ -1981,9 +1980,9 @@
}
},
"node_modules/gsap": {
"version": "3.12.4",
"resolved": "https://registry.npmjs.org/gsap/-/gsap-3.12.4.tgz",
"integrity": "sha512-1ByAq8dD0W4aBZ/JArgaQvc0gyUfkGkP8mgAQa0qZGdpOKlSOhOf+WNXjoLimKaKG3Z4Iu6DKZtnyszqQeyqWQ=="
"version": "3.12.5",
"resolved": "https://registry.npmjs.org/gsap/-/gsap-3.12.5.tgz",
"integrity": "sha512-srBfnk4n+Oe/ZnMIOXt3gT605BX9x5+rh/prT2F1SsNJsU1XuMiP0E2aptW481OnonOGACZWBqseH5Z7csHxhQ=="
},
"node_modules/has-property-descriptors": {
"version": "1.0.1",
@@ -2194,21 +2193,6 @@
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
"node_modules/lodash.clamp": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/lodash.clamp/-/lodash.clamp-4.0.3.tgz",
"integrity": "sha512-HvzRFWjtcguTW7yd8NJBshuNaCa8aqNFtnswdT7f/cMd/1YKy5Zzoq4W/Oxvnx9l7aeY258uSdDfM793+eLsVg=="
},
"node_modules/lodash.omit": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz",
"integrity": "sha512-XeqSp49hNGmlkj2EJlfrQFIzQ6lXdNro9sddtQzcJY8QaoC2GO0DT7xaIokHeyM+mIT0mPMlPvkYzg2xCuHdZg=="
},
"node_modules/lodash.pick": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz",
"integrity": "sha512-hXt6Ul/5yWjfklSGvLQl8vM//l3FtyHZeuelpzK6mm99pNvN9yTDruNZPEJZD1oWrqo+izBmB7oUfWgcCX7s4Q=="
},
"node_modules/loose-envify": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
@@ -2599,6 +2583,14 @@
"react": ">= 16.8"
}
},
"node_modules/react-gamepad": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/react-gamepad/-/react-gamepad-1.0.3.tgz",
"integrity": "sha512-gMwITmfoHtCaMFpDaEshcjeibHAgynXD28NnS2pa+dG+stwNoN66YDVizN7GfyIrYiW5Ft1ubRxs6/2xW9sRhQ==",
"peerDependencies": {
"react": ">=15.0.0"
}
},
"node_modules/react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
@@ -2893,22 +2885,22 @@
}
},
"node_modules/three": {
"version": "0.160.0",
"resolved": "https://registry.npmjs.org/three/-/three-0.160.0.tgz",
"integrity": "sha512-DLU8lc0zNIPkM7rH5/e1Ks1Z8tWCGRq6g8mPowdDJpw1CFBJMU7UoJjC6PefXW7z//SSl0b2+GCw14LB+uDhng=="
"version": "0.160.1",
"resolved": "https://registry.npmjs.org/three/-/three-0.160.1.tgz",
"integrity": "sha512-Bgl2wPJypDOZ1stAxwfWAcJ0WQf7QzlptsxkjYiURPz+n5k4RBDLsq+6f9Y75TYxn6aHLcWz+JNmwTOXWrQTBQ=="
},
"node_modules/three-mesh-bvh": {
"version": "0.6.8",
"resolved": "https://registry.npmjs.org/three-mesh-bvh/-/three-mesh-bvh-0.6.8.tgz",
"integrity": "sha512-EGebF9DZx1S8+7OZYNNTT80GXJZVf+UYXD/HyTg/e2kR/ApofIFfUS4ZzIHNnUVIadpnLSzM4n96wX+l7GMbnQ==",
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/three-mesh-bvh/-/three-mesh-bvh-0.7.0.tgz",
"integrity": "sha512-Hj0Z1Rp02yy5H+/xtMBu/dYAeRsSONaBaVLZoST9sMpZxycHypRiUeMHucPOLWFHnpc5hwelOnONcLpkfhDg0Q==",
"peerDependencies": {
"three": ">= 0.151.0"
}
},
"node_modules/three-stdlib": {
"version": "2.28.12",
"resolved": "https://registry.npmjs.org/three-stdlib/-/three-stdlib-2.28.12.tgz",
"integrity": "sha512-6ZAomFjrtDVNxI56F3QNgV7uVn8JlEZVgzZP+UE9h/zpKmeD3pIZvmWymw9sYPoteof0hLDFom3cETRhErQh3g==",
"version": "2.29.4",
"resolved": "https://registry.npmjs.org/three-stdlib/-/three-stdlib-2.29.4.tgz",
"integrity": "sha512-XNzGCrz/uAk9XoLwd35eN7dQyI4ggXZTeqjcN034YdYBpBlNO9kmLHehl/0Nw9jCelblB7jla+unHAOIyLyV6Q==",
"dependencies": {
"@types/draco3d": "^1.4.0",
"@types/offscreencanvas": "^2019.6.4",
@@ -2966,6 +2958,14 @@
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
"integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
},
"node_modules/tunnel-rat": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/tunnel-rat/-/tunnel-rat-0.1.2.tgz",
"integrity": "sha512-lR5VHmkPhzdhrM092lI2nACsLO4QubF0/yoOhzX7c+wIpbN1GjHNzCc91QlpxBi+cnx8vVJ+Ur6vL5cEoQPFpQ==",
"dependencies": {
"zustand": "^4.3.2"
}
},
"node_modules/type-is": {
"version": "1.6.18",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
@@ -3006,9 +3006,9 @@
}
},
"node_modules/utility-types": {
"version": "3.10.0",
"resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.10.0.tgz",
"integrity": "sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg==",
"version": "3.11.0",
"resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.11.0.tgz",
"integrity": "sha512-6Z7Ma2aVEWisaL6TvBCy7P8rm2LQoPv6dJ7ecIaIixHcwfbJ0x7mWdbcwlIM5IGQxPZSFYeqRCqlOOeKoJYMkw==",
"engines": {
"node": ">= 4"
}
@@ -3047,9 +3047,9 @@
}
},
"node_modules/vite": {
"version": "4.5.1",
"resolved": "https://registry.npmjs.org/vite/-/vite-4.5.1.tgz",
"integrity": "sha512-AXXFaAJ8yebyqzoNB9fu2pHoo/nWX+xZlaRwoeYUxEqBO+Zj4msE5G+BhGBll9lYEKv9Hfks52PAF2X7qDYXQA==",
"version": "4.5.2",
"resolved": "https://registry.npmjs.org/vite/-/vite-4.5.2.tgz",
"integrity": "sha512-tBCZBNSBbHQkaGyhGCDUGqeo2ph8Fstyp6FMSvTtsXeZSPpSMGlviAOav2hxVTqFcx8Hj/twtWKsMJXNY0xI8w==",
"dev": true,
"dependencies": {
"esbuild": "^0.18.10",
+5 -4
View File
@@ -9,15 +9,16 @@
"preview": "vite preview"
},
"dependencies": {
"@react-three/drei": "^9.93.0",
"@react-three/fiber": "^8.15.13",
"@react-three/drei": "^9.96.4",
"@react-three/fiber": "^8.15.15",
"@react-three/postprocessing": "^2.15.11",
"@react-three/rapier": "^1.2.1",
"gsap": "^3.12.4",
"gsap": "^3.12.5",
"leva": "^0.9.35",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"three": "^0.160.0",
"react-gamepad": "^1.0.3",
"three": "^0.160.1",
"zustand": "^4.5.0"
},
"devDependencies": {
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

File renamed without changes.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

+2 -2
View File
@@ -38,12 +38,12 @@ function App() {
<Suspense fallback={null}>
<Physics
gravity={[0, -90, 0]}
predictionDistance={0.001}
timeStep={'vary'}
>
<KeyboardControls map={map}>
<Experience />
</KeyboardControls>
{/* <Stats /> */}
<Stats />
</Physics>
</Suspense>
</Canvas>
+46
View File
@@ -0,0 +1,46 @@
import React, { useEffect, useRef } from "react";
export const HUD = () => {
const wheel = useRef();
useEffect(() => {
const handleMouseMove = (e) => {
if (wheel.current) {
const { clientX, clientY } = e;
const screenWidth = window.innerWidth;
const rotation = ((clientX - screenWidth / 2) / screenWidth) * 180;
wheel.current.style.left = `${clientX - 100}px`;
wheel.current.style.top = `${clientY - 100}px`;
wheel.current.style.transform = `rotate(${rotation}deg)`;
}
};
window.addEventListener("mousemove", handleMouseMove);
return () => {
window.removeEventListener("mousemove", handleMouseMove);
};
}, []);
return (
<div className="overlay"> dadasd
<div className="logo">
<img src="./logo.png" alt="logo" />
</div>
<div className="wheel">
<img
ref={wheel}
src="./steering_wheel.png"
alt="steering wheel"
className="steering-wheel"
style={{
position: "absolute",
pointerEvents: "none",
transformOrigin: "center",
}}
/>
</div>
</div>
);
};
-28
View File
@@ -1,28 +0,0 @@
import { Particles2 } from "./Particles2";
import { Particles4 } from "./Particles4";
export const DriftParticlesRight = ({turboColor,scale, ...props}) => {
if(scale < 0.5) {
return null;
}
return (
<group {...props}>
<Particles2 turboColor={turboColor} scale={scale} />
<Particles2 turboColor={turboColor} scale={scale} />
<Particles2 turboColor={turboColor} scale={scale} />
<Particles2 turboColor={turboColor} scale={scale} />
<Particles2 turboColor={turboColor} scale={scale} />
<Particles2 turboColor={turboColor} scale={scale} />
<Particles2 turboColor={turboColor} scale={scale} />
<Particles2 turboColor={turboColor} scale={scale} />
<Particles2 turboColor={turboColor} scale={scale} />
<Particles4 turboColor={turboColor} scale={scale} />
<Particles4 turboColor={turboColor} scale={scale} />
<Particles4 turboColor={turboColor} scale={scale} />
</group>
)
}
+13 -15
View File
@@ -1,19 +1,20 @@
import { Environment, OrbitControls, PerspectiveCamera, Lightformer } from '@react-three/drei'
import { Ground } from './Ground'
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, SMAA } from '@react-three/postprocessing'
import { Paris } from './models/tracks/Tour_paris_promenade'
import { EffectComposer, N8AO, Bloom, TiltShift2, HueSaturation, SMAA, ChromaticAberration, Vignette } from '@react-three/postprocessing'
import { Skid } from './Skid'
export const Experience = () => {
return (
<>
<PlayerController />
{/* <Skid /> */}
<Ground position={[0, 0, 0]} />
<Environment
resolution={256}
preset='lobby'
/>
<directionalLight
@@ -28,30 +29,27 @@ export const Experience = () => {
castShadow
/>
{/* <ambientLight intensity={0.2} /> */}
{/* <spotLight position={[10, 20, 10]} angle={0.12} penumbra={1} intensity={1} castShadow shadow-mapSize={1024} /> */}
<Paris position={[0, 0, 0]} />
<EffectComposer
multisampling={0}
disableNormalPass
disableSSAO
disableDepthPass
>
<SMAA />
{/* <N8AO distanceFalloff={1} aoRadius={1} intensity={4} /> */}
<N8AO distanceFalloff={1} aoRadius={1} intensity={3} />
<Bloom
luminanceThreshold={0}
mipmapBlur
luminanceSmoothing={0.01}
intensity={0.5}
/>
<DepthOfField
target={[0, 0, 13]}
focalLength={0.3}
bokehScale={20}
// height={700}
resolutionScale={0.3}
/>
{/* <TiltShift2/> */}
<TiltShift2/>
<ChromaticAberration offset={[0.0006, 0.0006]} />
<HueSaturation saturation={0.1} />
<Vignette eskil={false} offset={0.1} darkness={0.4} />
</EffectComposer>
</>
)
@@ -1,82 +0,0 @@
/**
* FakeGlow material component by Anderson Mancini - Dec 2024.
*/
import React, { useRef, useMemo } from 'react'
import { shaderMaterial } from '@react-three/drei'
import { extend, useFrame } from '@react-three/fiber'
import { Color, BackSide, AdditiveBlending } from 'three'
export default function FakeGlowMaterial({ glowCenter = 0.05, edgeIntensity = 6.0, glowColor = '#00ff00', glowOpacity = 1.0, fresnelOpacity = 0.5, fresnelAmount = 0.5, wireframe = false }) {
const FakeGlowMaterial = useMemo(() => {
return shaderMaterial(
{
time: 0,
glowCenter: glowCenter,
edgeIntensity: edgeIntensity,
glowColor: new Color(glowColor),
glowOpacity: glowOpacity,
fresnelOpacity: fresnelOpacity,
fresnelAmount: fresnelAmount
},
/*GLSL */
`
uniform float glowCenter;
uniform float edgeIntensity;
varying float intensity;
varying vec3 vNormel;
varying vec3 vNormal;
uniform float fresnelOpacity;
uniform float fresnelAmount;
void main() {
vec3 viewVector = normalize(vec3(cameraPosition-position));
float fresnelEffect = dot(vNormel, vNormal) * ( fresnelOpacity);
fresnelEffect = clamp(fresnelAmount - fresnelEffect, 0.5, fresnelOpacity);
vec3 vNormal = normalize( normalMatrix * normal );
vec3 vNormel = normalize( normalMatrix * viewVector );
intensity = pow( glowCenter - dot(vNormal, vNormel), edgeIntensity / fresnelEffect );
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}`,
/*GLSL */
`
uniform vec3 glowColor;
varying float intensity;
uniform float glowOpacity;
uniform float fresnelOpacity;
uniform float fresnelAmount;
varying vec3 vNormel;
varying vec3 vNormal;
uniform float glowCenter;
uniform float edgeIntensity;
void main()
{
vec3 glow = glowColor * intensity;
float fresnelEffect = - dot(vNormel, vNormal);
fresnelEffect = clamp(fresnelEffect, 0.1, 1.0);
gl_FragColor = vec4( clamp(glow, 0., 1.0), clamp(glowOpacity - intensity * fresnelEffect, 0., 1.0 ));
}`
)
}, [glowCenter, edgeIntensity, glowColor, glowOpacity, fresnelOpacity, fresnelAmount])
extend({ FakeGlowMaterial })
useFrame((state, delta) => {
ref.current.time += delta
})
const ref = useRef()
return (
<fakeGlowMaterial
wireframe={wireframe}
key={FakeGlowMaterial.key}
side={BackSide}
transparent={true}
blending={AdditiveBlending}
depthTest={false}
ref={ref}
/>
)
}
+17 -6
View File
@@ -1,12 +1,23 @@
import { RigidBody } from "@react-three/rapier";
import { RigidBody } from '@react-three/rapier'
export const Ground = (props) => {
return (
<RigidBody type="fixed" {...props}>
<mesh transparent receiveShadow rotation={[-Math.PI/2 , 0 ,0]}>
<RigidBody
type='fixed'
{...props}
>
<mesh
transparent
receiveShadow
rotation={[-Math.PI / 2, 0, 0]}
>
<planeGeometry args={[1000, 1000, 1000]} />
<meshStandardMaterial color="yellow" opacity={0} transparent/>
<meshStandardMaterial
color='yellow'
opacity={0}
transparent
/>
</mesh>
</RigidBody>
);
};
)
}
@@ -3,25 +3,23 @@ import { Particles3 } from "./Particles3";
export const DriftParticlesLeft = ({turboColor,scale, ...props}) => {
if(scale < 0.5) {
return null;
}
// if(scale < 0.8) {
// return null;
// }
return (
<group {...props}>
<Particles1 turboColor={turboColor} scale={scale} />
{/* <Particles1 turboColor={turboColor} scale={scale} />
<Particles1 turboColor={turboColor} scale={scale} />
<Particles1 turboColor={turboColor} scale={scale} />
<Particles1 turboColor={turboColor} scale={scale} />
<Particles1 turboColor={turboColor} scale={scale} />
<Particles1 turboColor={turboColor} scale={scale} />
<Particles1 turboColor={turboColor} scale={scale} />
<Particles1 turboColor={turboColor} scale={scale} />
<Particles1 turboColor={turboColor} scale={scale} />
<Particles1 turboColor={turboColor} scale={scale} /> */}
<Particles3 turboColor={turboColor} scale={scale} />
<Particles3 turboColor={turboColor} scale={scale} />
<Particles3 turboColor={turboColor} scale={scale} />
{/* <Particles3 turboColor={turboColor} scale={scale} /> */}
</group>
)
@@ -0,0 +1,16 @@
import { Particles2 } from "./Particles2";
import { Particles4 } from "./Particles4";
export const DriftParticlesRight = ({turboColor,scale, ...props}) => {
// if(scale < 0.8) {
// return null;
// }
return (
<group {...props}>
<Particles2 turboColor={turboColor} scale={scale} />
</group>
)
}
@@ -0,0 +1,67 @@
import React, { useRef, useMemo } from "react";
import { useLoader, useFrame } from "@react-three/fiber";
import * as THREE from "three";
export const FlameParticle = ({ position, png, isBoosting, delay = 0 }) => {
const texture = useLoader(THREE.TextureLoader, png);
const pointsRef = useRef();
const initialized = useRef(false);
// Initialize after delay
useMemo(() => {
const timer = setTimeout(() => {
initialized.current = true;
}, delay);
return () => clearTimeout(timer);
}, [delay]);
const points = useMemo(() => {
const geom = new THREE.BufferGeometry();
geom.setAttribute(
"position",
new THREE.Float32BufferAttribute(position, 3)
);
return geom;
}, [position]);
useFrame(({clock}, delta) => {
if (!initialized.current) return;
const pointsCurrent = pointsRef.current;
if (isBoosting) {
// Update logic when boosting
pointsCurrent.position.y += 0.03 * delta * 144;
pointsCurrent.position.z += 0.06 * delta * 144;
if(pointsCurrent.position.y > 0.4) {
pointsCurrent.position.y = 0;
pointsCurrent.position.z = 0;
pointsCurrent.material.opacity = 1;
}
if(pointsCurrent.material.opacity > 0) {
pointsCurrent.material.opacity -= 0.05 * delta * 144;
}
} else {
// Reset position and opacity when not boosting
pointsCurrent.position.y = 0;
pointsCurrent.position.z = 0;
pointsCurrent.material.opacity = 0;
}
});
return (
<points ref={pointsRef} geometry={points}>
<pointsMaterial
size={1}
alphaMap={texture}
transparent={true}
depthWrite={false}
color={0x000000}
opacity={1}
toneMapped={false}
/>
</points>
);
};
+166
View File
@@ -0,0 +1,166 @@
import { FlameParticle } from "./FlameParticle";
export const FlameParticles = ({ isBoosting }) => {
return (
<group>
{/* bottom left */}
<group position={[-0.26, 0.45, 1]}>
<FlameParticle
position={[0, 0, 0]}
png="./fire_01.png"
isBoosting={isBoosting}
delay={0}
/>
<FlameParticle
position={[0, 0, 0]}
png="./fire_02.png"
isBoosting={isBoosting}
delay={100}
/>
<FlameParticle
position={[0, 0, 0]}
png="./fire_01.png"
isBoosting={isBoosting}
delay={200}
/>
<FlameParticle
position={[0, 0, 0]}
png="./fire_02.png"
isBoosting={isBoosting}
delay={300}
/>
<FlameParticle
position={[0, 0, 0]}
png="./fire_02.png"
isBoosting={isBoosting}
delay={400}
/>
<FlameParticle
position={[0, 0, 0]}
png="./fire_01.png"
isBoosting={isBoosting}
delay={500}
/>
</group>
{/* bottom right */}
<group position={[0.26, 0.45, 1]}>
<FlameParticle
position={[0, 0, 0]}
png="./fire_01.png"
isBoosting={isBoosting}
delay={0}
/>
<FlameParticle
position={[0, 0, 0]}
png="./fire_02.png"
isBoosting={isBoosting}
delay={100}
/>
<FlameParticle
position={[0, 0, 0]}
png="./fire_01.png"
isBoosting={isBoosting}
delay={200}
/>
<FlameParticle
position={[0, 0, 0]}
png="./fire_02.png"
isBoosting={isBoosting}
delay={300}
/>
<FlameParticle
position={[0, 0, 0]}
png="./fire_01.png"
isBoosting={isBoosting}
delay={400}
/>
<FlameParticle
position={[0, 0, 0]}
png="./fire_02.png"
isBoosting={isBoosting}
delay={500}
/>
</group>
{/* top left */}
<group position={[-0.18, 0.6, 0.8]}>
<FlameParticle
position={[0, 0, 0]}
png="./fire_02.png"
isBoosting={isBoosting}
delay={0}
/>
<FlameParticle
position={[0, 0, 0]}
png="./fire_01.png"
isBoosting={isBoosting}
delay={100}
/>
<FlameParticle
position={[0, 0, 0]}
png="./fire_02.png"
isBoosting={isBoosting}
delay={200}
/>
<FlameParticle
position={[0, 0, 0]}
png="./fire_01.png"
isBoosting={isBoosting}
delay={300}
/>
<FlameParticle
position={[0, 0, 0]}
png="./fire_02.png"
isBoosting={isBoosting}
delay={400}
/>
<FlameParticle
position={[0, 0, 0]}
png="./fire_01.png"
isBoosting={isBoosting}
delay={500}
/>
</group>
<group position={[0.18, 0.6, 0.8]}>
<FlameParticle
position={[0, 0, 0]}
png="./fire_02.png"
isBoosting={isBoosting}
delay={0}
/>
<FlameParticle
position={[0, 0, 0]}
png="./fire_01.png"
isBoosting={isBoosting}
delay={100}
/>
<FlameParticle
position={[0, 0, 0]}
png="./fire_02.png"
isBoosting={isBoosting}
delay={200}
/>
<FlameParticle
position={[0, 0, 0]}
png="./fire_01.png"
isBoosting={isBoosting}
delay={300}
/>
<FlameParticle
position={[0, 0, 0]}
png="./fire_02.png"
isBoosting={isBoosting}
delay={400}
/>
<FlameParticle
position={[0, 0, 0]}
png="./fire_01.png"
isBoosting={isBoosting}
delay={500}
/>
</group>
</group>
);
};
+57
View File
@@ -0,0 +1,57 @@
import { useRef, useMemo } from "react";
import { useFrame } from "@react-three/fiber";
import * as THREE from 'three';
export const Particles1 = ({ turboColor, scale, numParticles = 50, ...props }) => {
const instancedMeshRef = useRef();
const particlesData = useMemo(() => {
return new Array(numParticles).fill().map(() => ({
position: new THREE.Vector3(-0.6, 0.05, 0.5),
velocity: new THREE.Vector3(-Math.random() * 0.05, Math.random() * 0.05, Math.random() * 0.02),
gravity: -0.003
}));
}, [numParticles]);
useFrame((state, delta) => {
if (!instancedMeshRef.current) {
return;
}
// Manage visibility directly in the animation loop
instancedMeshRef.current.visible = scale >= 0.8;
if (scale < 0.8) {
return;
}
const deltaScaled = delta * 144; // Scale for 144 FPS
particlesData.forEach((particle, i) => {
particle.velocity.y += particle.gravity * deltaScaled;
particle.position.x += particle.velocity.x * deltaScaled;
particle.position.y += particle.velocity.y * deltaScaled;
particle.position.z += particle.velocity.z * deltaScaled;
if (particle.position.y < 0.05) {
particle.position.set(-0.6, 0.05, 0.5);
particle.velocity.set(-Math.random() * 0.05, Math.random() * 0.05, Math.random() * 0.02);
}
const matrix = new THREE.Matrix4();
matrix.setPosition(particle.position);
instancedMeshRef.current.setMatrixAt(i, matrix);
});
instancedMeshRef.current.instanceMatrix.needsUpdate = true;
});
return (
<instancedMesh ref={instancedMeshRef} args={[null, null, numParticles]} visible={scale >= 0.8}>
<sphereGeometry args={[0.01, 16, 16]} />
<meshStandardMaterial
emissive={turboColor}
toneMapped={false}
emissiveIntensity={5}
/>
</instancedMesh>
);
};
+57
View File
@@ -0,0 +1,57 @@
import { useRef, useMemo } from "react";
import { useFrame } from "@react-three/fiber";
import * as THREE from 'three';
export const Particles2 = ({ turboColor, scale, numParticles = 50, ...props }) => {
const instancedMeshRef = useRef();
const particlesData = useMemo(() => {
return new Array(numParticles).fill().map(() => ({
position: new THREE.Vector3(0.6, 0.05, 0.5),
velocity: new THREE.Vector3(Math.random() * 0.05, Math.random() * 0.05, Math.random() * 0.02),
gravity: -0.003
}));
}, [numParticles]);
useFrame((state, delta) => {
if (!instancedMeshRef.current) {
return;
}
// Manage visibility directly in the animation loop
instancedMeshRef.current.visible = scale >= 0.8;
if (scale < 0.8) {
return;
}
const deltaScaled = delta * 144; // Scale for 144 FPS
particlesData.forEach((particle, i) => {
particle.velocity.y += particle.gravity * deltaScaled;
particle.position.x += particle.velocity.x * deltaScaled;
particle.position.y += particle.velocity.y * deltaScaled;
particle.position.z += particle.velocity.z * deltaScaled;
if (particle.position.y < 0.05) {
particle.position.set(0.6, 0.05, 0.5);
particle.velocity.set(Math.random() * 0.05, Math.random() * 0.05, Math.random() * 0.02);
}
const matrix = new THREE.Matrix4();
matrix.setPosition(particle.position);
instancedMeshRef.current.setMatrixAt(i, matrix);
});
instancedMeshRef.current.instanceMatrix.needsUpdate = true;
});
return (
<instancedMesh ref={instancedMeshRef} args={[null, null, numParticles]} visible={scale >= 0.8}>
<sphereGeometry args={[0.01, 16, 16]} />
<meshStandardMaterial
emissive={turboColor}
toneMapped={false}
emissiveIntensity={5}
/>
</instancedMesh>
);
};
+55
View File
@@ -0,0 +1,55 @@
import { useRef } from "react";
import { useFrame } from "@react-three/fiber";
import * as THREE from 'three';
export const Particles3 = ({ turboColor, scale, ...props }) => {
const ref = useRef();
const velocity = useRef({
x: -Math.random() * 0.05,
y: Math.random() * 0.05,
z: Math.random() * 0.02,
});
const gravity = -0.001;
useFrame((state, delta) => {
let position = ref.current.position;
let velocityVector = new THREE.Vector3(velocity.current.x, velocity.current.y, velocity.current.z);
// Adjust gravity and velocity based on delta
velocity.current.y += gravity * delta * 144; // Multiply by 144 to scale for 144 FPS
// Scale velocity changes by delta
position.x += velocity.current.x * delta * 144;
position.y += velocity.current.y * delta * 144;
position.z += velocity.current.z * delta * 144;
if (!velocityVector.equals(new THREE.Vector3(0, 0, 0))) {
const alignmentQuaternion = new THREE.Quaternion();
alignmentQuaternion.setFromUnitVectors(new THREE.Vector3(0, 1, 0), velocityVector.normalize());
ref.current.quaternion.slerp(alignmentQuaternion, 0.1);
}
if (position.y < 0.05) {
position.set(-0.6, 0.05, 0.5);
velocity.current = {
x: -Math.random() * 0.05,
y: Math.random() * 0.05,
z: Math.random() * 0.02,
};
}
ref.current.position.set(position.x, position.y, position.z);
});
return (
<mesh ref={ref} position={[-0.6, 0.05, 0.5]} scale={[scale, scale * 20, scale]}>
<sphereGeometry args={[0.01, 16, 16]} />
<meshStandardMaterial
emissive={turboColor}
toneMapped={false}
emissiveIntensity={5}
/>
</mesh>
);
};
+55
View File
@@ -0,0 +1,55 @@
import { useRef } from "react";
import { useFrame } from "@react-three/fiber";
import * as THREE from 'three';
export const Particles4 = ({ turboColor, scale, ...props }) => {
const ref = useRef();
const velocity = useRef({
x: Math.random() * 0.05,
y: Math.random() * 0.05,
z: Math.random() * 0.02,
});
const gravity = -0.001;
useFrame((state, delta) => {
let position = ref.current.position;
let velocityVector = new THREE.Vector3(velocity.current.x, velocity.current.y, velocity.current.z);
// Adjust gravity and velocity based on delta
velocity.current.y += gravity * delta * 144; // Multiply by 144 to scale for 144 FPS
// Scale velocity changes by delta
position.x += velocity.current.x * delta * 144;
position.y += velocity.current.y * delta * 144;
position.z += velocity.current.z * delta * 144;
if (!velocityVector.equals(new THREE.Vector3(0, 0, 0))) {
const alignmentQuaternion = new THREE.Quaternion();
alignmentQuaternion.setFromUnitVectors(new THREE.Vector3(0, 1, 0), velocityVector.normalize());
ref.current.quaternion.slerp(alignmentQuaternion, 0.1);
}
if (position.y < 0.05) {
position.set(0.6, 0.05, 0.5);
velocity.current = {
x: Math.random() * 0.05,
y: Math.random() * 0.05,
z: Math.random() * 0.02,
};
}
ref.current.position.set(position.x, position.y, position.z);
});
return (
<mesh ref={ref} position={[0.6, 0.05, 0.5]} scale={[scale, scale * 20, scale]}>
<sphereGeometry args={[0.01, 16, 16]} />
<meshStandardMaterial
emissive={turboColor}
toneMapped={false}
emissiveIntensity={5}
/>
</mesh>
);
};
@@ -0,0 +1,49 @@
import React, { useState, useEffect, useRef } from "react";
import { Canvas, useLoader, useFrame } from "@react-three/fiber";
import * as THREE from "three";
export const PointParticle = ({ position, png, turboColor }) => {
const texture = useLoader(THREE.TextureLoader, png);
const pointsRef = useRef();
const [size, setSize] = useState(0);
const [opacity, setOpacity] = useState(1);
const points = React.useMemo(() => {
const geom = new THREE.BufferGeometry();
geom.setAttribute(
"position",
new THREE.Float32BufferAttribute(position, 3)
);
return geom;
}, [position]);
useEffect(() => {
setSize(0);
setOpacity(1);
}, [turboColor]);
useFrame((_, delta) => {
if (turboColor === 0xffffff) return;
if (size < 5) {
setSize((size) => Math.min(size + 0.3 * delta * 144, 5));
} else if (opacity > 0) {
setOpacity((opacity) => Math.max(opacity - 0.2 * delta * 144, 0));
setSize((size) => Math.max(size - 0.2 * delta * 144, 0));
}
});
return (
<points ref={pointsRef} geometry={points}>
<pointsMaterial
size={size}
alphaMap={texture}
transparent={true}
depthWrite={false}
color={turboColor}
opacity={opacity}
toneMapped={false}
/>
</points>
);
};
-47
View File
@@ -1,47 +0,0 @@
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 (
<mesh ref={ref} position={[-0.6, 0.05, 0.5]} scale={scale}>
<boxGeometry args={[0.05, 0.1, 0.05]} />
<meshStandardMaterial
emissive={turboColor}
toneMapped={false}
emissiveIntensity={10}
/>
</mesh>
);
};
-47
View File
@@ -1,47 +0,0 @@
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 (
<mesh ref={ref} position={[0.6, 0.05, 0.5]} scale={scale}>
<boxGeometry args={[0.05, 0.1, 0.05]} />
<meshStandardMaterial
emissive={turboColor}
toneMapped={false}
emissiveIntensity={10}
/>
</mesh>
);
};
-48
View File
@@ -1,48 +0,0 @@
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 (
<mesh ref={ref} position={[-0.6, 0.05, 0.5]} scale={scale}>
<boxGeometry args={[0.1, 0.2, 0.1]} />
<meshStandardMaterial
emissive={turboColor}
toneMapped={false}
emissiveIntensity={50}
/>
</mesh>
);
};
-48
View File
@@ -1,48 +0,0 @@
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 (
<mesh ref={ref} position={[0.6, 0.05, 0.5]} scale={scale}>
<boxGeometry args={[0.1, 0.1, 0.1]} />
<meshStandardMaterial
emissive={turboColor}
toneMapped={false}
emissiveIntensity={50}
/>
</mesh>
);
};
+286 -178
View File
@@ -1,254 +1,352 @@
import { Controls } from '../App'
import { RigidBody, useRapier } from '@react-three/rapier'
import { useKeyboardControls, PerspectiveCamera, ContactShadows, Sphere } from '@react-three/drei'
import { useFrame, useThree } from '@react-three/fiber'
import { useRef, useState, useEffect, useCallback } from 'react'
import * as THREE from 'three'
import { Model } from './models/Racing_kart'
import { FrontRightWheel } from './models/Front_Right_Wheel'
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'
import FakeGlowMaterial from './FakeGlow/FakeGlowMaterial'
import { Controls } from "../App";
import { BallCollider, RigidBody, useRapier, vec3 } from "@react-three/rapier";
import {
useKeyboardControls,
PerspectiveCamera,
ContactShadows,
Sphere,
OrbitControls,
Trail,
PositionalAudio,
} from "@react-three/drei";
import { useFrame, useThree } from "@react-three/fiber";
import { useRef, useState, useEffect, useCallback } from "react";
import * as THREE from "three";
import { Mario } from "./models/characters/Mario_kart";
import { DriftParticlesLeft } from "./Particles/DriftParticlesLeft";
import { DriftParticlesRight } from "./Particles/DriftParticlesRight";
import { PointParticle } from "./Particles/PointParticle";
import { FlameParticles } from "./Particles/FlameParticles";
import { useStore } from "./store";
import { Cylinder } from "@react-three/drei";
export const PlayerController = () => {
const upPressed = useKeyboardControls((state) => state[Controls.up])
const downPressed = useKeyboardControls((state) => state[Controls.down])
const leftPressed = useKeyboardControls((state) => state[Controls.left])
const rightPressed = useKeyboardControls((state) => state[Controls.right])
const jumpPressed = useKeyboardControls((state) => state[Controls.jump])
const [isOnGround, setIsOnGround] = useState(false)
const body = useRef()
const kart = useRef()
const cam = useRef()
const initialSpeed = 0
const maxSpeed = 30
const boostSpeed = 50
const acceleration = 0.1
const decceleration = 0.2
const damping = 0.001
const MaxSteeringSpeed = 0.01
const [currentSteeringSpeed, setCurrentSteeringSpeed] = useState(0)
const [currentSpeed, setCurrentSpeed] = useState(initialSpeed)
const camMaxOffset = 0.5
let steeringAngle = 0
const isOnFloor = useRef(false)
const jumpForce = useRef(0)
const jumpIsHeld = useRef(false)
const driftDirection = useRef(0)
const driftLeft = useRef(false)
const driftRight = useRef(false)
const driftForce = useRef(0)
const mario = useRef()
const accumulatedDriftPower = useRef(0)
const blueTurboThreshold = 10
const orangeTurboThreshold = 30
const purpleTurboThreshold = 60
const [turboColor, setTurboColor] = useState(0xffffff)
const boostDuration = useRef(0)
const isBoosting = useRef(false)
let targetXPosition = 0
let targetZPosition = 8
const [steeringAngleWheels, setSteeringAngleWheels] = useState(0)
const upPressed = useKeyboardControls((state) => state[Controls.up]);
const downPressed = useKeyboardControls((state) => state[Controls.down]);
const leftPressed = useKeyboardControls((state) => state[Controls.left]);
const rightPressed = useKeyboardControls((state) => state[Controls.right]);
const jumpPressed = useKeyboardControls((state) => state[Controls.jump]);
const [isOnGround, setIsOnGround] = useState(false);
const body = useRef();
const kart = useRef();
const cam = useRef();
const initialSpeed = 0;
const maxSpeed = 30;
const boostSpeed = 50;
const acceleration = 0.1;
const decceleration = 0.2;
const damping = -0.1;
const MaxSteeringSpeed = 0.01;
const [currentSteeringSpeed, setCurrentSteeringSpeed] = useState(0);
const [currentSpeed, setCurrentSpeed] = useState(initialSpeed);
const camMaxOffset = 1;
let steeringAngle = 0;
const isOnFloor = useRef(false);
const jumpForce = useRef(0);
const jumpIsHeld = useRef(false);
const driftDirection = useRef(0);
const driftLeft = useRef(false);
const driftRight = useRef(false);
const driftForce = useRef(0);
const mario = useRef();
const accumulatedDriftPower = useRef(0);
const blueTurboThreshold = 10;
const orangeTurboThreshold = 30;
const purpleTurboThreshold = 60;
const [turboColor, setTurboColor] = useState(0xffffff);
const boostDuration = useRef(0);
const [isBoosting, setIsBoosting] = useState(false);
let targetXPosition = 0;
let targetZPosition = 8;
const [steeringAngleWheels, setSteeringAngleWheels] = useState(0);
const engineSound = useRef();
const [scale, setScale] = useState(0)
const [scale, setScale] = useState(0);
const { actions, addPastPosition } = useStore();
useFrame(({ pointer, clock }) => {
const time = clock.getElapsedTime()
if (!body.current && !mario.current) return
useFrame(({ pointer, clock }, delta) => {
const time = clock.getElapsedTime();
if (!body.current && !mario.current) return;
// HANDLING AND STEERING
const kartRotation = kart.current.rotation.y - driftDirection.current * driftForce.current
const forwardDirection = new THREE.Vector3(-Math.sin(kartRotation), 0, -Math.cos(kartRotation))
const kartRotation =
kart.current.rotation.y - driftDirection.current * driftForce.current;
const forwardDirection = new THREE.Vector3(
-Math.sin(kartRotation),
0,
-Math.cos(kartRotation)
);
actions.setBodyPosition(body.current.translation());
actions.setBodyRotation(kart.current.rotation);
if (leftPressed && currentSpeed > 0) {
steeringAngle = currentSteeringSpeed
targetXPosition = -camMaxOffset
steeringAngle = currentSteeringSpeed;
targetXPosition = -camMaxOffset;
} else if (rightPressed && currentSpeed > 0) {
steeringAngle = -currentSteeringSpeed
targetXPosition = camMaxOffset
steeringAngle = -currentSteeringSpeed;
targetXPosition = camMaxOffset;
} else {
steeringAngle = 0
targetXPosition = 0
1
steeringAngle = 0;
targetXPosition = 0;
1;
}
// mouse steering
steeringAngle = currentSteeringSpeed * -pointer.x
targetXPosition = -camMaxOffset * -pointer.x
if (!driftLeft.current && !driftRight.current) {
steeringAngle = currentSteeringSpeed * -pointer.x;
targetXPosition = -camMaxOffset * -pointer.x;
} else if (driftLeft.current && !driftRight.current) {
steeringAngle = currentSteeringSpeed * -(pointer.x - 0.5);
targetXPosition = -camMaxOffset * -pointer.x;
} else if (driftRight.current && !driftLeft.current) {
steeringAngle = currentSteeringSpeed * -(pointer.x + 0.5);
targetXPosition = -camMaxOffset * -pointer.x;
}
// ACCELERATING
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) {
setCurrentSpeed(Math.max(currentSpeed - decceleration, maxSpeed))
setCurrentSpeed(
Math.min(currentSpeed + acceleration * delta * 144, maxSpeed)
);
} else if (
upPressed &&
currentSpeed > maxSpeed &&
boostDuration.current > 0
) {
setCurrentSpeed(
Math.max(currentSpeed - decceleration * delta * 144, maxSpeed)
);
}
if (upPressed) {
if (currentSteeringSpeed < MaxSteeringSpeed) {
setCurrentSteeringSpeed(Math.min(currentSteeringSpeed + 0.0001, MaxSteeringSpeed))
setCurrentSteeringSpeed(
Math.min(
currentSteeringSpeed + 0.0001 * delta * 144,
MaxSteeringSpeed
)
);
}
}
// REVERSING
if (downPressed && currentSpeed < -maxSpeed) {
setCurrentSpeed(Math.max(currentSpeed - acceleration, -maxSpeed))
setCurrentSpeed(
Math.max(currentSpeed - acceleration * delta * 144, -maxSpeed)
);
}
// DECELERATING
else if (!upPressed && !downPressed) {
if (currentSteeringSpeed > 0) {
setCurrentSteeringSpeed(Math.max(currentSteeringSpeed - 0.00005, 0))
setCurrentSteeringSpeed(
Math.max(currentSteeringSpeed - 0.00005 * delta * 144, 0)
);
} else if (currentSteeringSpeed < 0) {
setCurrentSteeringSpeed(Math.min(currentSteeringSpeed + 0.00005, 0))
setCurrentSteeringSpeed(
Math.min(currentSteeringSpeed + 0.00005 * delta * 144, 0)
);
}
setCurrentSpeed(Math.max(currentSpeed - decceleration, 0))
setCurrentSpeed(Math.max(currentSpeed - decceleration * delta * 144, 0));
}
// Update the kart's rotation based on the steering angle
kart.current.rotation.y += steeringAngle
kart.current.rotation.y += steeringAngle * delta * 144;
// Apply damping to simulate slowdown when no keys are pressed
body.current.applyImpulse(
{
x: -body.current.linvel().x * (1 - damping),
x: -body.current.linvel().x * (1 - damping) * delta * 144,
y: 0,
z: -body.current.linvel().z * (1 - damping)
z: -body.current.linvel().z * (1 - damping) * delta * 144,
},
true
)
const bodyPosition = body.current.translation()
kart.current.position.set(bodyPosition.x, bodyPosition.y - 1, bodyPosition.z)
);
const bodyPosition = body.current.translation();
kart.current.position.set(
bodyPosition.x,
bodyPosition.y - 0.5,
bodyPosition.z
);
// JUMPING
if (jumpPressed && isOnFloor.current && !jumpIsHeld.current) {
jumpForce.current += 11
isOnFloor.current = false
jumpIsHeld.current = true
jumpForce.current += 10;
isOnFloor.current = false;
jumpIsHeld.current = true;
}
if (!isOnFloor.current && jumpForce.current > 0) {
jumpForce.current -= 1
jumpForce.current -= 1 * delta * 144;
}
if (!jumpPressed) {
jumpIsHeld.current = false
driftDirection.current = 0
driftForce.current = 0
driftLeft.current = false
driftRight.current = false
jumpIsHeld.current = false;
driftDirection.current = 0;
driftForce.current = 0;
driftLeft.current = false;
driftRight.current = false;
}
// DRIFTING
if (jumpIsHeld.current && currentSteeringSpeed > 0 && pointer.x < -0.24 && !driftRight.current) {
driftLeft.current = true
if (
jumpIsHeld.current &&
currentSteeringSpeed > 0 &&
pointer.x < -0.1 &&
!driftRight.current
) {
driftLeft.current = true;
}
if (jumpIsHeld.current && currentSteeringSpeed > 0 && pointer.x > 0.24 && !driftLeft.current) {
driftRight.current = true
if (
jumpIsHeld.current &&
currentSteeringSpeed > 0 &&
pointer.x > 0.1 &&
!driftLeft.current
) {
driftRight.current = true;
}
if (!jumpIsHeld.current && !driftLeft.current && !driftRight.current) {
mario.current.rotation.y = THREE.MathUtils.lerp(mario.current.rotation.y, 0, 0.001)
setTurboColor(0xffffff)
accumulatedDriftPower.current = 0
mario.current.rotation.y = THREE.MathUtils.lerp(
mario.current.rotation.y,
0,
0.0001 * delta * 144
);
setTurboColor(0xffffff);
accumulatedDriftPower.current = 0;
}
if (driftLeft.current) {
driftDirection.current = 1
driftForce.current = 0.4
mario.current.rotation.y = THREE.MathUtils.lerp(mario.current.rotation.y, steeringAngle * 50 + 0.5, 0.1)
accumulatedDriftPower.current += 0.1 * (steeringAngle + 1)
driftDirection.current = 1;
driftForce.current = 0.4;
mario.current.rotation.y = THREE.MathUtils.lerp(
mario.current.rotation.y,
steeringAngle * 50 + 0.5,
0.05 * delta * 144
);
accumulatedDriftPower.current += 0.1 * (steeringAngle + 1) * delta * 144;
}
if (driftRight.current) {
driftDirection.current = -1
driftForce.current = 0.4
mario.current.rotation.y = THREE.MathUtils.lerp(mario.current.rotation.y, -(-steeringAngle * 50 + 0.5), 0.1)
accumulatedDriftPower.current += 0.1 * (-steeringAngle + 1)
driftDirection.current = -1;
driftForce.current = 0.4;
mario.current.rotation.y = THREE.MathUtils.lerp(
mario.current.rotation.y,
-(-steeringAngle * 50 + 0.5),
0.05 * delta * 144
);
accumulatedDriftPower.current += 0.1 * (-steeringAngle + 1) * delta * 144;
}
if (!driftLeft.current && !driftRight.current) {
mario.current.rotation.y = THREE.MathUtils.lerp(mario.current.rotation.y, steeringAngle * 30, 0.1)
setScale(0)
mario.current.rotation.y = THREE.MathUtils.lerp(
mario.current.rotation.y,
steeringAngle * 30,
0.05 * delta * 144
);
setScale(0);
}
if (accumulatedDriftPower.current > blueTurboThreshold) {
setTurboColor(0x00ffff)
boostDuration.current = 50
setTurboColor(0x00ffff);
boostDuration.current = 50;
}
if (accumulatedDriftPower.current > orangeTurboThreshold) {
setTurboColor(0xffcf00)
boostDuration.current = 100
setTurboColor(0xffcf00);
boostDuration.current = 100;
}
if (accumulatedDriftPower.current > purpleTurboThreshold) {
setTurboColor(0xff00ff)
boostDuration.current = 250
setTurboColor(0xff00ff);
boostDuration.current = 250;
}
if (driftLeft.current || driftRight.current) {
const oscillation = Math.sin(time * 1000) * 0.1
const oscillation = Math.sin(time * 1000) * 0.1;
const vibration = oscillation + 0.9;
const vibration = oscillation + 0.9
setScale(vibration)
if (turboColor === 0xffffff) {
setScale(vibration * 0.8);
} else {
setScale(vibration);
}
}
// RELEASING DRIFT
if (boostDuration.current > 1 && !jumpIsHeld.current) {
setCurrentSpeed(boostSpeed)
boostDuration.current -= 1
targetZPosition = 10
setIsBoosting(true);
} else if (boostDuration.current <= 1) {
targetZPosition = 8
targetZPosition = 8;
setIsBoosting(false);
}
if (isBoosting && boostDuration.current > 1) {
setCurrentSpeed(boostSpeed);
boostDuration.current -= 1 * delta * 144;
targetZPosition = 10;
} else if (boostDuration.current <= 1) {
setIsBoosting(false);
targetZPosition = 8;
}
// CAMERA WORK
cam.current.updateMatrixWorld()
cam.current.updateMatrixWorld();
cam.current.position.x = THREE.MathUtils.lerp(cam.current.position.x, targetXPosition, 0.01)
cam.current.position.x = THREE.MathUtils.lerp(
cam.current.position.x,
targetXPosition,
0.01 * delta * 144
);
cam.current.position.z = THREE.MathUtils.lerp(cam.current.position.z, targetZPosition, 0.01)
cam.current.updateMatrixWorld()
cam.current.position.z = THREE.MathUtils.lerp(
cam.current.position.z,
targetZPosition,
0.01 * delta * 144
);
body.current.applyImpulse(
{
x: forwardDirection.x * currentSpeed,
y: 0 + jumpForce.current,
z: forwardDirection.z * currentSpeed
x: forwardDirection.x * currentSpeed * delta * 144,
y: 0 + jumpForce.current * delta * 144,
z: forwardDirection.z * currentSpeed * delta * 144,
},
true
)
);
// Update the kart's rotation based on the steering angle
setSteeringAngleWheels(steeringAngle * 25)
})
setSteeringAngleWheels(steeringAngle * 25);
// SOUND WORK
// console.lowg(body.current.translation())
});
return (
<group>
<RigidBody
ref={body}
type='dynamic'
colliders={'ball'}
position={[0, 20, 0]}
colliders={false}
position={[8, 20, -96]}
centerOfMass={[0, -1, 0]}
onCollisionEnter={(event) => {
isOnFloor.current = true
}}
mass={3}
ccd
>
<mesh transparent>
<sphereGeometry args={[1, 6, 6]} />
<meshStandardMaterial
color='blue'
transparent
opacity={0}
/>
</mesh>
<BallCollider
args={[0.5]}
mass={3}
onCollisionEnter={(event) => {
isOnFloor.current = true;
}}
// onCollisionExit={(event) => {
// isOnFloor.current = false
// }}
/>
</RigidBody>
<group ref={kart}>
<group ref={kart} rotation={[0, Math.PI / 2, 0]}>
<group ref={mario}>
<Mario
currentSpeed={currentSpeed}
steeringAngleWheels={steeringAngleWheels}
isBoosting={isBoosting}
/>
{/* <pointLight
position={[0.6, 0.05, 0.5]}
@@ -256,55 +354,64 @@ export const PlayerController = () => {
color={turboColor}
distance={1}
/> */}
<Sphere
args={[1, 16, 16]}
position={[0.6, 0.05, 0.5]}
>
<FakeGlowMaterial
glowCenter={0.1}
edgeIntensity={6.2}
/>
</Sphere>
<mesh
position={[0.6, 0.05, 0.5]}
scale={scale}
>
<sphereGeometry args={[0.1, 16, 16]} />
<mesh position={[0.6, 0.05, 0.5]} scale={scale}>
<sphereGeometry args={[0.05, 16, 16]} />
<meshStandardMaterial
emissive={turboColor}
toneMapped={false}
emissiveIntensity={50}
emissiveIntensity={100}
transparent
opacity={1}
opacity={0.4}
/>
</mesh>
<pointLight
{/* <pointLight
position={[-0.6, 0.05, 0.5]}
intensity={scale}
color={turboColor}
distance={1}
/>
<mesh
position={[-0.6, 0.05, 0.5]}
scale={scale}
>
<sphereGeometry args={[0.1, 16, 16]} />
/> */}
<mesh position={[-0.6, 0.05, 0.5]} scale={scale}>
<sphereGeometry args={[0.05, 16, 16]} />
<meshStandardMaterial
emissive={turboColor}
toneMapped={false}
emissiveIntensity={50}
emissiveIntensity={100}
transparent
opacity={1}
opacity={0.4}
/>
</mesh>
<DriftParticlesLeft
{/* <Cylinder
args={[0.1, 0, 1, 128, 64, true]}
position={[-0.6, 0.05, 0.5]}
rotation={[Math.PI / 3, 0 , 0]}
>
<meshStandardMaterial side={THREE.DoubleSide} />
</Cylinder> */}
{/* <Flame/> */}
<FlameParticles isBoosting={isBoosting} />
<DriftParticlesLeft turboColor={turboColor} scale={scale} />
<DriftParticlesRight turboColor={turboColor} scale={scale} />
<PointParticle
position={[-0.6, 0.05, 0.5]}
png="./circle.png"
turboColor={turboColor}
scale={scale}
/>
<DriftParticlesRight
<PointParticle
position={[0.6, 0.05, 0.5]}
png="./circle.png"
turboColor={turboColor}
/>
<PointParticle
position={[-0.6, 0.05, 0.5]}
png="./star.png"
turboColor={turboColor}
/>
<PointParticle
position={[0.6, 0.05, 0.5]}
png="./star.png"
turboColor={turboColor}
scale={scale}
/>
</group>
@@ -315,7 +422,8 @@ export const PlayerController = () => {
fov={50}
ref={cam}
/>
{/* <PositionalAudio ref={engineSound} url="./sounds/engine.wav" autoplay loop distance={10}/> */}
</group>
</group>
)
}
);
};
@@ -0,0 +1,159 @@
/**
* FakeFlame material component by Anderson Mancini - Jan 2024.
*/
import React, { useMemo, useRef } from 'react'
import { shaderMaterial } from '@react-three/drei'
import { extend, useFrame } from '@react-three/fiber'
import { Color, DoubleSide, AdditiveBlending } from 'three'
export default function FakeFlame({ falloff = 3, glowInternalRadius = 1.0, glowColor = 'orange', glowSharpness = 1.0 , isBoosting,}) {
const FakeFlame = useMemo(() => {
return shaderMaterial(
{
falloffAmount: falloff,
glowInternalRadius: glowInternalRadius,
glowColor: new Color(glowColor),
glowSharpness: glowSharpness,
time: 0,
isBoosting: isBoosting,
},
/*GLSL */
`
varying vec3 vNormal;
varying vec2 vUv;
uniform float time;
float random2D(vec2 value)
{
return fract(sin(dot(value.xy, vec2(12.9898,78.233))) * 43758.5453123);
}
void main() {
// Position
vec4 modelPosition = modelMatrix * vec4(position, 1.0);
vec4 modelNormal = modelMatrix * vec4(normal, 0.0);
// Glitch
float glitchTime = time + modelPosition.y;
float glitchStrength = sin(glitchTime) + sin(glitchTime * .05) + sin(glitchTime * .36);
glitchStrength /= 2.0;
glitchStrength = smoothstep(0.2, 0.8, glitchStrength);
glitchStrength *= 0.05;
modelPosition.x += (random2D(modelNormal.xx + time) - 0.5) * glitchStrength;
modelPosition.x += (random2D(modelNormal.xx - time) - 0.2) * glitchStrength;
modelPosition.y += sin(smoothstep(0.3, vUv.y - 2.2, position.y) * 2.) * sin(time * 48.);
modelPosition.z += sin(smoothstep(0., vUv.x - 0.8, position.z) * 2.) * sin(time * 24.) * .6;
gl_Position = projectionMatrix * viewMatrix * modelPosition;
vUv = uv;
}`,
/*GLSL */
`
uniform vec3 glowColor;
uniform float falloffAmount;
uniform float glowSharpness;
uniform float glowInternalRadius;
uniform float time;
uniform bool isBoosting;
varying vec2 vUv;
vec2 hash( vec2 p )
{
p = vec2( dot(p,vec2(127.1,311.7)),
dot(p,vec2(269.5,183.3)) );
return -1.0 + 2.0*fract(sin(p)*43758.5453123);
}
float noise( in vec2 p )
{
const float K1 = 0.366025404; // (sqrt(3)-1)/2;
const float K2 = 0.211324865; // (3-sqrt(3))/6;
vec2 i = floor( p + (p.x+p.y)*K1 );
vec2 a = p - i + (i.x+i.y)*K2;
vec2 o = (a.x>a.y) ? vec2(1.0,0.0) : vec2(0.0,1.0);
vec2 b = a - o + K2;
vec2 c = a - 1.0 + 2.0*K2;
vec3 h = max( 0.5-vec3(dot(a,a), dot(b,b), dot(c,c) ), 0.0 );
vec3 n = h*h*h*h*vec3( dot(a,hash(i+0.0)), dot(b,hash(i+o)), dot(c,hash(i+1.0)));
return dot( n, vec3(70.0) );
}
float fbm(vec2 uv)
{
float f;
mat2 m = mat2( 1.6, 1.2, -1.2, 1.6 );
f = 0.5000*noise( uv ); uv = m*uv;
f += 0.2500*noise( uv ); uv = m*uv;
// f += 0.1250*noise( uv ); uv = m*uv;
// f += 0.0625*noise( uv ); uv = m*uv;
f = 0.5 + 0.5*f;
return f;
}
// #define BLUE_FLAME
// #define GREEN_FLAME
void main()
{
vec2 q = vUv;
q.x *= 2.;
q.y *= 2.;
float strength = floor(q.x+1.5);
float T3 = max(2.,2.25*strength)*time * 3.;
q.x = mod(q.x,1.)-0.5;
q.y -= 0.05;
float n = fbm(strength*q + vec2(0,T3));
float c = 0.7 - 0.01 * pow( max( 0., length(q*vec2(1.8+q.y*1.5,.75) ) - n * max( 0., q.y+.25 ) ),.2 );
// float c1 = n * c * fract((1.9-pow(0.15*vUv.y,2.))) * 2.;
float c1 = n * c * (pow(1.90*vUv.y,2.));
c1=clamp(c1,0.,1.);
vec3 col = smoothstep(0.1, 0.8, vec3(c1, c1*c1*c1, c1*c1*c1*c1*c1*c1));
#ifdef BLUE_FLAME
col = col.zyx;
#endif
#ifdef GREEN_FLAME
col = 0.85*col.yxz;
#endif
if (isBoosting) {
gl_FragColor = vec4(col, 1.0);
} else {
gl_FragColor = vec4(col, 0.0);
}
#include <tonemapping_fragment>
#include <colorspace_fragment>
}`
)
}, [falloff, glowInternalRadius, glowColor, glowSharpness, isBoosting])
extend({ FakeFlame })
useFrame((state, delta) => {
ref.current.time += delta
})
const ref = useRef()
return (
<fakeFlame
key={FakeFlame.key}
side={DoubleSide}
transparent={true}
blending={AdditiveBlending}
depthTest={false}
ref={ref}
/>
)
}
@@ -0,0 +1,73 @@
/**
* fakeGlow material component by Anderson Mancini - Dec 2023.
*/
import React, { useMemo } from 'react'
import { shaderMaterial } from '@react-three/drei'
import { extend } from '@react-three/fiber'
import { Color, DoubleSide, AdditiveBlending } from 'three'
export default function FakeGlowMaterial({ falloff = 3, glowInternalRadius = 1.0, glowColor = '#b97939', glowSharpness = 1.0 }) {
const FakeGlowMaterial = useMemo(() => {
return shaderMaterial(
{
falloffAmount: falloff,
glowInternalRadius: glowInternalRadius,
glowColor: new Color(glowColor),
glowSharpness: glowSharpness
},
/*GLSL */
`
varying vec3 vPosition;
varying vec3 vNormal;
void main() {
vec4 modelPosition = modelMatrix * vec4(position, 1.0);
gl_Position = projectionMatrix * viewMatrix * modelPosition;
vec4 modelNormal = modelMatrix * vec4(normal, 0.0);
vPosition = modelPosition.xyz;
vNormal = modelNormal.xyz;
}`,
/*GLSL */
`
uniform vec3 glowColor;
uniform float falloffAmount;
uniform float glowSharpness;
uniform float glowInternalRadius;
varying vec3 vPosition;
varying vec3 vNormal;
void main()
{
// Normal
vec3 normal = normalize(vNormal);
if(!gl_FrontFacing){ normal *= - 1.0; }
vec3 viewDirection = normalize(cameraPosition - vPosition);
float fresnel = dot(viewDirection, normal);
fresnel = pow(fresnel, glowInternalRadius);
float falloff = smoothstep(0., falloffAmount, fresnel);
float fakeGlow = fresnel;
fakeGlow += fresnel * glowSharpness;
fakeGlow *= falloff;
gl_FragColor = vec4(clamp(glowColor * fresnel, 0., 1.0), clamp(fakeGlow, 0., 1.0));
#include <tonemapping_fragment>
#include <colorspace_fragment>
}`
)
}, [falloff, glowInternalRadius, glowColor, glowSharpness])
extend({ FakeGlowMaterial })
return (
<fakeGlowMaterial
key={FakeGlowMaterial.key}
side={DoubleSide}
transparent={true}
blending={AdditiveBlending}
depthTest={false}
/>
)
}
+68
View File
@@ -0,0 +1,68 @@
import { Euler, Object3D, BackSide, Vector3 } from "three";
import { useRef, useLayoutEffect } from "react";
import { useFrame } from "@react-three/fiber";
import { useStore } from "./store";
const o = new Object3D();
export function Skid({ count = 500, opacity = 1, size = 0.4 }) {
const ref = useRef(null);
const [bodyPosition, bodyRotation] = useStore((state) => [
state.bodyPosition,
state.bodyRotation,
]);
let index = 0;
useFrame(() => {
// console.log(bodyPosition, bodyRotation);
if (ref.current && bodyPosition && bodyRotation !== undefined) {
setItemAt(ref.current, bodyPosition, bodyRotation, 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 (
<instancedMesh ref={ref} args={[undefined, undefined, count]}>
<planeGeometry args={[size, size * 2]} />
<meshBasicMaterial
color={0x000000}
transparent
opacity={opacity}
depthWrite={false}
side={BackSide}
/>
</instancedMesh>
);
}
function setItemAt(instances, bodyPosition, bodyRotation, index) {
// Calculate the backward offset
const backwardOffset = 0.5; // Adjust this value as needed
const forwardDirection = new Vector3(
-Math.sin(bodyRotation),
0,
-Math.cos(bodyRotation)
);
const backwardPosition = forwardDirection
.multiplyScalar(-backwardOffset)
.add(bodyPosition);
// Apply the offset to position the skid marks behind the body
console.log(bodyPosition);
o.position.copy(bodyPosition.x, bodyPosition.y + 2, bodyPosition.z);
o.rotation.set(0, bodyRotation, 0);
o.scale.setScalar(1);
o.updateMatrix();
instances.setMatrixAt(index, o.matrix);
instances.instanceMatrix.needsUpdate = true;
}
@@ -1,73 +0,0 @@
import React, { useEffect, useRef } from "react";
import { useGLTF } from "@react-three/drei";
import gsap from "gsap";
export function FrontLeftWheel({
currentSpeed,
left,
right,
...props
}) {
const { nodes, materials } = useGLTF("./models/front_wheel.glb");
const wheel = useRef();
useEffect(() => {
if (!wheel.current) return;
if(left){
gsap.to(wheel.current.rotation, {
duration: 0.5,
y: Math.PI + Math.PI / 8,
ease: "power2.inOut",
});
gsap.to(wheel.current.position, {
duration: 0.5,
z: 0.075,
ease: "power2.inOut",
});
} else if(right){
gsap.to(wheel.current.rotation, {
duration: 0.5,
y: Math.PI - Math.PI / 8,
ease: "power2.inOut",
});
gsap.to(wheel.current.position, {
duration: 0.5,
z: -0.075,
ease: "power2.inOut",
});
} else if(!left && !right){
gsap.to(wheel.current.rotation, {
duration: 0.2,
y: Math.PI,
ease: "power2.inOut",
});
gsap.to(wheel.current.position, {
duration: 0.2,
z: 0,
ease: "power2.inOut",
});
}
}, [left, right]);
return (
<group {...props} dispose={null}>
<group ref={wheel}>
<mesh
geometry={nodes.FL_Wheel_Body_0001.geometry}
material={materials.Body}
/>
<mesh
geometry={nodes.FL_Wheel_Rims_0001.geometry}
material={materials.Rims}
/>
<mesh
geometry={nodes.FL_Wheel_Tires_0001.geometry}
material={materials.Tires}
/>
</group>
</group>
);
}
useGLTF.preload("./models/front_wheel.glb");
@@ -1,74 +0,0 @@
import React, { useEffect, useRef } from "react";
import { useGLTF } from "@react-three/drei";
import gsap from "gsap";
export function FrontRightWheel({
currentSpeed,
left,
right,
...props
}) {
const { nodes, materials } = useGLTF("./models/front_wheel.glb");
const wheel = useRef();
useEffect(() => {
if (!wheel.current) return;
if(left){
gsap.to(wheel.current.rotation, {
duration: 0.5,
y: Math.PI / 8,
ease: "power2.inOut",
});
gsap.to(wheel.current.position, {
duration: 0.5,
z: -0.075,
ease: "power2.inOut",
});
} else if(right){
gsap.to(wheel.current.rotation, {
duration: 0.5,
y: - Math.PI / 8,
ease: "power2.inOut",
});
gsap.to(wheel.current.position, {
duration: 0.5,
z: 0.075,
ease: "power2.inOut",
});
} else if(!left && !right) {
gsap.to(wheel.current.rotation, {
duration: 0.2,
y: 0,
ease: "power2.inOut",
});
gsap.to(wheel.current.position, {
duration: 0.2,
z: 0,
ease: "power2.inOut",
});
}
}, [left, right]);
return (
<group {...props} dispose={null}>
<group ref={wheel}>
<mesh
geometry={nodes.FL_Wheel_Body_0001.geometry}
material={materials.Body}
/>
<mesh
geometry={nodes.FL_Wheel_Rims_0001.geometry}
material={materials.Rims}
/>
<mesh
geometry={nodes.FL_Wheel_Tires_0001.geometry}
material={materials.Tires}
/>
</group>
</group>
);
}
useGLTF.preload("./models/front_wheel.glb");
-44
View File
@@ -1,44 +0,0 @@
/*
Auto-generated by: https://github.com/pmndrs/gltfjsx
Command: npx gltfjsx@6.2.16 .\front_wheel.glb
*/
import React, { useEffect, useRef } from "react";
import { useGLTF } from "@react-three/drei";
import gsap from "gsap";
export function FrontWheel({
isLeftWheel,
currentSpeed,
left,
right,
...props
}) {
const { nodes, materials } = useGLTF("./models/front_wheel.glb");
const wheel = useRef();
const rotation = isLeftWheel ? [0, Math.PI, 0] : [0, 0, 0];
useEffect(() => {
}, [currentSpeed, left, right]);
return (
<group {...props} dispose={null}>
<group ref={wheel} rotation={rotation}>
<mesh
geometry={nodes.FL_Wheel_Body_0001.geometry}
material={materials.Body}
/>
<mesh
geometry={nodes.FL_Wheel_Rims_0001.geometry}
material={materials.Rims}
/>
<mesh
geometry={nodes.FL_Wheel_Tires_0001.geometry}
material={materials.Tires}
/>
</group>
</group>
);
}
useGLTF.preload("./models/front_wheel.glb");
-39
View File
@@ -1,39 +0,0 @@
/*
Auto-generated by: https://github.com/pmndrs/gltfjsx
Command: npx gltfjsx@6.2.16 .\mariokarttest.glb --shadows
*/
import React, { useRef } from 'react'
import { useGLTF } from '@react-three/drei'
import { useFrame } from '@react-three/fiber'
export function Mario({currentSpeed, steeringAngleWheels, ...props}) {
const { nodes, materials } = useGLTF('./models/mariokarttest.glb')
const frontLeftWheel = useRef()
const frontRightWheel = useRef()
const rearWheels = useRef()
const frontWheels = useRef()
useFrame(() => {
const rotation = currentSpeed / 100
frontLeftWheel.current.rotation.x += rotation
frontRightWheel.current.rotation.x += rotation
rearWheels.current.rotation.x += rotation
frontWheels.current.rotation.y = steeringAngleWheels
})
return (
<group {...props} rotation={[0, Math.PI, 0]} dispose={null}>
<mesh castShadow receiveShadow geometry={nodes.mt_kart_Mario_S.geometry} material={materials.mt_kart_Mario_S} />
<mesh ref={rearWheels} castShadow receiveShadow geometry={nodes.mt_Kart_Mario_Tire_S001.geometry} material={materials.mt_Kart_Mario_Tire_S} position={[0, 0.22, -0.347]} />
<group ref={frontWheels} >
<mesh ref={frontLeftWheel} castShadow receiveShadow geometry={nodes.mt_Kart_Mario_Tire_S002.geometry} material={materials.mt_Kart_Mario_Tire_S} position={[0.370, 0.193, 0.441]} />
<mesh ref={frontRightWheel} castShadow receiveShadow geometry={nodes.mt_Kart_Mario_Tire_S003.geometry} material={materials.mt_Kart_Mario_Tire_S} position={[-0.370, 0.193, 0.441]} rotation={[-Math.PI, 0, 0]} scale={-1} />
</group>
<mesh castShadow receiveShadow geometry={nodes.mt_mario.geometry} material={materials.mt_mario} />
</group>
)
}
useGLTF.preload('./models/mariokarttest.glb')
-111
View File
@@ -1,111 +0,0 @@
/*
Auto-generated by: https://github.com/pmndrs/gltfjsx
Command: npx gltfjsx@6.2.16 .\racing_kart.glb --transform
Files: .\racing_kart.glb [1.83MB] > C:\Users\mouli\dev\r3f-vite-starter\public\models\racing_kart-transformed.glb [150.05KB] (92%)
Author: scailman (https://sketchfab.com/scailman)
License: CC-BY-4.0 (http://creativecommons.org/licenses/by/4.0/)
Source: https://sketchfab.com/3d-models/racing-kart-f48f8e66bba6492eadc000d2585b6a32
Title: Racing Kart
*/
import React, { useEffect, useRef } from "react";
import { useGLTF } from "@react-three/drei";
import gsap from "gsap";
export function Model({ steeringAngle, speed, left, right, ...props }) {
const { nodes, materials } = useGLTF("./models/racing_kart-transformed.glb");
return (
<group {...props} dispose={null}>
<group rotation={[0, Math.PI, 0]}>
<mesh
geometry={nodes.drivers_Visera_0.geometry}
material={materials.Visera}
position={[0, 1.055, 0]}
rotation={[-Math.PI / 2, 0, 0]}
/>
<mesh
geometry={nodes.drivers_Mono1_0.geometry}
material={materials.Mono1}
position={[0, 1.055, 0]}
rotation={[-Math.PI / 2, 0, 0]}
/>
<mesh
geometry={nodes.drivers_Casco2_0.geometry}
material={materials.Casco2}
position={[0, 1.055, 0]}
rotation={[-Math.PI / 2, 0, 0]}
/>
<mesh
geometry={nodes.drivers_Casco_0.geometry}
material={materials.Casco}
position={[0, 1.055, 0]}
rotation={[-Math.PI / 2, 0, 0]}
/>
<mesh
geometry={nodes.drivers_Piel_0.geometry}
material={materials.Piel}
position={[0, 1.055, 0]}
rotation={[-Math.PI / 2, 0, 0]}
/>
<mesh
geometry={nodes.drivers_Mono2_0.geometry}
material={materials.Mono2}
position={[0, 1.055, 0]}
rotation={[-Math.PI / 2, 0, 0]}
/>
<mesh
geometry={nodes.drivers_Mono2_0_1.geometry}
material={materials.Mono2_0}
position={[0, 1.055, 0]}
rotation={[-Math.PI / 2, 0, 0]}
/>
<mesh
geometry={nodes.Chassis_Rims_0.geometry}
material={materials.Rims}
position={[-0.221, 0.132, 0.413]}
/>
<mesh
geometry={nodes.Chassis_Chassis_0.geometry}
material={materials.Chassis}
position={[-0.221, 0.132, 0.413]}
/>
{/* <mesh
geometry={nodes.FR_Wheel_Tires_0.geometry}
material={materials.Tires}
position={[-0.033, 0.157, 0.412]}
rotation={[-Math.PI / 2, 0, 0]}
/>
<mesh
geometry={nodes.FR_Wheel_Body_0.geometry}
material={materials.Body}
position={[-0.033, 0.157, 0.412]}
rotation={[-Math.PI / 2, 0, 0]}
/> */}
<mesh
geometry={nodes.Body_Lines2_0.geometry}
material={materials.Lines2}
position={[-0.351, 0.15, -0.124]}
rotation={[0, -1.57, 0]}
/>
<mesh
geometry={nodes.Engine_Engine_0.geometry}
material={materials.Engine}
position={[-0.229, 0.22, -0.465]}
rotation={[0, -1.57, 0]}
scale={[1.31, 1.31, 1.041]}
/>
<mesh
geometry={nodes.Engine_Deposit_0.geometry}
material={materials.Deposit}
position={[-0.229, 0.22, -0.465]}
rotation={[0, -1.57, 0]}
scale={[1.31, 1.31, 1.041]}
/>
</group>
</group>
);
}
useGLTF.preload("./models/racing_kart-transformed.glb");
-33
View File
@@ -1,33 +0,0 @@
/*
Auto-generated by: https://github.com/pmndrs/gltfjsx
Command: npx gltfjsx@6.2.16 .\rear_wheels.glb
*/
import React, { useRef } from 'react'
import { useGLTF } from '@react-three/drei'
export function RearWheels(props) {
const { nodes, materials } = useGLTF('./models/rear_wheels.glb')
return (
<group {...props} dispose={null}>
<group position={[0.463, 0.157, -0.622]}>
<group position={[-0.431, 0, 0]} rotation={[-Math.PI / 2, 0, 0]}>
<mesh geometry={nodes.RL_Wheel_Body_0.geometry} material={materials.Body} />
<mesh geometry={nodes.RL_Wheel_Rims_0.geometry} material={materials.Rims} />
<mesh geometry={nodes.RL_Wheel_Tires_0.geometry} material={materials.Tires} />
<mesh geometry={nodes.RL_Wheel_Tires_0001.geometry} material={materials.Tires} />
</group>
</group>
<group position={[-0.463, 0.157, -0.622]}>
<group position={[0.431, 0, 0]} rotation={[-Math.PI / 2, 0, 0]}>
<mesh geometry={nodes.RR_Wheel_Body_0.geometry} material={materials.Body} />
<mesh geometry={nodes.RR_Wheel_Rims_0.geometry} material={materials.Rims} />
<mesh geometry={nodes.RR_Wheel_Tires_0.geometry} material={materials.Tires} />
<mesh geometry={nodes.RR_Wheel_Tires_0001.geometry} material={materials.Tires} />
</group>
</group>
</group>
)
}
useGLTF.preload('./models/rear_wheels.glb')
@@ -1,21 +0,0 @@
/*
Auto-generated by: https://github.com/pmndrs/gltfjsx
Command: npx gltfjsx@6.2.16 .\spafrancorchamps-REALISTIC.glb
*/
import React, { useRef } from 'react'
import { useGLTF } from '@react-three/drei'
import { RigidBody } from '@react-three/rapier'
export function Track(props) {
const { nodes, materials } = useGLTF('./models/spafrancorchamps-REALISTIC.glb')
return (
<group {...props} dispose={null}>
<RigidBody type="fixed" name={'terrain'} colliders="trimesh" userData={'terrain'} position={[0, 1, 0]}>
<mesh geometry={nodes.Cube.geometry} material={nodes.Cube.material} />
</RigidBody>
</group>
)
}
useGLTF.preload('./models/spafrancorchamps-REALISTIC.glb')
@@ -0,0 +1,126 @@
/*
Auto-generated by: https://github.com/pmndrs/gltfjsx
Command: npx gltfjsx@6.2.16 .\mariokarttest.glb --shadows
*/
import React, { useRef } from 'react'
import { Cylinder, OrbitControls, Sphere, useGLTF } from '@react-three/drei'
import { useFrame } from '@react-three/fiber'
import FakeGlowMaterial from '../../ShaderMaterials/FakeGlow/FakeGlowMaterial'
import FakeFlame from '../../ShaderMaterials/FakeFlame/FakeFlame'
export function Mario({ currentSpeed, steeringAngleWheels, isBoosting, ...props }) {
const { nodes, materials } = useGLTF('./models/characters/mariokarttest.glb')
const frontLeftWheel = useRef()
const frontRightWheel = useRef()
const rearWheels = useRef()
const frontWheels = useRef()
const [scale, setScale] = React.useState(1)
// isBoosting = true;
useFrame((_,delta) => {
const rotation = currentSpeed / 100
frontLeftWheel.current.rotation.x += rotation
frontRightWheel.current.rotation.x += rotation
rearWheels.current.rotation.x += rotation
frontWheels.current.rotation.y = steeringAngleWheels
if (isBoosting){
setScale(Math.min(scale + 0.05 * 144 * delta, 1))
} else {
setScale(Math.max(scale - 0.03 * 144 * delta, 0))
}
})
return (
<group
{...props}
rotation={[0, Math.PI, 0]}
dispose={null}
>
<mesh
castShadow
receiveShadow
geometry={nodes.mt_kart_Mario_S.geometry}
material={materials.mt_kart_Mario_S}
/>
<mesh
ref={rearWheels}
castShadow
receiveShadow
geometry={nodes.mt_Kart_Mario_Tire_S001.geometry}
material={materials.mt_Kart_Mario_Tire_S}
position={[0, 0.22, -0.347]}
/>
<group ref={frontWheels}>
<mesh
ref={frontLeftWheel}
castShadow
receiveShadow
geometry={nodes.mt_Kart_Mario_Tire_S002.geometry}
material={materials.mt_Kart_Mario_Tire_S}
position={[0.37, 0.193, 0.441]}
/>
<mesh
ref={frontRightWheel}
castShadow
receiveShadow
geometry={nodes.mt_Kart_Mario_Tire_S003.geometry}
material={materials.mt_Kart_Mario_Tire_S}
position={[-0.37, 0.193, 0.441]}
rotation={[-Math.PI, 0, 0]}
scale={-1}
/>
</group>
<mesh
castShadow
receiveShadow
geometry={nodes.mt_mario.geometry}
material={materials.mt_mario}
/>
<Sphere
position={[0, 0.6, -1.2]}
scale={scale * 1.2}
>
<FakeGlowMaterial />
</Sphere>
<Cylinder
args={[0.1, 0, 1, 128, 64, true]}
position={[0.3, 0.6, -1.2]}
rotation={[Math.PI / 1.5, 0, 0]}
scale={scale}
>
<FakeFlame isBoosting={isBoosting}/>
</Cylinder>
<Cylinder
args={[0.1, 0, 1, 128, 64, true]}
position={[-0.3, 0.6, -1.2]}
rotation={[Math.PI / 1.5, 0, 0]}
scale={scale}
>
<FakeFlame isBoosting={isBoosting} />
</Cylinder>
<Cylinder
args={[0.09, 0, 1, 128, 64, true]}
position={[0.18, 0.7, -0.8]}
rotation={[Math.PI / 1.5, 0, 0]}
scale={scale}
>
<FakeFlame isBoosting={isBoosting} />
</Cylinder>
<Cylinder
args={[0.09, 0, 1, 128, 64, true]}
position={[-0.18, 0.7, -0.8]}
rotation={[Math.PI / 1.5, 0, 0]}
scale={scale}
>
<FakeFlame isBoosting={isBoosting}/>
</Cylinder>
</group>
)
}
useGLTF.preload('./models/characters/mariokarttest.glb')
@@ -13,7 +13,7 @@ import { useGLTF } from '@react-three/drei'
import { RigidBody } from '@react-three/rapier'
export function Paris(props) {
const { nodes, materials } = useGLTF('./models/tour_paris_promenade-transformed.glb')
const { nodes, materials } = useGLTF('./models/tracks/tour_paris_promenade-transformed.glb')
materials.M_Cmn_ShadowCollision.opacity = 0
materials.M_Cmn_ShadowCollision.transparent = true
return (
@@ -35,4 +35,4 @@ export function Paris(props) {
)
}
useGLTF.preload('./models/tour_paris_promenade-transformed.glb')
useGLTF.preload('./models/tracks/tour_paris_promenade-transformed.glb')
+44 -29
View File
@@ -1,33 +1,48 @@
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),
}));
},
particles1: [],
particles2: [],
bodyPosition: [0, 0, 0],
bodyRotation: [0, 0, 0],
pastPositions: [],
addPastPosition: (position) => {
set((state) => ({
pastPositions: [position, ...state.pastPositions.slice(0, 499)],
}));
},
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),
}));
},
setBodyPosition: (position) => {
set({ bodyPosition: position });
},
setBodyRotation: (rotation) => {
set({ bodyRotation: rotation });
},
getBodyPosition: () => {
return get().bodyPosition;
},
getBodyRotation: () => {
return get().bodyRotation;
},
},
}));
+54
View File
@@ -3,6 +3,60 @@
height: 100vh;
}
*
body {
margin: 0;
/* cursor:none; */
overflow-y: none;
overflow-x: none;
}
body::-webkit-scrollbar {
display: none;
}
.wheel{
display: none;
position:absolute;
top:0;
opacity: 0.2;
img{
width: 200px;
}
}
.overlay{
position:absolute;
top:0;
left:0;
width:100vw;
height:100vh;
pointer-events: none;
}
.logo{
position:absolute;
top:150px;
left:500px;
opacity: 1;
img{
width: 600px;
animation: bounce 0.4s infinite cubic-bezier(.71,1.94,.5,.61)
}
}
@keyframes bounce {
0%, 100% {
transform: scale(1);
}
50% {
transform: scale(1.2);
}
}
+2
View File
@@ -2,9 +2,11 @@ import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
import './index.css'
import { HUD } from './HUD'
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<App />
{/* <HUD /> */}
</React.StrictMode>,
)