Added FakeGlow Material
+default performance optomizations
This commit is contained in:
1 parent
59bc38d06e
commit
4f3e52b9d7
4 files changed
+328
-263
No files matched your search
+37
-39
@@ -1,55 +1,53 @@
|
|||||||
import { Canvas } from "@react-three/fiber";
|
import { Canvas } from '@react-three/fiber'
|
||||||
import { Experience } from "./components/Experience";
|
import { Experience } from './components/Experience'
|
||||||
import { Suspense, useMemo } from "react";
|
import { Suspense, useMemo } from 'react'
|
||||||
import { Physics } from "@react-three/rapier";
|
import { Physics } from '@react-three/rapier'
|
||||||
import {
|
import { KeyboardControls, Loader, OrbitControls, Preload, Stats } from '@react-three/drei'
|
||||||
KeyboardControls,
|
|
||||||
Loader,
|
|
||||||
OrbitControls,
|
|
||||||
Preload,
|
|
||||||
Stats,
|
|
||||||
} from "@react-three/drei";
|
|
||||||
|
|
||||||
export const Controls = {
|
export const Controls = {
|
||||||
up: "up",
|
up: 'up',
|
||||||
down: "down",
|
down: 'down',
|
||||||
left: "left",
|
left: 'left',
|
||||||
right: "right",
|
right: 'right',
|
||||||
boost: "boost",
|
boost: 'boost',
|
||||||
shoot: "shoot",
|
shoot: 'shoot',
|
||||||
slow: "slow",
|
slow: 'slow',
|
||||||
reset: "reset",
|
reset: 'reset'
|
||||||
};
|
}
|
||||||
function App() {
|
function App() {
|
||||||
|
|
||||||
|
|
||||||
const map = useMemo(
|
const map = useMemo(
|
||||||
() => [
|
() => [
|
||||||
{ name: Controls.up, keys: ["KeyW", "ArrowUp"] },
|
{ name: Controls.up, keys: ['KeyW', 'ArrowUp'] },
|
||||||
{ name: Controls.down, keys: ["KeyS", "ArrowDown"] },
|
{ name: Controls.down, keys: ['KeyS', 'ArrowDown'] },
|
||||||
{ name: Controls.left, keys: ["KeyA", "ArrowLeft"] },
|
{ name: Controls.left, keys: ['KeyA', 'ArrowLeft'] },
|
||||||
{ name: Controls.right, keys: ["KeyD", "ArrowRight"] },
|
{ name: Controls.right, keys: ['KeyD', 'ArrowRight'] },
|
||||||
{ name: Controls.jump, keys: ["Space"] },
|
{ name: Controls.jump, keys: ['Space'] },
|
||||||
{ name: Controls.slow, keys: ["Shift"] },
|
{ name: Controls.slow, keys: ['Shift'] },
|
||||||
{ name: Controls.shoot, keys: ["KeyE", "Click"] },
|
{ name: Controls.shoot, keys: ['KeyE', 'Click'] },
|
||||||
{ name: Controls.reset, keys: ["KeyR"] },
|
{ name: Controls.reset, keys: ['KeyR'] }
|
||||||
],
|
],
|
||||||
[]
|
[]
|
||||||
);
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Canvas shadows>
|
<Canvas
|
||||||
|
shadows
|
||||||
|
dpr={1}
|
||||||
|
gl={{ antialias: false, stencil: false, powerPreference: 'high-performance' }}
|
||||||
|
>
|
||||||
<Suspense fallback={null}>
|
<Suspense fallback={null}>
|
||||||
<Physics gravity={[0,-90,0]}>
|
<Physics
|
||||||
<KeyboardControls map={map}>
|
gravity={[0, -90, 0]}
|
||||||
|
predictionDistance={0.001}
|
||||||
|
>
|
||||||
|
<KeyboardControls map={map}>
|
||||||
<Experience />
|
<Experience />
|
||||||
</KeyboardControls>
|
</KeyboardControls>
|
||||||
{/* <Stats /> */}
|
{/* <Stats /> */}
|
||||||
</Physics>
|
</Physics>
|
||||||
</Suspense>
|
</Suspense>
|
||||||
|
|
||||||
</Canvas>
|
</Canvas>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default App;
|
export default App
|
||||||
@@ -1,47 +1,58 @@
|
|||||||
import {
|
import { Environment, OrbitControls, PerspectiveCamera, Lightformer } from '@react-three/drei'
|
||||||
Environment,
|
import { Ground } from './Ground'
|
||||||
OrbitControls,
|
import { RigidBody } from '@react-three/rapier'
|
||||||
PerspectiveCamera,
|
import { PlayerController } from './PlayerController'
|
||||||
Lightformer
|
import { Track } from './models/Spafrancorchamps-REALISTIC'
|
||||||
} from "@react-three/drei";
|
import { Paris } from './models/Tour_paris_promenade'
|
||||||
import { Ground } from "./Ground";
|
import { EffectComposer, N8AO, Bloom, DepthOfField, TiltShift2, HueSaturation, SMAA } from '@react-three/postprocessing'
|
||||||
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'
|
|
||||||
|
|
||||||
export const Experience = () => {
|
export const Experience = () => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<PlayerController />
|
<PlayerController />
|
||||||
<Ground position={[0, 0, 0]} />
|
<Ground position={[0, 0, 0]} />
|
||||||
<Environment resolution={256} preset='lobby'/>
|
<Environment
|
||||||
|
resolution={256}
|
||||||
|
preset='lobby'
|
||||||
|
/>
|
||||||
|
|
||||||
<directionalLight
|
<directionalLight
|
||||||
|
position={[10, 50, -30]}
|
||||||
position={[10, 50,-30]}
|
intensity={1}
|
||||||
intensity={1}
|
shadow-bias={-0.0001}
|
||||||
shadow-bias={-0.0001}
|
shadow-mapSize={[4096, 4096]}
|
||||||
shadow-mapSize={[4096, 4096]}
|
shadow-camera-left={-300}
|
||||||
shadow-camera-left={-300}
|
shadow-camera-right={300}
|
||||||
shadow-camera-right={300}
|
shadow-camera-top={300}
|
||||||
shadow-camera-top={300}
|
shadow-camera-bottom={-3000}
|
||||||
shadow-camera-bottom={-3000}
|
castShadow
|
||||||
castShadow
|
/>
|
||||||
/>
|
|
||||||
|
|
||||||
{/* <ambientLight intensity={0.2} /> */}
|
{/* <ambientLight intensity={0.2} /> */}
|
||||||
{/* <spotLight position={[10, 20, 10]} angle={0.12} penumbra={1} intensity={1} castShadow shadow-mapSize={1024} /> */}
|
{/* <spotLight position={[10, 20, 10]} angle={0.12} penumbra={1} intensity={1} castShadow shadow-mapSize={1024} /> */}
|
||||||
<Paris position={[0, 0, 0]} />
|
<Paris position={[0, 0, 0]} />
|
||||||
<EffectComposer multisampling={4}>
|
<EffectComposer
|
||||||
<SMAA/>
|
multisampling={0}
|
||||||
|
disableNormalPass
|
||||||
|
>
|
||||||
|
<SMAA />
|
||||||
{/* <N8AO distanceFalloff={1} aoRadius={1} intensity={4} /> */}
|
{/* <N8AO distanceFalloff={1} aoRadius={1} intensity={4} /> */}
|
||||||
<Bloom luminanceThreshold={0} mipmapBlur luminanceSmoothing={0.01} intensity={0.5} />
|
<Bloom
|
||||||
<DepthOfField target={[0, 0, 13]} focalLength={0.3} bokehScale={15} height={700} />
|
luminanceThreshold={0}
|
||||||
|
mipmapBlur
|
||||||
|
luminanceSmoothing={0.01}
|
||||||
|
intensity={0.5}
|
||||||
|
/>
|
||||||
|
<DepthOfField
|
||||||
|
target={[0, 0, 13]}
|
||||||
|
focalLength={0.3}
|
||||||
|
bokehScale={20}
|
||||||
|
// height={700}
|
||||||
|
resolutionScale={0.3}
|
||||||
|
/>
|
||||||
{/* <TiltShift2/> */}
|
{/* <TiltShift2/> */}
|
||||||
<HueSaturation saturation={0.1} />
|
<HueSaturation saturation={0.1} />
|
||||||
</EffectComposer>
|
</EffectComposer>
|
||||||
</>
|
</>
|
||||||
);
|
)
|
||||||
};
|
}
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
/**
|
||||||
|
* FakeGlow material component by Anderson Mancini - Dec 2024.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React, { useRef, useMemo } from 'react'
|
||||||
|
import { shaderMaterial } from '@react-three/drei'
|
||||||
|
import { extend, useFrame } from '@react-three/fiber'
|
||||||
|
import { Color, BackSide, AdditiveBlending } from 'three'
|
||||||
|
|
||||||
|
export default function FakeGlowMaterial({ glowCenter = 0.05, edgeIntensity = 6.0, glowColor = '#00ff00', glowOpacity = 1.0, fresnelOpacity = 0.5, fresnelAmount = 0.5, wireframe = false }) {
|
||||||
|
const FakeGlowMaterial = useMemo(() => {
|
||||||
|
return shaderMaterial(
|
||||||
|
{
|
||||||
|
time: 0,
|
||||||
|
glowCenter: glowCenter,
|
||||||
|
edgeIntensity: edgeIntensity,
|
||||||
|
glowColor: new Color(glowColor),
|
||||||
|
glowOpacity: glowOpacity,
|
||||||
|
fresnelOpacity: fresnelOpacity,
|
||||||
|
fresnelAmount: fresnelAmount
|
||||||
|
},
|
||||||
|
/*GLSL */
|
||||||
|
`
|
||||||
|
uniform float glowCenter;
|
||||||
|
uniform float edgeIntensity;
|
||||||
|
varying float intensity;
|
||||||
|
varying vec3 vNormel;
|
||||||
|
varying vec3 vNormal;
|
||||||
|
uniform float fresnelOpacity;
|
||||||
|
uniform float fresnelAmount;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec3 viewVector = normalize(vec3(cameraPosition-position));
|
||||||
|
float fresnelEffect = dot(vNormel, vNormal) * ( fresnelOpacity);
|
||||||
|
fresnelEffect = clamp(fresnelAmount - fresnelEffect, 0.5, fresnelOpacity);
|
||||||
|
vec3 vNormal = normalize( normalMatrix * normal );
|
||||||
|
vec3 vNormel = normalize( normalMatrix * viewVector );
|
||||||
|
intensity = pow( glowCenter - dot(vNormal, vNormel), edgeIntensity / fresnelEffect );
|
||||||
|
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
|
||||||
|
}`,
|
||||||
|
/*GLSL */
|
||||||
|
`
|
||||||
|
uniform vec3 glowColor;
|
||||||
|
varying float intensity;
|
||||||
|
uniform float glowOpacity;
|
||||||
|
uniform float fresnelOpacity;
|
||||||
|
uniform float fresnelAmount;
|
||||||
|
varying vec3 vNormel;
|
||||||
|
varying vec3 vNormal;
|
||||||
|
uniform float glowCenter;
|
||||||
|
uniform float edgeIntensity;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec3 glow = glowColor * intensity;
|
||||||
|
float fresnelEffect = - dot(vNormel, vNormal);
|
||||||
|
fresnelEffect = clamp(fresnelEffect, 0.1, 1.0);
|
||||||
|
gl_FragColor = vec4( clamp(glow, 0., 1.0), clamp(glowOpacity - intensity * fresnelEffect, 0., 1.0 ));
|
||||||
|
}`
|
||||||
|
)
|
||||||
|
}, [glowCenter, edgeIntensity, glowColor, glowOpacity, fresnelOpacity, fresnelAmount])
|
||||||
|
|
||||||
|
extend({ FakeGlowMaterial })
|
||||||
|
|
||||||
|
useFrame((state, delta) => {
|
||||||
|
ref.current.time += delta
|
||||||
|
})
|
||||||
|
|
||||||
|
const ref = useRef()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<fakeGlowMaterial
|
||||||
|
wireframe={wireframe}
|
||||||
|
key={FakeGlowMaterial.key}
|
||||||
|
side={BackSide}
|
||||||
|
transparent={true}
|
||||||
|
blending={AdditiveBlending}
|
||||||
|
depthTest={false}
|
||||||
|
ref={ref}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
+166
-192
@@ -1,294 +1,246 @@
|
|||||||
import { Controls } from "../App";
|
import { Controls } from '../App'
|
||||||
import { RigidBody, useRapier } from "@react-three/rapier";
|
import { RigidBody, useRapier } from '@react-three/rapier'
|
||||||
import {
|
import { useKeyboardControls, PerspectiveCamera, ContactShadows, Sphere } 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'
|
||||||
} from "@react-three/drei";
|
import { Model } from './models/Racing_kart'
|
||||||
import { useFrame, useThree } from "@react-three/fiber";
|
import { FrontRightWheel } from './models/Front_Right_Wheel'
|
||||||
import { useRef, useState, useEffect, useCallback } from "react";
|
import { FrontLeftWheel } from './models/Front_Left_Wheel'
|
||||||
import * as THREE from "three";
|
import { RearWheels } from './models/Rear_wheels'
|
||||||
import { Model } from "./models/Racing_kart";
|
import gsap from 'gsap'
|
||||||
import { FrontRightWheel } from "./models/Front_Right_Wheel";
|
import { Mario } from './models/Mario_kart'
|
||||||
import { FrontLeftWheel } from "./models/Front_Left_Wheel";
|
import { Particles1 } from './Particles1'
|
||||||
import { RearWheels } from "./models/Rear_wheels";
|
import { DriftParticlesLeft } from './DriftParticlesLeft'
|
||||||
import gsap from "gsap";
|
import { DriftParticlesRight } from './DriftParticlesRight'
|
||||||
import { Mario } from "./models/Mario_kart";
|
import FakeGlowMaterial from './FakeGlow/FakeGlowMaterial'
|
||||||
import { Particles1 } from "./Particles1";
|
|
||||||
import { DriftParticlesLeft } from "./DriftParticlesLeft";
|
|
||||||
import { DriftParticlesRight } from "./DriftParticlesRight";
|
|
||||||
|
|
||||||
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.001;
|
const damping = 0.001
|
||||||
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 = 0.5;
|
const camMaxOffset = 0.5
|
||||||
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 = useRef(false);
|
const isBoosting = useRef(false)
|
||||||
let targetXPosition = 0;
|
let targetXPosition = 0
|
||||||
let targetZPosition = 8;
|
let targetZPosition = 8
|
||||||
const [steeringAngleWheels, setSteeringAngleWheels] = useState(0);
|
const [steeringAngleWheels, setSteeringAngleWheels] = useState(0)
|
||||||
|
|
||||||
const [scale, setScale] = useState(0);
|
const [scale, setScale] = useState(0)
|
||||||
|
|
||||||
useFrame(({ pointer, clock }) => {
|
useFrame(({ pointer, clock }) => {
|
||||||
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
|
||||||
steeringAngle = currentSteeringSpeed * -pointer.x;
|
steeringAngle = currentSteeringSpeed * -pointer.x
|
||||||
targetXPosition = -camMaxOffset * -pointer.x;
|
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, maxSpeed));
|
setCurrentSpeed(Math.min(currentSpeed + acceleration, maxSpeed))
|
||||||
} else if (
|
} else if (upPressed && currentSpeed > maxSpeed && boostDuration.current > 0) {
|
||||||
upPressed &&
|
setCurrentSpeed(Math.max(currentSpeed - decceleration, maxSpeed))
|
||||||
currentSpeed > maxSpeed &&
|
|
||||||
boostDuration.current > 0
|
|
||||||
) {
|
|
||||||
setCurrentSpeed(Math.max(currentSpeed - decceleration, maxSpeed));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (upPressed) {
|
if (upPressed) {
|
||||||
if (currentSteeringSpeed < MaxSteeringSpeed) {
|
if (currentSteeringSpeed < MaxSteeringSpeed) {
|
||||||
setCurrentSteeringSpeed(
|
setCurrentSteeringSpeed(Math.min(currentSteeringSpeed + 0.0001, MaxSteeringSpeed))
|
||||||
Math.min(currentSteeringSpeed + 0.0001, MaxSteeringSpeed)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// REVERSING
|
// REVERSING
|
||||||
if (downPressed && currentSpeed < -maxSpeed) {
|
if (downPressed && currentSpeed < -maxSpeed) {
|
||||||
setCurrentSpeed(Math.max(currentSpeed - acceleration, -maxSpeed));
|
setCurrentSpeed(Math.max(currentSpeed - acceleration, -maxSpeed))
|
||||||
}
|
}
|
||||||
// DECELERATING
|
// DECELERATING
|
||||||
else if (!upPressed && !downPressed) {
|
else if (!upPressed && !downPressed) {
|
||||||
if (currentSteeringSpeed > 0) {
|
if (currentSteeringSpeed > 0) {
|
||||||
setCurrentSteeringSpeed(Math.max(currentSteeringSpeed - 0.00005, 0));
|
setCurrentSteeringSpeed(Math.max(currentSteeringSpeed - 0.00005, 0))
|
||||||
} else if (currentSteeringSpeed < 0) {
|
} else if (currentSteeringSpeed < 0) {
|
||||||
setCurrentSteeringSpeed(Math.min(currentSteeringSpeed + 0.00005, 0));
|
setCurrentSteeringSpeed(Math.min(currentSteeringSpeed + 0.00005, 0))
|
||||||
}
|
}
|
||||||
setCurrentSpeed(Math.max(currentSpeed - decceleration, 0));
|
setCurrentSpeed(Math.max(currentSpeed - decceleration, 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;
|
kart.current.rotation.y += steeringAngle
|
||||||
|
|
||||||
// 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),
|
x: -body.current.linvel().x * (1 - damping),
|
||||||
y: 0,
|
y: 0,
|
||||||
z: -body.current.linvel().z * (1 - damping),
|
z: -body.current.linvel().z * (1 - damping)
|
||||||
},
|
},
|
||||||
true
|
true
|
||||||
);
|
)
|
||||||
const bodyPosition = body.current.translation();
|
const bodyPosition = body.current.translation()
|
||||||
kart.current.position.set(
|
kart.current.position.set(bodyPosition.x, bodyPosition.y - 1, bodyPosition.z)
|
||||||
bodyPosition.x,
|
|
||||||
bodyPosition.y - 1,
|
|
||||||
bodyPosition.z
|
|
||||||
);
|
|
||||||
|
|
||||||
// JUMPING
|
// JUMPING
|
||||||
if (jumpPressed && isOnFloor.current && !jumpIsHeld.current) {
|
if (jumpPressed && isOnFloor.current && !jumpIsHeld.current) {
|
||||||
jumpForce.current += 11;
|
jumpForce.current += 11
|
||||||
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;
|
jumpForce.current -= 1
|
||||||
}
|
}
|
||||||
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.24 && !driftRight.current) {
|
||||||
jumpIsHeld.current &&
|
driftLeft.current = true
|
||||||
currentSteeringSpeed > 0 &&
|
|
||||||
pointer.x < -0.24 &&
|
|
||||||
!driftRight.current
|
|
||||||
) {
|
|
||||||
driftLeft.current = true;
|
|
||||||
}
|
}
|
||||||
if (
|
if (jumpIsHeld.current && currentSteeringSpeed > 0 && pointer.x > 0.24 && !driftLeft.current) {
|
||||||
jumpIsHeld.current &&
|
driftRight.current = true
|
||||||
currentSteeringSpeed > 0 &&
|
|
||||||
pointer.x > 0.24 &&
|
|
||||||
!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.001)
|
||||||
mario.current.rotation.y,
|
setTurboColor(0xffffff)
|
||||||
0,
|
accumulatedDriftPower.current = 0
|
||||||
0.001
|
|
||||||
);
|
|
||||||
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.1)
|
||||||
mario.current.rotation.y,
|
accumulatedDriftPower.current += 0.1 * (steeringAngle + 1)
|
||||||
steeringAngle * 50 + 0.5,
|
|
||||||
0.1
|
|
||||||
);
|
|
||||||
accumulatedDriftPower.current += 0.1 * (steeringAngle + 1);
|
|
||||||
}
|
}
|
||||||
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.1)
|
||||||
mario.current.rotation.y,
|
accumulatedDriftPower.current += 0.1 * (-steeringAngle + 1)
|
||||||
-(-steeringAngle * 50 + 0.5),
|
|
||||||
0.1
|
|
||||||
);
|
|
||||||
accumulatedDriftPower.current += 0.1 * (-steeringAngle + 1);
|
|
||||||
}
|
}
|
||||||
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.1)
|
||||||
mario.current.rotation.y,
|
setScale(0)
|
||||||
steeringAngle * 30,
|
|
||||||
0.1
|
|
||||||
);
|
|
||||||
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;
|
const vibration = oscillation + 0.9
|
||||||
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;
|
boostDuration.current -= 1
|
||||||
targetZPosition = 10;
|
targetZPosition = 10
|
||||||
} else if (boostDuration.current <= 1) {
|
} else if (boostDuration.current <= 1) {
|
||||||
targetZPosition = 8;
|
targetZPosition = 8
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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)
|
||||||
cam.current.position.x,
|
|
||||||
targetXPosition,
|
|
||||||
0.01
|
|
||||||
);
|
|
||||||
|
|
||||||
cam.current.position.z = THREE.MathUtils.lerp(
|
cam.current.position.z = THREE.MathUtils.lerp(cam.current.position.z, targetZPosition, 0.01)
|
||||||
cam.current.position.z,
|
cam.current.updateMatrixWorld()
|
||||||
targetZPosition,
|
|
||||||
0.01
|
|
||||||
);
|
|
||||||
cam.current.updateMatrixWorld();
|
|
||||||
|
|
||||||
body.current.applyImpulse(
|
body.current.applyImpulse(
|
||||||
{
|
{
|
||||||
x: forwardDirection.x * currentSpeed,
|
x: forwardDirection.x * currentSpeed,
|
||||||
y: 0 + jumpForce.current,
|
y: 0 + jumpForce.current,
|
||||||
z: forwardDirection.z * currentSpeed,
|
z: forwardDirection.z * currentSpeed
|
||||||
},
|
},
|
||||||
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)
|
||||||
});
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<group>
|
<group>
|
||||||
<RigidBody
|
<RigidBody
|
||||||
ref={body}
|
ref={body}
|
||||||
type="dynamic"
|
type='dynamic'
|
||||||
colliders={"ball"}
|
colliders={'ball'}
|
||||||
position={[0, 20, 0]}
|
position={[0, 20, 0]}
|
||||||
centerOfMass={[0, -1, 0]}
|
centerOfMass={[0, -1, 0]}
|
||||||
onCollisionEnter={(event) => {
|
onCollisionEnter={(event) => {
|
||||||
isOnFloor.current = true;
|
isOnFloor.current = true
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<mesh transparent>
|
<mesh transparent>
|
||||||
<sphereGeometry args={[1, 6, 6]} />
|
<sphereGeometry args={[1, 6, 6]} />
|
||||||
<meshStandardMaterial color="blue" transparent opacity={0} />
|
<meshStandardMaterial
|
||||||
|
color='blue'
|
||||||
|
transparent
|
||||||
|
opacity={0}
|
||||||
|
/>
|
||||||
</mesh>
|
</mesh>
|
||||||
</RigidBody>
|
</RigidBody>
|
||||||
|
|
||||||
@@ -298,13 +250,25 @@ export const PlayerController = () => {
|
|||||||
currentSpeed={currentSpeed}
|
currentSpeed={currentSpeed}
|
||||||
steeringAngleWheels={steeringAngleWheels}
|
steeringAngleWheels={steeringAngleWheels}
|
||||||
/>
|
/>
|
||||||
<pointLight
|
{/* <pointLight
|
||||||
position={[0.6, 0.05, 0.5]}
|
position={[0.6, 0.05, 0.5]}
|
||||||
intensity={scale}
|
intensity={scale}
|
||||||
color={turboColor}
|
color={turboColor}
|
||||||
distance={1}
|
distance={1}
|
||||||
/>
|
/> */}
|
||||||
<mesh position={[0.6, 0.05, 0.5]} scale={scale}>
|
<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]} />
|
<sphereGeometry args={[0.1, 16, 16]} />
|
||||||
<meshStandardMaterial
|
<meshStandardMaterial
|
||||||
emissive={turboColor}
|
emissive={turboColor}
|
||||||
@@ -320,7 +284,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}
|
||||||
@@ -330,8 +297,15 @@ export const PlayerController = () => {
|
|||||||
opacity={1}
|
opacity={1}
|
||||||
/>
|
/>
|
||||||
</mesh>
|
</mesh>
|
||||||
<DriftParticlesLeft turboColor={turboColor} scale={scale}/>
|
|
||||||
<DriftParticlesRight turboColor={turboColor} scale={scale}/>
|
<DriftParticlesLeft
|
||||||
|
turboColor={turboColor}
|
||||||
|
scale={scale}
|
||||||
|
/>
|
||||||
|
<DriftParticlesRight
|
||||||
|
turboColor={turboColor}
|
||||||
|
scale={scale}
|
||||||
|
/>
|
||||||
</group>
|
</group>
|
||||||
|
|
||||||
{/* <ContactShadows frames={1} /> */}
|
{/* <ContactShadows frames={1} /> */}
|
||||||
@@ -343,5 +317,5 @@ export const PlayerController = () => {
|
|||||||
/>
|
/>
|
||||||
</group>
|
</group>
|
||||||
</group>
|
</group>
|
||||||
);
|
)
|
||||||
};
|
}
|
||||||
Reference in new issue
Block a user