Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
faad40aa9d | ||
|
|
bfccc00f4d | ||
|
|
54810a73cd | ||
|
|
fdd821e630 | ||
|
|
2d9230b8ea | ||
|
|
b1b93043f8 | ||
|
|
73343a8739 | ||
|
|
be364fca25 | ||
|
|
83d7e6c16b | ||
|
|
934c26491c | ||
|
|
6232bf9498 | ||
|
|
2753ec7127 | ||
|
|
a819fcae4c | ||
|
|
f5ebee224c | ||
|
|
7daaf262aa | ||
|
|
16b2bbb93a | ||
|
|
6d4032d9c7 | ||
|
|
e1c11b3d74 | ||
|
|
cb8052e1d3 | ||
|
|
602536bc23 |
No files matched your search
@@ -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>
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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": {
|
||||
|
||||
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 93 KiB |
|
After Width: | Height: | Size: 82 KiB |
|
After Width: | Height: | Size: 127 KiB |
|
After Width: | Height: | Size: 35 KiB |
|
After Width: | Height: | Size: 9.2 KiB |
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
@@ -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}
|
||||
/>
|
||||
)
|
||||
}
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
@@ -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}
|
||||
/>
|
||||
)
|
||||
}
|
||||
@@ -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");
|
||||
@@ -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");
|
||||
@@ -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')
|
||||
@@ -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");
|
||||
@@ -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')
|
||||
@@ -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;
|
||||
},
|
||||
},
|
||||
}));
|
||||
@@ -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,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>,
|
||||
)
|
||||