Fixed FakeGlowMaterial

+Added Flames Material :)
skidmarks
Anderson Mancini 2024-01-24 09:40:02 -03:00
parent 2753ec7127
commit 6232bf9498
4 changed files with 446 additions and 277 deletions

View File

@ -0,0 +1,152 @@
/**
* 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 }) {
const FakeFlame = useMemo(() => {
return shaderMaterial(
{
falloffAmount: falloff,
glowInternalRadius: glowInternalRadius,
glowColor: new Color(glowColor),
glowSharpness: glowSharpness,
time: 0
},
/*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.25;
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 - 1.8, position.y) * 2.) * sin(time * 2.);
modelPosition.z += sin(smoothstep(0., vUv.x - 0.8, position.z) * 2.) * sin(time * 2.) * .6;
gl_Position = projectionMatrix * viewMatrix * modelPosition;
vUv = uv;
}`,
/*GLSL */
`
uniform vec3 glowColor;
uniform float falloffAmount;
uniform float glowSharpness;
uniform float glowInternalRadius;
uniform float time;
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;
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
gl_FragColor = vec4( col, 1.0);
#include <tonemapping_fragment>
#include <colorspace_fragment>
}`
)
}, [falloff, glowInternalRadius, glowColor, glowSharpness])
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}
/>
)
}

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 { shaderMaterial } from '@react-three/drei'
import { extend, useFrame } from '@react-three/fiber' import { extend } from '@react-three/fiber'
import { Color, BackSide, AdditiveBlending } from 'three' 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(() => { const FakeGlowMaterial = useMemo(() => {
return shaderMaterial( return shaderMaterial(
{ {
time: 0, falloffAmount: falloff,
glowCenter: glowCenter, glowInternalRadius: glowInternalRadius,
edgeIntensity: edgeIntensity,
glowColor: new Color(glowColor), glowColor: new Color(glowColor),
glowOpacity: glowOpacity, glowSharpness: glowSharpness
fresnelOpacity: fresnelOpacity,
fresnelAmount: fresnelAmount
}, },
/*GLSL */ /*GLSL */
` `
uniform float glowCenter; varying vec3 vPosition;
uniform float edgeIntensity;
varying float intensity;
varying vec3 vNormel;
varying vec3 vNormal; varying vec3 vNormal;
uniform float fresnelOpacity;
uniform float fresnelAmount;
void main() { void main() {
vec3 viewVector = normalize(vec3(cameraPosition-position)); vec4 modelPosition = modelMatrix * vec4(position, 1.0);
float fresnelEffect = dot(vNormel, vNormal) * ( fresnelOpacity); gl_Position = projectionMatrix * viewMatrix * modelPosition;
fresnelEffect = clamp(fresnelAmount - fresnelEffect, 0.5, fresnelOpacity); vec4 modelNormal = modelMatrix * vec4(normal, 0.0);
vec3 vNormal = normalize( normalMatrix * normal ); vPosition = modelPosition.xyz;
vec3 vNormel = normalize( normalMatrix * viewVector ); vNormal = modelNormal.xyz;
intensity = pow( glowCenter - dot(vNormal, vNormel), edgeIntensity / fresnelEffect );
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}`, }`,
/*GLSL */ /*GLSL */
` `
uniform vec3 glowColor; uniform vec3 glowColor;
varying float intensity; uniform float falloffAmount;
uniform float glowOpacity; uniform float glowSharpness;
uniform float fresnelOpacity; uniform float glowInternalRadius;
uniform float fresnelAmount;
varying vec3 vNormel; varying vec3 vPosition;
varying vec3 vNormal; varying vec3 vNormal;
uniform float glowCenter;
uniform float edgeIntensity;
void main() void main()
{ {
vec3 glow = glowColor * intensity; // Normal
float fresnelEffect = - dot(vNormel, vNormal); vec3 normal = normalize(vNormal);
fresnelEffect = clamp(fresnelEffect, 0.1, 1.0); if(!gl_FrontFacing){ normal *= - 1.0; }
gl_FragColor = vec4( clamp(glow, 0., 1.0), clamp(glowOpacity - intensity * fresnelEffect, 0., 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 }) extend({ FakeGlowMaterial })
useFrame((state, delta) => {
ref.current.time += delta
})
const ref = useRef()
return ( return (
<fakeGlowMaterial <fakeGlowMaterial
wireframe={wireframe}
key={FakeGlowMaterial.key} key={FakeGlowMaterial.key}
side={BackSide} side={DoubleSide}
transparent={true} transparent={true}
blending={AdditiveBlending} blending={AdditiveBlending}
depthTest={false} depthTest={false}
ref={ref}
/> />
) )
} }

View File

@ -1,310 +1,246 @@
import { Controls } from "../App"; import { Controls } from '../App'
import { BallCollider, RigidBody, useRapier } from "@react-three/rapier"; import { BallCollider, RigidBody, useRapier } from '@react-three/rapier'
import { import { useKeyboardControls, PerspectiveCamera, ContactShadows, Sphere, OrbitControls, Trail, PositionalAudio } from '@react-three/drei'
useKeyboardControls, import { useFrame, useThree } from '@react-three/fiber'
PerspectiveCamera, import { useRef, useState, useEffect, useCallback } from 'react'
ContactShadows, import * as THREE from 'three'
Sphere, import { Model } from './models/Racing_kart'
OrbitControls, import { FrontRightWheel } from './models/Front_Right_Wheel'
Trail, import { FrontLeftWheel } from './models/Front_Left_Wheel'
PositionalAudio, import { RearWheels } from './models/Rear_wheels'
} from "@react-three/drei"; import gsap from 'gsap'
import { useFrame, useThree } from "@react-three/fiber"; import { Mario } from './models/Mario_kart'
import { useRef, useState, useEffect, useCallback } from "react"; import { Particles1 } from './Particles1'
import * as THREE from "three"; import { DriftParticlesLeft } from './DriftParticlesLeft'
import { Model } from "./models/Racing_kart"; import { DriftParticlesRight } from './DriftParticlesRight'
import { FrontRightWheel } from "./models/Front_Right_Wheel"; import FakeGlowMaterial from './FakeGlow/FakeGlowMaterial'
import { FrontLeftWheel } from "./models/Front_Left_Wheel"; import { PointParticle } from './PointParticle'
import { RearWheels } from "./models/Rear_wheels"; import { FlameParticle } from './FlameParticle'
import gsap from "gsap"; import { FlameParticles } from './FlameParticles'
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 PlayerController = () => { export const PlayerController = () => {
const upPressed = useKeyboardControls((state) => state[Controls.up]); const upPressed = useKeyboardControls((state) => state[Controls.up])
const downPressed = useKeyboardControls((state) => state[Controls.down]); const downPressed = useKeyboardControls((state) => state[Controls.down])
const leftPressed = useKeyboardControls((state) => state[Controls.left]); const leftPressed = useKeyboardControls((state) => state[Controls.left])
const rightPressed = useKeyboardControls((state) => state[Controls.right]); const rightPressed = useKeyboardControls((state) => state[Controls.right])
const jumpPressed = useKeyboardControls((state) => state[Controls.jump]); const jumpPressed = useKeyboardControls((state) => state[Controls.jump])
const [isOnGround, setIsOnGround] = useState(false); const [isOnGround, setIsOnGround] = useState(false)
const body = useRef(); const body = useRef()
const kart = useRef(); const kart = useRef()
const cam = useRef(); const cam = useRef()
const initialSpeed = 0; const initialSpeed = 0
const maxSpeed = 30; const maxSpeed = 30
const boostSpeed = 50; const boostSpeed = 50
const acceleration = 0.1; const acceleration = 0.1
const decceleration = 0.2; const decceleration = 0.2
const damping = -0.1; const damping = -0.1
const MaxSteeringSpeed = 0.01; const MaxSteeringSpeed = 0.01
const [currentSteeringSpeed, setCurrentSteeringSpeed] = useState(0); const [currentSteeringSpeed, setCurrentSteeringSpeed] = useState(0)
const [currentSpeed, setCurrentSpeed] = useState(initialSpeed); const [currentSpeed, setCurrentSpeed] = useState(initialSpeed)
const camMaxOffset = 1; const camMaxOffset = 1
let steeringAngle = 0; let steeringAngle = 0
const isOnFloor = useRef(false); const isOnFloor = useRef(false)
const jumpForce = useRef(0); const jumpForce = useRef(0)
const jumpIsHeld = useRef(false); const jumpIsHeld = useRef(false)
const driftDirection = useRef(0); const driftDirection = useRef(0)
const driftLeft = useRef(false); const driftLeft = useRef(false)
const driftRight = useRef(false); const driftRight = useRef(false)
const driftForce = useRef(0); const driftForce = useRef(0)
const mario = useRef(); const mario = useRef()
const accumulatedDriftPower = useRef(0); const accumulatedDriftPower = useRef(0)
const blueTurboThreshold = 10; const blueTurboThreshold = 10
const orangeTurboThreshold = 30; const orangeTurboThreshold = 30
const purpleTurboThreshold = 60; const purpleTurboThreshold = 60
const [turboColor, setTurboColor] = useState(0xffffff); const [turboColor, setTurboColor] = useState(0xffffff)
const boostDuration = useRef(0); const boostDuration = useRef(0)
const [isBoosting, setIsBoosting] = useState(false); const [isBoosting, setIsBoosting] = useState(false)
let targetXPosition = 0; let targetXPosition = 0
let targetZPosition = 8; let targetZPosition = 8
const [steeringAngleWheels, setSteeringAngleWheels] = useState(0); const [steeringAngleWheels, setSteeringAngleWheels] = useState(0)
const engineSound = useRef(); const engineSound = useRef()
const [scale, setScale] = useState(0); const [scale, setScale] = useState(0)
useFrame(({ pointer, clock }, delta) => { useFrame(({ pointer, clock }, delta) => {
const time = clock.getElapsedTime(); const time = clock.getElapsedTime()
if (!body.current && !mario.current) return; if (!body.current && !mario.current) return
// HANDLING AND STEERING // HANDLING AND STEERING
const kartRotation = const kartRotation = kart.current.rotation.y - driftDirection.current * driftForce.current
kart.current.rotation.y - driftDirection.current * driftForce.current; const forwardDirection = new THREE.Vector3(-Math.sin(kartRotation), 0, -Math.cos(kartRotation))
const forwardDirection = new THREE.Vector3(
-Math.sin(kartRotation),
0,
-Math.cos(kartRotation)
);
if (leftPressed && currentSpeed > 0) { if (leftPressed && currentSpeed > 0) {
steeringAngle = currentSteeringSpeed; steeringAngle = currentSteeringSpeed
targetXPosition = -camMaxOffset; targetXPosition = -camMaxOffset
} else if (rightPressed && currentSpeed > 0) { } else if (rightPressed && currentSpeed > 0) {
steeringAngle = -currentSteeringSpeed; steeringAngle = -currentSteeringSpeed
targetXPosition = camMaxOffset; targetXPosition = camMaxOffset
} else { } else {
steeringAngle = 0; steeringAngle = 0
targetXPosition = 0; targetXPosition = 0
1; 1
} }
// mouse steering // mouse steering
if (!driftLeft.current && !driftRight.current) {
if(!driftLeft.current && !driftRight.current){ steeringAngle = currentSteeringSpeed * -pointer.x
steeringAngle = currentSteeringSpeed * -pointer.x; targetXPosition = -camMaxOffset * -pointer.x
targetXPosition = -camMaxOffset * -pointer.x; } else if (driftLeft.current && !driftRight.current) {
} steeringAngle = currentSteeringSpeed * -(pointer.x - 0.5)
targetXPosition = -camMaxOffset * -pointer.x
else if (driftLeft.current && !driftRight.current) { } else if (driftRight.current && !driftLeft.current) {
steeringAngle = currentSteeringSpeed * -(pointer.x - 0.5); steeringAngle = currentSteeringSpeed * -(pointer.x + 0.5)
targetXPosition = -camMaxOffset * -pointer.x; targetXPosition = -camMaxOffset * -pointer.x
}
else if (driftRight.current && !driftLeft.current) {
steeringAngle = currentSteeringSpeed * -(pointer.x + 0.5);
targetXPosition = -camMaxOffset * -pointer.x;
} }
// ACCELERATING // ACCELERATING
if (upPressed && currentSpeed < maxSpeed) { if (upPressed && currentSpeed < maxSpeed) {
// Accelerate the kart within the maximum speed limit // Accelerate the kart within the maximum speed limit
setCurrentSpeed(Math.min(currentSpeed + acceleration * delta * 144, maxSpeed)); setCurrentSpeed(Math.min(currentSpeed + acceleration * delta * 144, maxSpeed))
} else if ( } else if (upPressed && currentSpeed > maxSpeed && boostDuration.current > 0) {
upPressed && setCurrentSpeed(Math.max(currentSpeed - decceleration * delta * 144, maxSpeed))
currentSpeed > maxSpeed &&
boostDuration.current > 0
) {
setCurrentSpeed(Math.max(currentSpeed - decceleration * delta * 144, maxSpeed));
} }
if (upPressed) { if (upPressed) {
if (currentSteeringSpeed < MaxSteeringSpeed) { if (currentSteeringSpeed < MaxSteeringSpeed) {
setCurrentSteeringSpeed( setCurrentSteeringSpeed(Math.min(currentSteeringSpeed + 0.0001 * delta * 144, MaxSteeringSpeed))
Math.min(currentSteeringSpeed + 0.0001 * delta * 144, MaxSteeringSpeed)
);
} }
} }
// REVERSING // REVERSING
if (downPressed && currentSpeed < -maxSpeed) { if (downPressed && currentSpeed < -maxSpeed) {
setCurrentSpeed(Math.max(currentSpeed - acceleration * delta * 144, -maxSpeed)); setCurrentSpeed(Math.max(currentSpeed - acceleration * delta * 144, -maxSpeed))
} }
// DECELERATING // DECELERATING
else if (!upPressed && !downPressed) { else if (!upPressed && !downPressed) {
if (currentSteeringSpeed > 0) { if (currentSteeringSpeed > 0) {
setCurrentSteeringSpeed(Math.max(currentSteeringSpeed - 0.00005 * delta * 144, 0)); setCurrentSteeringSpeed(Math.max(currentSteeringSpeed - 0.00005 * delta * 144, 0))
} else if (currentSteeringSpeed < 0) { } else if (currentSteeringSpeed < 0) {
setCurrentSteeringSpeed(Math.min(currentSteeringSpeed + 0.00005 * delta * 144, 0)); setCurrentSteeringSpeed(Math.min(currentSteeringSpeed + 0.00005 * delta * 144, 0))
} }
setCurrentSpeed(Math.max(currentSpeed - decceleration * delta * 144, 0)); setCurrentSpeed(Math.max(currentSpeed - decceleration * delta * 144, 0))
} }
// Update the kart's rotation based on the steering angle // Update the kart's rotation based on the steering angle
kart.current.rotation.y += steeringAngle * delta * 144; kart.current.rotation.y += steeringAngle * delta * 144
// Apply damping to simulate slowdown when no keys are pressed // Apply damping to simulate slowdown when no keys are pressed
body.current.applyImpulse( body.current.applyImpulse(
{ {
x: -body.current.linvel().x * (1 - damping) * delta * 144, x: -body.current.linvel().x * (1 - damping) * delta * 144,
y: 0, y: 0,
z: -body.current.linvel().z * (1 - damping) * delta * 144, z: -body.current.linvel().z * (1 - damping) * delta * 144
}, },
true true
); )
const bodyPosition = body.current.translation(); const bodyPosition = body.current.translation()
kart.current.position.set( kart.current.position.set(bodyPosition.x, bodyPosition.y - 0.5, bodyPosition.z)
bodyPosition.x,
bodyPosition.y - 0.5,
bodyPosition.z
);
// JUMPING // JUMPING
if (jumpPressed && isOnFloor.current && !jumpIsHeld.current) { if (jumpPressed && isOnFloor.current && !jumpIsHeld.current) {
jumpForce.current += 10 ; jumpForce.current += 10
isOnFloor.current = false; isOnFloor.current = false
jumpIsHeld.current = true; jumpIsHeld.current = true
} }
if (!isOnFloor.current && jumpForce.current > 0) { if (!isOnFloor.current && jumpForce.current > 0) {
jumpForce.current -= 1 * delta * 144; jumpForce.current -= 1 * delta * 144
} }
if (!jumpPressed) { if (!jumpPressed) {
jumpIsHeld.current = false; jumpIsHeld.current = false
driftDirection.current = 0; driftDirection.current = 0
driftForce.current = 0; driftForce.current = 0
driftLeft.current = false; driftLeft.current = false
driftRight.current = false; driftRight.current = false
} }
// DRIFTING // DRIFTING
if ( if (jumpIsHeld.current && currentSteeringSpeed > 0 && pointer.x < -0.1 && !driftRight.current) {
jumpIsHeld.current && driftLeft.current = true
currentSteeringSpeed > 0 &&
pointer.x < -0.1 &&
!driftRight.current
) {
driftLeft.current = true;
} }
if ( if (jumpIsHeld.current && currentSteeringSpeed > 0 && pointer.x > 0.1 && !driftLeft.current) {
jumpIsHeld.current && driftRight.current = true
currentSteeringSpeed > 0 &&
pointer.x > 0.1 &&
!driftLeft.current
) {
driftRight.current = true;
} }
if (!jumpIsHeld.current && !driftLeft.current && !driftRight.current) { if (!jumpIsHeld.current && !driftLeft.current && !driftRight.current) {
mario.current.rotation.y = THREE.MathUtils.lerp( mario.current.rotation.y = THREE.MathUtils.lerp(mario.current.rotation.y, 0, 0.0001 * delta * 144)
mario.current.rotation.y, setTurboColor(0xffffff)
0, accumulatedDriftPower.current = 0
0.0001 * delta * 144
);
setTurboColor(0xffffff);
accumulatedDriftPower.current = 0;
} }
if (driftLeft.current) { if (driftLeft.current) {
driftDirection.current = 1; driftDirection.current = 1
driftForce.current = 0.4; driftForce.current = 0.4
mario.current.rotation.y = THREE.MathUtils.lerp( mario.current.rotation.y = THREE.MathUtils.lerp(mario.current.rotation.y, steeringAngle * 50 + 0.5, 0.05 * delta * 144)
mario.current.rotation.y, accumulatedDriftPower.current += 0.1 * (steeringAngle + 1) * delta * 144
steeringAngle * 50 + 0.5,
0.05 * delta * 144
);
accumulatedDriftPower.current += 0.1 * (steeringAngle + 1) * delta * 144;
} }
if (driftRight.current) { if (driftRight.current) {
driftDirection.current = -1; driftDirection.current = -1
driftForce.current = 0.4; driftForce.current = 0.4
mario.current.rotation.y = THREE.MathUtils.lerp( mario.current.rotation.y = THREE.MathUtils.lerp(mario.current.rotation.y, -(-steeringAngle * 50 + 0.5), 0.05 * delta * 144)
mario.current.rotation.y, accumulatedDriftPower.current += 0.1 * (-steeringAngle + 1) * delta * 144
-(-steeringAngle * 50 + 0.5),
0.05 * delta * 144
);
accumulatedDriftPower.current += 0.1 * (-steeringAngle + 1) * delta * 144 ;
} }
if (!driftLeft.current && !driftRight.current) { if (!driftLeft.current && !driftRight.current) {
mario.current.rotation.y = THREE.MathUtils.lerp( mario.current.rotation.y = THREE.MathUtils.lerp(mario.current.rotation.y, steeringAngle * 30, 0.05 * delta * 144)
mario.current.rotation.y, setScale(0)
steeringAngle * 30,
0.05 * delta * 144
);
setScale(0);
} }
if (accumulatedDriftPower.current > blueTurboThreshold) { if (accumulatedDriftPower.current > blueTurboThreshold) {
setTurboColor(0x00ffff); setTurboColor(0x00ffff)
boostDuration.current = 50; boostDuration.current = 50
} }
if (accumulatedDriftPower.current > orangeTurboThreshold) { if (accumulatedDriftPower.current > orangeTurboThreshold) {
setTurboColor(0xffcf00); setTurboColor(0xffcf00)
boostDuration.current = 100; boostDuration.current = 100
} }
if (accumulatedDriftPower.current > purpleTurboThreshold) { if (accumulatedDriftPower.current > purpleTurboThreshold) {
setTurboColor(0xff00ff); setTurboColor(0xff00ff)
boostDuration.current = 250; boostDuration.current = 250
} }
if (driftLeft.current || driftRight.current) { 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;
if (turboColor === 0xffffff) { if (turboColor === 0xffffff) {
setScale(vibration * 0.8); setScale(vibration * 0.8)
} else { } else {
setScale(vibration); setScale(vibration)
} }
} }
// RELEASING DRIFT // RELEASING DRIFT
if (boostDuration.current > 1 && !jumpIsHeld.current) { if (boostDuration.current > 1 && !jumpIsHeld.current) {
setCurrentSpeed(boostSpeed); setCurrentSpeed(boostSpeed)
boostDuration.current -= 1 * delta * 144; boostDuration.current -= 1 * delta * 144
targetZPosition = 10; targetZPosition = 10
setIsBoosting(true); setIsBoosting(true)
} else if (boostDuration.current <= 1 ) { } else if (boostDuration.current <= 1) {
targetZPosition = 8; targetZPosition = 8
setIsBoosting(false); setIsBoosting(false)
} }
// CAMERA WORK // CAMERA WORK
cam.current.updateMatrixWorld(); cam.current.updateMatrixWorld()
cam.current.position.x = THREE.MathUtils.lerp( cam.current.position.x = THREE.MathUtils.lerp(cam.current.position.x, targetXPosition, 0.01 * delta * 144)
cam.current.position.x,
targetXPosition,
0.01 * delta * 144
);
cam.current.position.z = THREE.MathUtils.lerp( cam.current.position.z = THREE.MathUtils.lerp(cam.current.position.z, targetZPosition, 0.01 * delta * 144)
cam.current.position.z,
targetZPosition,
0.01 * delta * 144
);
body.current.applyImpulse( body.current.applyImpulse(
{ {
x: forwardDirection.x * currentSpeed * delta * 144, x: forwardDirection.x * currentSpeed * delta * 144,
y: 0 + jumpForce.current * delta * 144, y: 0 + jumpForce.current * delta * 144,
z: forwardDirection.z * currentSpeed * delta * 144, z: forwardDirection.z * currentSpeed * delta * 144
}, },
true true
); )
// Update the kart's rotation based on the steering angle // Update the kart's rotation based on the steering angle
setSteeringAngleWheels(steeringAngle * 25); setSteeringAngleWheels(steeringAngle * 25)
// SOUND WORK // SOUND WORK
// console.log(body.current.translation())
console.log(body.current.translation()) })
});
return ( return (
<group> <group>
@ -319,16 +255,19 @@ export const PlayerController = () => {
args={[0.5]} args={[0.5]}
mass={3} mass={3}
onCollisionEnter={(event) => { onCollisionEnter={(event) => {
isOnFloor.current = true; isOnFloor.current = true
}} }}
/> />
onCollisionEnter= onCollisionEnter=
{(event) => { {(event) => {
isOnFloor.current = false; isOnFloor.current = false
}} }}
</RigidBody> </RigidBody>
<group ref={kart} rotation={[0, Math.PI / 2, 0]}> <group
ref={kart}
rotation={[0, Math.PI / 2, 0]}
>
<group ref={mario}> <group ref={mario}>
<Mario <Mario
currentSpeed={currentSpeed} currentSpeed={currentSpeed}
@ -341,7 +280,10 @@ export const PlayerController = () => {
distance={1} distance={1}
/> />
<mesh position={[0.6, 0.05, 0.5]} scale={scale}> <mesh
position={[0.6, 0.05, 0.5]}
scale={scale}
>
<sphereGeometry args={[0.1, 16, 16]} /> <sphereGeometry args={[0.1, 16, 16]} />
<meshStandardMaterial <meshStandardMaterial
emissive={turboColor} emissive={turboColor}
@ -357,7 +299,10 @@ export const PlayerController = () => {
color={turboColor} color={turboColor}
distance={1} distance={1}
/> />
<mesh position={[-0.6, 0.05, 0.5]} scale={scale}> <mesh
position={[-0.6, 0.05, 0.5]}
scale={scale}
>
<sphereGeometry args={[0.1, 16, 16]} /> <sphereGeometry args={[0.1, 16, 16]} />
<meshStandardMaterial <meshStandardMaterial
emissive={turboColor} emissive={turboColor}
@ -368,13 +313,35 @@ export const PlayerController = () => {
/> />
</mesh> </mesh>
{/* <Flame/> */} {/* <Flame/> */}
<FlameParticles isBoosting={isBoosting}/> <FlameParticles isBoosting={isBoosting} />
<DriftParticlesLeft turboColor={turboColor} scale={scale} /> <DriftParticlesLeft
<DriftParticlesRight turboColor={turboColor} scale={scale} /> turboColor={turboColor}
<PointParticle position={[-0.6, 0.05, 0.5]} png="./circle.png" 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="./star.png" turboColor={turboColor}/> <DriftParticlesRight
<PointParticle position={[0.6, 0.05, 0.5]} png="./star.png" turboColor={turboColor}/> 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> </group>
{/* <ContactShadows frames={1} /> */} {/* <ContactShadows frames={1} /> */}
@ -385,8 +352,7 @@ export const PlayerController = () => {
ref={cam} ref={cam}
/> />
{/* <PositionalAudio ref={engineSound} url="./sounds/engine.wav" autoplay loop distance={10}/> */} {/* <PositionalAudio ref={engineSound} url="./sounds/engine.wav" autoplay loop distance={10}/> */}
</group> </group>
</group> </group>
); )
}; }

View File

@ -4,10 +4,12 @@ Command: npx gltfjsx@6.2.16 .\mariokarttest.glb --shadows
*/ */
import React, { useRef } from 'react' 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 { 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, ...props }) {
const { nodes, materials } = useGLTF('./models/mariokarttest.glb') const { nodes, materials } = useGLTF('./models/mariokarttest.glb')
const frontLeftWheel = useRef() const frontLeftWheel = useRef()
@ -21,17 +23,75 @@ export function Mario({currentSpeed, steeringAngleWheels, ...props}) {
frontRightWheel.current.rotation.x += rotation frontRightWheel.current.rotation.x += rotation
rearWheels.current.rotation.x += rotation rearWheels.current.rotation.x += rotation
frontWheels.current.rotation.y = steeringAngleWheels frontWheels.current.rotation.y = steeringAngleWheels
}) })
return ( return (
<group {...props} rotation={[0, Math.PI, 0]} dispose={null}> <group
<mesh castShadow receiveShadow geometry={nodes.mt_kart_Mario_S.geometry} material={materials.mt_kart_Mario_S} /> {...props}
<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]} /> rotation={[0, Math.PI, 0]}
<group ref={frontWheels} > dispose={null}
<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} /> <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> </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={1.2}
>
<FakeGlowMaterial />
</Sphere>
<Cylinder
args={[0.1, 0.5, 1, 128, 64, true]}
position={[0.3, 0.6, -1.2]}
rotation={[Math.PI / 1.5, 0, 0]}
>
<FakeFlame />
</Cylinder>
<Cylinder
args={[0.1, 0.5, 1, 128, 64, true]}
position={[-0.3, 0.6, -1.2]}
rotation={[Math.PI / 1.5, 0, 0]}
>
<FakeFlame />
</Cylinder>
</group> </group>
) )
} }