Author SHA1 Message Date
Alex b1b93043f8 bug(game): tried to add skid according to 0xc0a 's racing game 2024-01-25 10:04:19 +01:00
Alex 73343a8739 fix:(game) just fixed a small issue causing gained boost to stop if the player is drifting 2024-01-25 04:19:06 +01:00
Alex be364fca25 fix:(game) GAME IS FIXED, CAN CONTINUE DEV SAFELY 2024-01-24 15:51:51 +01:00
Alex 83d7e6c16b fix:(game) Fixed small issue with pointParticle causing the particle to go negative 2024-01-24 14:55:30 +01:00
Anderson Mancini 934c26491c Added small physics improvments 2024-01-24 09:44:28 -03:00
Anderson Mancini 6232bf9498 Fixed FakeGlowMaterial
+Added Flames Material :)
2024-01-24 09:40:02 -03:00
Alex 2753ec7127 fix:(game) Fixed constant refresh rate behavior 2024-01-24 11:15:25 +01:00
Alex a819fcae4c fix:(game) Fixed constant refresh rate behavior 2024-01-24 11:04:23 +01:00
Alex f5ebee224c fix:(game) Fixed constant refresh rate behavior 2024-01-24 11:02:05 +01:00
Alex 7daaf262aa feat:(game) set a real starting pose 2024-01-23 15:02:38 +01:00
Alex 16b2bbb93a feat:(game) added flame particles for boosting 2024-01-23 12:56:30 +01:00
Alex 6d4032d9c7 feat:(game) improved particle system for drifting again 2024-01-23 11:49:50 +01:00
Alex e1c11b3d74 feat:(game) improved particle system for drifting 2024-01-23 10:44:10 +01:00
Alex cb8052e1d3 feat:(game) fixed drifting mechanics and improved postprocessing effects 2024-01-22 19:46:07 +01:00
Alex 602536bc23 feat(game) : added ui base for steering 2024-01-22 18:39:20 +01:00
33 changed files with 1658 additions and 386 deletions

No files matched your search

+2 -2
View File
@@ -2,9 +2,9 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<link rel="icon" type="image/svg+xml" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React</title>
<title>Mario Kart 3.js</title>
</head>
<body>
<div id="root"></div>
+4 -4
View File
@@ -12,7 +12,7 @@
"@react-three/fiber": "^8.15.13",
"@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",
@@ -1981,9 +1981,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",
+1 -1
View File
@@ -13,7 +13,7 @@
"@react-three/fiber": "^8.15.13",
"@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",
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

+1 -1
View File
@@ -38,7 +38,7 @@ function App() {
<Suspense fallback={null}>
<Physics
gravity={[0, -90, 0]}
predictionDistance={0.001}
timeStep={'vary'}
>
<KeyboardControls map={map}>
<Experience />
+46
View File
@@ -0,0 +1,46 @@
import React, { useEffect, useRef } from "react";
export const HUD = () => {
const wheel = useRef();
useEffect(() => {
const handleMouseMove = (e) => {
if (wheel.current) {
const { clientX, clientY } = e;
const screenWidth = window.innerWidth;
const rotation = ((clientX - screenWidth / 2) / screenWidth) * 180;
wheel.current.style.left = `${clientX - 100}px`;
wheel.current.style.top = `${clientY - 100}px`;
wheel.current.style.transform = `rotate(${rotation}deg)`;
}
};
window.addEventListener("mousemove", handleMouseMove);
return () => {
window.removeEventListener("mousemove", handleMouseMove);
};
}, []);
return (
<div className="overlay"> dadasd
<div className="logo">
<img src="./logo.png" alt="logo" />
</div>
<div className="wheel">
<img
ref={wheel}
src="./steering_wheel.png"
alt="steering wheel"
className="steering-wheel"
style={{
position: "absolute",
pointerEvents: "none",
transformOrigin: "center",
}}
/>
</div>
</div>
);
};
+1 -3
View File
@@ -3,7 +3,7 @@ import { Particles3 } from "./Particles3";
export const DriftParticlesLeft = ({turboColor,scale, ...props}) => {
if(scale < 0.5) {
if(scale < 0.8) {
return null;
}
@@ -20,8 +20,6 @@ export const DriftParticlesLeft = ({turboColor,scale, ...props}) => {
<Particles1 turboColor={turboColor} scale={scale} />
<Particles3 turboColor={turboColor} scale={scale} />
<Particles3 turboColor={turboColor} scale={scale} />
<Particles3 turboColor={turboColor} scale={scale} />
</group>
)
+3 -4
View File
@@ -3,13 +3,13 @@ import { Particles4 } from "./Particles4";
export const DriftParticlesRight = ({turboColor,scale, ...props}) => {
if(scale < 0.5) {
if(scale < 0.8) {
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} />
@@ -20,8 +20,7 @@ export const DriftParticlesRight = ({turboColor,scale, ...props}) => {
<Particles2 turboColor={turboColor} scale={scale} />
<Particles4 turboColor={turboColor} scale={scale} />
<Particles4 turboColor={turboColor} scale={scale} />
<Particles4 turboColor={turboColor} scale={scale} />
</group>
)
+19 -10
View File
@@ -4,16 +4,21 @@ 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 { EffectComposer, N8AO, Bloom, DepthOfField, TiltShift2, HueSaturation, SMAA, ChromaticAberration, Vignette } from '@react-three/postprocessing'
import { PlayerControllerAgain } from './PlayerControllerAgain'
import { Skid } from './Skid'
export const Experience = () => {
return (
<>
<PlayerController />
<Skid />
{/* <PlayerControllerAgain /> */}
<Ground position={[0, 0, 0]} />
<Environment
resolution={256}
preset='lobby'
/>
<directionalLight
@@ -34,24 +39,28 @@ export const Experience = () => {
<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/> */}
{/* <DepthOfField
target={[0, 0, 12]}
focalLength={15}
bokehScale={60}
resolutionScale={1}
/> */}
<TiltShift2/>
<ChromaticAberration offset={[0.0006, 0.0006]} />
<HueSaturation saturation={0.1} />
<Vignette eskil={false} offset={0.1} darkness={0.4} />
</EffectComposer>
</>
)
+159
View File
@@ -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}
/>
)
}
+36 -45
View File
@@ -1,82 +1,73 @@
/**
* FakeGlow material component by Anderson Mancini - Dec 2024.
* fakeGlow material component by Anderson Mancini - Dec 2023.
*/
import React, { useRef, useMemo } from 'react'
import React, { useMemo } from 'react'
import { shaderMaterial } from '@react-three/drei'
import { extend, useFrame } from '@react-three/fiber'
import { Color, BackSide, AdditiveBlending } from 'three'
import { extend } from '@react-three/fiber'
import { Color, DoubleSide, 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 }) {
export default function FakeGlowMaterial({ falloff = 3, glowInternalRadius = 1.0, glowColor = '#b97939', glowSharpness = 1.0 }) {
const FakeGlowMaterial = useMemo(() => {
return shaderMaterial(
{
time: 0,
glowCenter: glowCenter,
edgeIntensity: edgeIntensity,
falloffAmount: falloff,
glowInternalRadius: glowInternalRadius,
glowColor: new Color(glowColor),
glowOpacity: glowOpacity,
fresnelOpacity: fresnelOpacity,
fresnelAmount: fresnelAmount
glowSharpness: glowSharpness
},
/*GLSL */
`
uniform float glowCenter;
uniform float edgeIntensity;
varying float intensity;
varying vec3 vNormel;
varying vec3 vPosition;
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 );
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;
varying float intensity;
uniform float glowOpacity;
uniform float fresnelOpacity;
uniform float fresnelAmount;
varying vec3 vNormel;
uniform float falloffAmount;
uniform float glowSharpness;
uniform float glowInternalRadius;
varying vec3 vPosition;
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 ));
// 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>
}`
)
}, [glowCenter, edgeIntensity, glowColor, glowOpacity, fresnelOpacity, fresnelAmount])
}, [falloff, glowInternalRadius, glowColor, glowSharpness])
extend({ FakeGlowMaterial })
useFrame((state, delta) => {
ref.current.time += delta
})
const ref = useRef()
return (
<fakeGlowMaterial
wireframe={wireframe}
key={FakeGlowMaterial.key}
side={BackSide}
side={DoubleSide}
transparent={true}
blending={AdditiveBlending}
depthTest={false}
ref={ref}
/>
)
}
+56
View File
@@ -0,0 +1,56 @@
import React, { useState, useEffect, useRef } from "react";
import { useLoader, useFrame } from "@react-three/fiber";
import * as THREE from "three";
export const FlameParticle = ({ position, png, turboColor, delay = 0 }) => {
const texture = useLoader(THREE.TextureLoader, png);
const pointsRef = useRef();
const [size, setSize] = useState(1);
const [opacity, setOpacity] = useState(1);
const [initialized, setInitialized] = useState(false);
useEffect(() => {
const timer = setTimeout(() => {
setInitialized(true);
}, delay);
return () => clearTimeout(timer);
}, [delay]);
const points = React.useMemo(() => {
const geom = new THREE.BufferGeometry();
geom.setAttribute(
"position",
new THREE.Float32BufferAttribute(position, 3)
);
return geom;
}, [position]);
useFrame(({clock}, delta) => {
if (!initialized) return;
pointsRef.current.position.y += 0.03 * delta * 144;
pointsRef.current.position.z += 0.06 * delta * 144;
if(pointsRef.current.position.y > 0.4) {
pointsRef.current.position.y = 0;
pointsRef.current.position.z = 0;
setOpacity(1);
}
if(opacity > 0) {
setOpacity((opacity) => opacity - 0.05 * delta * 144);
}
});
return (
<points ref={pointsRef} geometry={points}>
<pointsMaterial
size={size}
alphaMap={texture}
transparent={true}
depthWrite={false}
color={0x000000}
opacity={opacity}
toneMapped={false}
/>
</points>
);
};
+168
View File
@@ -0,0 +1,168 @@
import { FlameParticle } from "./FlameParticle";
export const FlameParticles = ({ isBoosting }) => {
if (!isBoosting) {
return null;
}
return (
<group>
{/* bottom left */}
<group position={[-0.26, 0.45, 1]}>
<FlameParticle
position={[0, 0, 0]}
png="./fire_01.png"
turboColor={0xfea347}
delay={0}
/>
<FlameParticle
position={[0, 0, 0]}
png="./fire_02.png"
turboColor={0xfea347}
delay={100}
/>
<FlameParticle
position={[0, 0, 0]}
png="./fire_01.png"
turboColor={0xfea347}
delay={200}
/>
<FlameParticle
position={[0, 0, 0]}
png="./fire_02.png"
turboColor={0xfea347}
delay={300}
/>
<FlameParticle
position={[0, 0, 0]}
png="./fire_02.png"
turboColor={0xfea347}
delay={400}
/>
<FlameParticle
position={[0, 0, 0]}
png="./fire_01.png"
turboColor={0xfea347}
delay={500}
/>
</group>
{/* bottom right */}
<group position={[0.26, 0.45, 1]}>
<FlameParticle
position={[0, 0, 0]}
png="./fire_01.png"
turboColor={0xfea347}
delay={0}
/>
<FlameParticle
position={[0, 0, 0]}
png="./fire_02.png"
turboColor={0xfea347}
delay={100}
/>
<FlameParticle
position={[0, 0, 0]}
png="./fire_01.png"
turboColor={0xfea347}
delay={200}
/>
<FlameParticle
position={[0, 0, 0]}
png="./fire_02.png"
turboColor={0xfea347}
delay={300}
/>
<FlameParticle
position={[0, 0, 0]}
png="./fire_01.png"
turboColor={0xfea347}
delay={400}
/>
<FlameParticle
position={[0, 0, 0]}
png="./fire_02.png"
turboColor={0xfea347}
delay={500}
/>
</group>
{/* top left */}
<group position={[-0.18, 0.6, 0.8]}>
<FlameParticle
position={[0, 0, 0]}
png="./fire_02.png"
turboColor={0xfea347}
delay={0}
/>
<FlameParticle
position={[0, 0, 0]}
png="./fire_01.png"
turboColor={0xfea347}
delay={100}
/>
<FlameParticle
position={[0, 0, 0]}
png="./fire_02.png"
turboColor={0xfea347}
delay={200}
/>
<FlameParticle
position={[0, 0, 0]}
png="./fire_01.png"
turboColor={0xfea347}
delay={300}
/>
<FlameParticle
position={[0, 0, 0]}
png="./fire_02.png"
turboColor={0xfea347}
delay={400}
/>
<FlameParticle
position={[0, 0, 0]}
png="./fire_01.png"
turboColor={0xfea347}
delay={500}
/>
</group>
<group position={[0.18, 0.6, 0.8]}>
<FlameParticle
position={[0, 0, 0]}
png="./fire_02.png"
turboColor={0xfea347}
delay={0}
/>
<FlameParticle
position={[0, 0, 0]}
png="./fire_01.png"
turboColor={0xfea347}
delay={100}
/>
<FlameParticle
position={[0, 0, 0]}
png="./fire_02.png"
turboColor={0xfea347}
delay={200}
/>
<FlameParticle
position={[0, 0, 0]}
png="./fire_01.png"
turboColor={0xfea347}
delay={300}
/>
<FlameParticle
position={[0, 0, 0]}
png="./fire_02.png"
turboColor={0xfea347}
delay={400}
/>
<FlameParticle
position={[0, 0, 0]}
png="./fire_01.png"
turboColor={0xfea347}
delay={500}
/>
</group>
</group>
);
};
+17 -6
View File
@@ -1,12 +1,23 @@
import { RigidBody } from "@react-three/rapier";
import { RigidBody } from '@react-three/rapier'
export const Ground = (props) => {
return (
<RigidBody type="fixed" {...props}>
<mesh transparent receiveShadow rotation={[-Math.PI/2 , 0 ,0]}>
<RigidBody
type='fixed'
{...props}
>
<mesh
transparent
receiveShadow
rotation={[-Math.PI / 2, 0, 0]}
>
<planeGeometry args={[1000, 1000, 1000]} />
<meshStandardMaterial color="yellow" opacity={0} transparent/>
<meshStandardMaterial
color='yellow'
opacity={0}
transparent
/>
</mesh>
</RigidBody>
);
};
)
}
+29 -21
View File
@@ -1,46 +1,54 @@
import { useRef } from "react";
import { useFrame } from "@react-three/fiber";
import * as THREE from 'three';
export const Particles1 = ({ turboColor, scale, ...props }) => {
const ref = useRef();
const frame = useRef(0);
const velocity = useRef({
x: -Math.random() * 0.1,
x: -Math.random() * 0.05,
y: Math.random() * 0.05,
z: Math.random() * 0.05,
z: Math.random() * 0.02,
});
const gravity = -0.003;
useFrame(() => {
frame.current += 1;
useFrame((state, delta) => {
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) {
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.1,
x: -Math.random() * 0.05,
y: Math.random() * 0.05,
z: 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}>
<boxGeometry args={[0.05, 0.1, 0.05]} />
<mesh ref={ref} position={[-0.6, 0.05, 0.5]} scale={[scale, scale * 5, scale]}>
<sphereGeometry args={[0.01, 16, 16]} />
<meshStandardMaterial
emissive={turboColor}
toneMapped={false}
emissiveIntensity={10}
emissiveIntensity={5}
/>
</mesh>
);
+29 -21
View File
@@ -1,46 +1,54 @@
import { useRef } from "react";
import { useFrame } from "@react-three/fiber";
import * as THREE from 'three';
export const Particles2 = ({ turboColor, scale, ...props }) => {
const ref = useRef();
const frame = useRef(0);
const velocity = useRef({
x: Math.random() * 0.1,
x: Math.random() * 0.05,
y: Math.random() * 0.05,
z: Math.random() * 0.05,
z: Math.random() * 0.02,
});
const gravity = -0.003;
useFrame(() => {
frame.current += 1;
useFrame((state, delta) => {
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) {
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.1,
x: Math.random() * 0.05,
y: Math.random() * 0.05,
z: 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}>
<boxGeometry args={[0.05, 0.1, 0.05]} />
<mesh ref={ref} position={[0.6, 0.05, 0.5]} scale={[scale, scale * 5, scale]}>
<sphereGeometry args={[0.01, 16, 16]} />
<meshStandardMaterial
emissive={turboColor}
toneMapped={false}
emissiveIntensity={10}
emissiveIntensity={5}
/>
</mesh>
);
+32 -25
View File
@@ -1,47 +1,54 @@
import { useRef } from "react";
import { useFrame } from "@react-three/fiber";
import { Trail } from "@react-three/drei";
import * as THREE from 'three';
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,
x: -Math.random() * 0.05,
y: Math.random() * 0.05,
z: Math.random() * 0.02,
});
const gravity = -0.003;
useFrame(() => {
frame.current += 1;
const gravity = -0.001;
useFrame((state, delta) => {
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) {
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.1,
y: Math.random() * 0.1,
z: Math.random() * 0.05,
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}>
<boxGeometry args={[0.1, 0.2, 0.1]} />
<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={50}
emissiveIntensity={5}
/>
</mesh>
);
+32 -25
View File
@@ -1,47 +1,54 @@
import { useRef } from "react";
import { useFrame } from "@react-three/fiber";
import { Trail } from "@react-three/drei";
import * as THREE from 'three';
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,
x: Math.random() * 0.05,
y: Math.random() * 0.05,
z: Math.random() * 0.02,
});
const gravity = -0.003;
useFrame(() => {
frame.current += 1;
const gravity = -0.001;
useFrame((state, delta) => {
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) {
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.1,
y: Math.random() * 0.1,
z: Math.random() * 0.05,
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}>
<boxGeometry args={[0.1, 0.1, 0.1]} />
<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={50}
emissiveIntensity={5}
/>
</mesh>
);
+291 -178
View File
@@ -1,254 +1,357 @@
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 { 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 { PointParticle } from "./PointParticle";
import { FlameParticle } from "./FlameParticle";
import { FlameParticles } from "./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 +359,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 +427,8 @@ export const PlayerController = () => {
fov={50}
ref={cam}
/>
{/* <PositionalAudio ref={engineSound} url="./sounds/engine.wav" autoplay loop distance={10}/> */}
</group>
</group>
)
}
);
};
+417
View File
@@ -0,0 +1,417 @@
import { Controls } from "../App";
import { BallCollider, RigidBody, useRapier } 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 { 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 { PointParticle } from "./PointParticle";
import { FlameParticle } from "./FlameParticle";
import { FlameParticles } from "./FlameParticles";
export const PlayerControllerAgain = () => {
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 = 45;
const boostSpeed = 70;
const acceleration = 30;
const decceleration = 50;
const damping = 90;
const MaxSteeringSpeed = 1.1;
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 cameraLerpFactor = 2;
const marioLerpFactor = 5;
const [scale, setScale] = useState(0);
let lastTime = performance.now();
useFrame(({ pointer, clock }) => {
const time = clock.getElapsedTime();
const currentTime = performance.now();
const deltaTime = (currentTime - lastTime) * 0.001;
lastTime = currentTime;
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)
);
body.current.applyImpulse(
{
x: forwardDirection.x * currentSpeed * 50 * deltaTime,
y: 0 + jumpForce.current,
z: forwardDirection.z * currentSpeed * 50 * deltaTime,
},
true
);
// ACCELERATING
if (upPressed && currentSpeed < maxSpeed) {
setCurrentSpeed(
Math.min(currentSpeed + acceleration * deltaTime, maxSpeed)
);
}
if (!upPressed) {
if (currentSpeed > 0) {
setCurrentSpeed(Math.max(currentSpeed - decceleration * deltaTime, 0));
}
if (currentSteeringSpeed > 0) {
setCurrentSteeringSpeed(
Math.max(currentSteeringSpeed - 1 * deltaTime, 0)
);
}
}
if (upPressed) {
if (currentSteeringSpeed < MaxSteeringSpeed) {
setCurrentSteeringSpeed(
Math.min(currentSteeringSpeed + 1 * deltaTime, MaxSteeringSpeed)
);
}
}
if (leftPressed && currentSpeed > 0) {
steeringAngle = currentSteeringSpeed;
targetXPosition = -camMaxOffset;
} else if (rightPressed && currentSpeed > 0) {
steeringAngle = -currentSteeringSpeed;
targetXPosition = camMaxOffset;
} else {
steeringAngle = 0;
targetXPosition = 0;
1;
}
if (!driftLeft.current && !driftRight.current) {
steeringAngle = currentSteeringSpeed * -pointer.x;
targetXPosition = -camMaxOffset * -pointer.x;
} else if (driftLeft.current && !driftRight.current) {
steeringAngle = currentSteeringSpeed * -(pointer.x - 0.8);
targetXPosition = -camMaxOffset * -pointer.x;
} else if (driftRight.current && !driftLeft.current) {
steeringAngle = currentSteeringSpeed * -(pointer.x + 0.8);
targetXPosition = -camMaxOffset * -pointer.x;
}
kart.current.rotation.y += steeringAngle * deltaTime;
body.current.applyImpulse(
{
x: -body.current.linvel().x * damping * deltaTime,
y: 0,
z: -body.current.linvel().z * damping * deltaTime,
},
true
);
body.current.applyImpulse(
{
x: forwardDirection.x * currentSpeed * 50 * deltaTime,
y: 0 + jumpForce.current,
z: forwardDirection.z * currentSpeed * 50 * deltaTime,
},
true
);
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 += 7;
isOnFloor.current = false;
jumpIsHeld.current = true;
}
if (!isOnFloor.current && jumpForce.current > 0) {
jumpForce.current -= 1;
}
if (!jumpPressed) {
jumpIsHeld.current = false;
driftDirection.current = 0;
driftForce.current = 0;
driftLeft.current = false;
driftRight.current = false;
}
// DRIFTING
if (
jumpIsHeld.current &&
currentSteeringSpeed > 0 &&
pointer.x < -0.1 &&
!driftRight.current
) {
driftLeft.current = true;
}
if (
jumpIsHeld.current &&
currentSteeringSpeed > 0 &&
pointer.x > 0.1 &&
!driftLeft.current
) {
driftRight.current = true;
}
if (driftLeft.current) {
driftDirection.current = 1;
driftForce.current = 0.15;
mario.current.rotation.y = THREE.MathUtils.lerp(
mario.current.rotation.y,
steeringAngle * 0.5,
marioLerpFactor * deltaTime
);
accumulatedDriftPower.current += 10 * (steeringAngle + 1) * deltaTime;
}
if (driftRight.current) {
driftDirection.current = -1;
driftForce.current = 0.15;
mario.current.rotation.y = THREE.MathUtils.lerp(
mario.current.rotation.y,
-(-steeringAngle) * 0.5,
marioLerpFactor * deltaTime
);
accumulatedDriftPower.current += 10 * (-steeringAngle + 1) * deltaTime;
}
// console.log(steeringAngle)
if (!driftLeft.current && !driftRight.current) {
mario.current.rotation.y = THREE.MathUtils.lerp(
mario.current.rotation.y,
steeringAngle * 0.2,
marioLerpFactor * deltaTime
);
setScale(0);
accumulatedDriftPower.current = 0;
setTurboColor(0xffffff);
}
if (accumulatedDriftPower.current > blueTurboThreshold) {
setTurboColor(0x00ffff);
boostDuration.current = 50;
}
if (accumulatedDriftPower.current > orangeTurboThreshold) {
setTurboColor(0xffcf00);
boostDuration.current = 100;
}
if (accumulatedDriftPower.current > purpleTurboThreshold) {
setTurboColor(0xff00ff);
boostDuration.current = 250;
}
if (driftLeft.current || driftRight.current) {
const oscillation = Math.sin(time * 1000) * 0.1;
const vibration = oscillation + 0.9;
if (turboColor === 0xffffff) {
setScale(vibration * 0.8);
} else {
setScale(vibration);
}
}
// RELEASING DRIFT
if (isBoosting) {
setCurrentSpeed(boostSpeed);
boostDuration.current -= deltaTime * 200;
targetZPosition = 10;
if (boostDuration.current <= 0) {
setIsBoosting(false);
targetZPosition = 8;
}
} else if (boostDuration.current > 0 && !jumpIsHeld.current) {
setIsBoosting(true);
}
if (!isBoosting && currentSpeed === boostSpeed) {
setCurrentSpeed(maxSpeed);
}
if (!isBoosting) {
if (upPressed && currentSpeed < maxSpeed) {
setCurrentSpeed(Math.min(currentSpeed + acceleration * deltaTime, maxSpeed));
} else if (!upPressed && currentSpeed > 0) {
setCurrentSpeed(Math.max(currentSpeed - decceleration * deltaTime, 0));
}
}
// Debug logging
// console.log(`Speed: ${currentSpeed}, Boosting: ${isBoosting}, Boost Duration: ${boostDuration.current}`);
// CAMERA WORK
cam.current.position.x = THREE.MathUtils.lerp(
cam.current.position.x,
targetXPosition,
cameraLerpFactor * deltaTime
);
cam.current.position.z = THREE.MathUtils.lerp(
cam.current.position.z,
targetZPosition,
cameraLerpFactor * deltaTime
);
cam.current.updateMatrixWorld();
setSteeringAngleWheels(steeringAngle * 0.1);
//misc / debug
// SOUND WORK
});
return (
<group>
<RigidBody
ref={body}
colliders={false}
position={[8, 20, -96]}
centerOfMass={[0, -1, 0]}
mass={3}
>
<BallCollider
args={[0.5]}
mass={3}
onCollisionEnter={(event) => {
isOnFloor.current = true;
}}
/>
onCollisionEnter=
{(event) => {
isOnFloor.current = false;
}}
</RigidBody>
<group ref={kart} rotation={[0, Math.PI / 2, 0]}>
<group ref={mario}>
<Mario
currentSpeed={currentSpeed}
steeringAngleWheels={steeringAngleWheels}
/>
<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]} />
<meshStandardMaterial
emissive={turboColor}
toneMapped={false}
emissiveIntensity={100}
transparent
opacity={0.4}
/>
</mesh>
<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]} />
<meshStandardMaterial
emissive={turboColor}
toneMapped={false}
emissiveIntensity={100}
transparent
opacity={0.4}
/>
</mesh>
{/* <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}
/>
<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}
/>
</group>
{/* <ContactShadows frames={1} /> */}
<PerspectiveCamera
makeDefault
position={[0, 2, 8]}
fov={40}
ref={cam}
/>
{/* <PositionalAudio ref={engineSound} url="./sounds/engine.wav" autoplay loop distance={10}/> */}
</group>
</group>
);
};
+49
View File
@@ -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>
);
};
+68
View File
@@ -0,0 +1,68 @@
import { Euler, Object3D, BackSide, Vector3 } from "three";
import { useRef, useLayoutEffect } from "react";
import { useFrame } from "@react-three/fiber";
import { useStore } from "./store";
const o = new Object3D();
export function Skid({ count = 500, opacity = 1, size = 0.4 }) {
const ref = useRef(null);
const [bodyPosition, bodyRotation] = useStore((state) => [
state.bodyPosition,
state.bodyRotation,
]);
let index = 0;
useFrame(() => {
// console.log(bodyPosition, bodyRotation);
if (ref.current && bodyPosition && bodyRotation !== undefined) {
setItemAt(ref.current, bodyPosition, bodyRotation, index++);
if (index === count) index = 0;
}
});
useLayoutEffect(() => {
if (ref.current) {
ref.current.geometry.rotateX(-Math.PI / 2);
return () => {
ref.current.geometry.rotateX(Math.PI / 2);
};
}
});
return (
<instancedMesh ref={ref} args={[undefined, undefined, count]}>
<planeGeometry args={[size, size * 2]} />
<meshBasicMaterial
color={0x000000}
transparent
opacity={opacity}
depthWrite={false}
side={BackSide}
/>
</instancedMesh>
);
}
function setItemAt(instances, bodyPosition, bodyRotation, index) {
// Calculate the backward offset
const backwardOffset = 0.5; // Adjust this value as needed
const forwardDirection = new Vector3(
-Math.sin(bodyRotation),
0,
-Math.cos(bodyRotation)
);
const backwardPosition = forwardDirection
.multiplyScalar(-backwardOffset)
.add(bodyPosition);
// Apply the offset to position the skid marks behind the body
console.log(bodyPosition);
o.position.copy(bodyPosition.x, bodyPosition.y + 2, bodyPosition.z);
o.rotation.set(0, bodyRotation, 0);
o.scale.setScalar(1);
o.updateMatrix();
instances.setMatrixAt(index, o.matrix);
instances.instanceMatrix.needsUpdate = true;
}
+98 -11
View File
@@ -4,34 +4,121 @@ Command: npx gltfjsx@6.2.16 .\mariokarttest.glb --shadows
*/
import React, { useRef } from 'react'
import { useGLTF } from '@react-three/drei'
import { Cylinder, OrbitControls, Sphere, useGLTF } from '@react-three/drei'
import { useFrame } from '@react-three/fiber'
import FakeGlowMaterial from '../FakeGlow/FakeGlowMaterial'
import FakeFlame from '../FakeFlame/FakeFlame'
export function Mario({currentSpeed, steeringAngleWheels, ...props}) {
export function Mario({ currentSpeed, steeringAngleWheels, isBoosting, ...props }) {
const { nodes, materials } = useGLTF('./models/mariokarttest.glb')
const frontLeftWheel = useRef()
const frontRightWheel = useRef()
const rearWheels = useRef()
const frontWheels = useRef()
const [scale, setScale] = React.useState(1)
// isBoosting = true;
useFrame(() => {
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.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
{...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} />
<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>
)
}
+44 -29
View File
@@ -1,33 +1,48 @@
import { create } from "zustand";
export const useStore = create((set, get) => ({
return : {
particles1: [],
particles2: [],
actions : {
addParticle1: (particle) => {
set((state) => ({
particles1: [...state.particles1, particle],
}));
},
removeParticle1: (particle) => {
set((state) => ({
particles1: state.particles1.filter((p) => p.id !== particle.id),
}));
},
addParticle2: (particle) => {
set((state) => ({
particles2: [...state.particles2, particle],
}));
},
removeParticle2: (particle) => {
set((state) => ({
particles2: state.particles2.filter((p) => p.id !== particle.id),
}));
},
particles1: [],
particles2: [],
bodyPosition: [0, 0, 0],
bodyRotation: [0, 0, 0],
pastPositions: [],
addPastPosition: (position) => {
set((state) => ({
pastPositions: [position, ...state.pastPositions.slice(0, 499)],
}));
},
actions: {
addParticle1: (particle) => {
set((state) => ({
particles1: [...state.particles1, particle],
}));
},
}
}));
removeParticle1: (particle) => {
set((state) => ({
particles1: state.particles1.filter((p) => p.id !== particle.id),
}));
},
addParticle2: (particle) => {
set((state) => ({
particles2: [...state.particles2, particle],
}));
},
removeParticle2: (particle) => {
set((state) => ({
particles2: state.particles2.filter((p) => p.id !== particle.id),
}));
},
setBodyPosition: (position) => {
set({ bodyPosition: position });
},
setBodyRotation: (rotation) => {
set({ bodyRotation: rotation });
},
getBodyPosition: () => {
return get().bodyPosition;
},
getBodyRotation: () => {
return get().bodyRotation;
},
},
}));
+54
View File
@@ -3,6 +3,60 @@
height: 100vh;
}
*
body {
margin: 0;
/* cursor:none; */
overflow-y: none;
overflow-x: none;
}
body::-webkit-scrollbar {
display: none;
}
.wheel{
display: none;
position:absolute;
top:0;
opacity: 0.2;
img{
width: 200px;
}
}
.overlay{
position:absolute;
top:0;
left:0;
width:100vw;
height:100vh;
pointer-events: none;
}
.logo{
position:absolute;
top:150px;
left:500px;
opacity: 1;
img{
width: 600px;
animation: bounce 0.4s infinite cubic-bezier(.71,1.94,.5,.61)
}
}
@keyframes bounce {
0%, 100% {
transform: scale(1);
}
50% {
transform: scale(1.2);
}
}
+2
View File
@@ -2,9 +2,11 @@ import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
import './index.css'
import { HUD } from './HUD'
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<App />
{/* <HUD /> */}
</React.StrictMode>,
)