added item system

This commit is contained in:
Alex committed 2024-01-31 15:29:31 +01:00
1 parent 11be02d977
commit 77a14c7733
26 files changed
+676 -35

No files matched your search

+1
View File
@@ -18,6 +18,7 @@
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-gamepad": "^1.0.3", "react-gamepad": "^1.0.3",
"three": "^0.160.1", "three": "^0.160.1",
"three-mesh-bvh": "^0.7.0",
"zustand": "^4.5.0" "zustand": "^4.5.0"
}, },
"devDependencies": { "devDependencies": {
+1
View File
@@ -19,6 +19,7 @@
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-gamepad": "^1.0.3", "react-gamepad": "^1.0.3",
"three": "^0.160.1", "three": "^0.160.1",
"three-mesh-bvh": "^0.7.0",
"zustand": "^4.5.0" "zustand": "^4.5.0"
}, },
"devDependencies": { "devDependencies": {
Binary file not shown.
Binary file not shown.
Binary file not shown.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

+1
View File
@@ -39,6 +39,7 @@ function App() {
<Physics <Physics
gravity={[0, -90, 0]} gravity={[0, -90, 0]}
timeStep={'vary'} timeStep={'vary'}
// debug
> >
<KeyboardControls map={map}> <KeyboardControls map={map}>
<Experience /> <Experience />
+55 -16
View File
@@ -1,21 +1,62 @@
import { Environment, OrbitControls, PerspectiveCamera, Lightformer } from '@react-three/drei' import {
import { Ground } from './Ground' Environment,
import { PlayerController } from './PlayerController' OrbitControls,
import { Paris } from './models/tracks/Tour_paris_promenade' PerspectiveCamera,
import { EffectComposer, N8AO, Bloom, TiltShift2, HueSaturation, SMAA, ChromaticAberration, Vignette } from '@react-three/postprocessing' Lightformer,
import { Skid } from './Skid' Bvh,
} from "@react-three/drei";
import { Ground } from "./Ground";
import { PlayerController } from "./PlayerController";
import { Paris } from "./models/tracks/Tour_paris_promenade";
import {
EffectComposer,
N8AO,
Bloom,
TiltShift2,
HueSaturation,
SMAA,
ChromaticAberration,
Vignette,
} from "@react-three/postprocessing";
import { Skid } from "./Skid";
import { Banana } from "./models/items/Banana_peel_mario_kart";
import { ItemBox } from "./models/misc/Mario_kart_item_box";
import { useStore } from "./store";
import { Shell } from "./models/items/Mario_shell_red";
export const Experience = () => { export const Experience = () => {
const onCollide = (event) => {
console.log(event);
};
const { bananas, shells } = useStore();
return ( return (
<> <>
<PlayerController /> <PlayerController />
<Paris position={[0, 0, 0]} />
<Banana onCollide={onCollide} position={[-10, 1.8, -119]} />
{/* <Shell position={[-20, 2, -119]} /> */}
<ItemBox position={[-20, 2, -119]} />
{/* <Skid /> */} {/* <Skid /> */}
<Ground position={[0, 0, 0]} /> <Ground position={[0, 0, 0]} />
<Environment <Environment resolution={256} preset="lobby" />
resolution={256}
preset='lobby'
/> {bananas.map((banana) => (
<Banana
key={banana.id}
position={banana.position}
// rotation={banana.rotation}
/>
))}
{shells.map((shell) => (
<Shell
key={shell.id}
position={shell.position}
rotation={shell.rotation}
/>
))}
<directionalLight <directionalLight
position={[10, 50, -30]} position={[10, 50, -30]}
@@ -25,17 +66,15 @@ export const Experience = () => {
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={-300}
castShadow castShadow
/> />
<Paris position={[0, 0, 0]} />
<EffectComposer <EffectComposer
multisampling={0} multisampling={0}
disableNormalPass disableNormalPass
disableSSAO disableSSAO
disableDepthPass disableDepthPass
> >
<SMAA /> <SMAA />
<N8AO distanceFalloff={1} aoRadius={1} intensity={3} /> <N8AO distanceFalloff={1} aoRadius={1} intensity={3} />
@@ -46,11 +85,11 @@ export const Experience = () => {
intensity={0.5} intensity={0.5}
/> />
<TiltShift2/> <TiltShift2 />
<ChromaticAberration offset={[0.0006, 0.0006]} /> <ChromaticAberration offset={[0.0006, 0.0006]} />
<HueSaturation saturation={0.1} /> <HueSaturation saturation={0.1} />
<Vignette eskil={false} offset={0.1} darkness={0.4} /> <Vignette eskil={false} offset={0.1} darkness={0.4} />
</EffectComposer> </EffectComposer>
</> </>
) );
} };
+139
View File
@@ -0,0 +1,139 @@
import React, { useState, useEffect, useRef } from "react";
import { Canvas, useLoader, useFrame, extend } from "@react-three/fiber";
import * as THREE from "three";
import { shaderMaterial } from "@react-three/drei";
export const HitParticle = ({ position, shouldLaunch }) => {
const texture = useLoader(THREE.TextureLoader, "./particles/star_symbol.png");
const pointsRef = useRef();
const materialRef = useRef();
const [size, setSize] = useState(3);
const frames = useRef(50);
const gravity = -0.03;
const velocity = useRef({
x: (Math.random() - 0.5) * 33,
y: (Math.random() + 0.3) * 4,
});
const points = React.useMemo(() => {
const geom = new THREE.BufferGeometry();
geom.setAttribute(
"position",
new THREE.Float32BufferAttribute(position, 3)
);
return geom;
}, [position]);
useEffect(() => {
if (shouldLaunch) {
if (pointsRef.current) {
// Reset position
pointsRef.current.position.set(0, 0, 0);
// Reset velocity
velocity.current = {
x: (Math.random() - 0.5) * 33,
y: (Math.random() + 0.3) * 4,
};
// Reset opacity if needed
if (materialRef.current) {
materialRef.current.opacity = 1;
materialRef.current.size = 3;
}
frames.current = 50;
}
}
}, [shouldLaunch]);
useEffect(() => {
if (materialRef.current) {
materialRef.current.color.multiplyScalar(15);
}
}, []);
useFrame((_state, delta) => {
if (pointsRef.current) {
let position = pointsRef.current.position;
// Normalized time value for ease-out effect
let t = 1 - Math.max(frames.current / 150, 0); // Ensure t is between 0 and 1
let easeOutCubic = 1 - Math.pow(1 - t, 3);
// Apply the velocity to the position
position.x += velocity.current.x * delta * easeOutCubic;
position.y += velocity.current.y * delta * easeOutCubic;
// Adjust gravity based on delta
velocity.current.y += gravity * delta * 144;
// Decrease frames
frames.current -= 1;
if (materialRef.current) {
// materialRef.current.size = 3 + Math.sin(frames.current * 0.1) * 2;
materialRef.current.opacity = Math.abs(Math.sin(frames.current * 0.1));
}
// Reset the particle position and velocity when it goes too far
if (frames.current < 0) {
// if(materialRef.current.opacity > 0) {
// Math.max(materialRef.current.opacity -= 0.01 * delta * 144, 0);
// }
if (materialRef.current.size > 0) {
Math.max((materialRef.current.size -= 0.1 * delta * 144), 0);
}
}
pointsRef.current.position.set(position.x, position.y, position.z);
}
});
return (
<points ref={pointsRef} geometry={points}>
<pointsMaterial
ref={materialRef}
size={size}
alphaMap={texture}
transparent={true}
depthWrite={false}
color={0xfafad2}
opacity={1}
/>
</points>
);
};
export const PointsShaderMaterial = shaderMaterial(
{
time: 0,
tex: undefined,
color: new THREE.Color(0xfafad2),
},
// Vertex Shader
`
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
// Fragment Shader
`
varying vec2 vUv;
uniform sampler2D tex;
uniform vec3 color;
uniform float time; // Using the declared 'time' uniform
void main() {
vec2 uv = vUv;
vec4 texColor = texture2D(tex, uv);
gl_FragColor = vec4(color, 1.0) * texColor * vec4(1.0, 1.0, 1.0, 1.0);
}
`
);
extend({ PointsShaderMaterial });
@@ -0,0 +1,72 @@
import React, { useState, useEffect, useRef } from "react";
import { Canvas, useLoader, useFrame } from "@react-three/fiber";
import * as THREE from "three";
import gsap from "gsap";
export const HitParticleTwo = ({ position, shouldLaunch}) => {
const texture = useLoader(THREE.TextureLoader, "./particles/star_symbol.png");
const pointsRef = useRef();
const materialRef = useRef();
const [size, setSize] = useState(1);
const frames = useRef(100);
const gravity = -0.03;
const velocity = useRef({
x: (Math.random() - 0.5) * 16,
y: (Math.random() + 0.3) *4,
});
const points = React.useMemo(() => {
const geom = new THREE.BufferGeometry();
geom.setAttribute(
"position",
new THREE.Float32BufferAttribute(position, 3)
);
return geom;
}, [position]);
useEffect(() => {
if (shouldLaunch) {
if (pointsRef.current) {
// Reset position
pointsRef.current.position.set(0, 0, 0);
// Reset velocity
velocity.current = {
x: (Math.random() - 0.5) * 16,
y: (Math.random() + 0.3) * 4,
};
// Reset opacity if needed
if (materialRef.current) {
materialRef.current.opacity = 1;
}
frames.current = 100;
}
}
}, [shouldLaunch]);
useEffect(() => {
if (materialRef.current) {
materialRef.current.color.multiplyScalar(15);
}
}, []);
return (
<points ref={pointsRef} geometry={points}>
<pointsMaterial
ref={materialRef}
size={size}
alphaMap={texture}
transparent={true}
depthWrite={false}
color={0xFAFAD2}
opacity={1}
// toneMapped={false}
/>
</points>
);
};
+19
View File
@@ -0,0 +1,19 @@
import React from 'react'
import { HitParticle } from './HitParticle'
export const HitParticles = ({ position, shouldLaunch }) => {
return (
<>
<HitParticle position={[0,0,0]} shouldLaunch={shouldLaunch}/>
<HitParticle position={[0,0,0]} shouldLaunch={shouldLaunch}/>
<HitParticle position={[0,0,0]} shouldLaunch={shouldLaunch}/>
<HitParticle position={[0,0,0]} shouldLaunch={shouldLaunch}/>
<HitParticle position={[0,0,0]} shouldLaunch={shouldLaunch}/>
<HitParticle position={[0,0,0]} shouldLaunch={shouldLaunch}/>
<HitParticle position={[0,0,0]} shouldLaunch={shouldLaunch}/>
<HitParticle position={[0,0,0]} shouldLaunch={shouldLaunch}/>
<HitParticle position={[0,0,0]} shouldLaunch={shouldLaunch}/>
</>
)
}
+5 -1
View File
@@ -5,6 +5,7 @@ import * as THREE from "three";
export const PointParticle = ({ position, png, turboColor }) => { export const PointParticle = ({ position, png, turboColor }) => {
const texture = useLoader(THREE.TextureLoader, png); const texture = useLoader(THREE.TextureLoader, png);
const pointsRef = useRef(); const pointsRef = useRef();
const materialRef = useRef();
const [size, setSize] = useState(0); const [size, setSize] = useState(0);
const [opacity, setOpacity] = useState(1); const [opacity, setOpacity] = useState(1);
@@ -18,7 +19,9 @@ export const PointParticle = ({ position, png, turboColor }) => {
}, [position]); }, [position]);
useEffect(() => { useEffect(() => {
if (materialRef.current) {
materialRef.current.color.multiplyScalar(10);
}
setSize(0); setSize(0);
setOpacity(1); setOpacity(1);
}, [turboColor]); }, [turboColor]);
@@ -36,6 +39,7 @@ export const PointParticle = ({ position, png, turboColor }) => {
return ( return (
<points ref={pointsRef} geometry={points}> <points ref={pointsRef} geometry={points}>
<pointsMaterial <pointsMaterial
ref={materialRef}
size={size} size={size}
alphaMap={texture} alphaMap={texture}
transparent={true} transparent={true}
+91 -16
View File
@@ -23,6 +23,7 @@ import { FlameParticles } from "./Particles/FlameParticles";
import { useStore } from "./store"; import { useStore } from "./store";
import { Cylinder } from "@react-three/drei"; import { Cylinder } from "@react-three/drei";
import FakeGlowMaterial from "./ShaderMaterials/FakeGlow/FakeGlowMaterial"; import FakeGlowMaterial from "./ShaderMaterials/FakeGlow/FakeGlowMaterial";
import { HitParticles } from "./Particles/HitParticles";
export const PlayerController = () => { export const PlayerController = () => {
const upPressed = useKeyboardControls((state) => state[Controls.up]); const upPressed = useKeyboardControls((state) => state[Controls.up]);
@@ -30,6 +31,8 @@ export const PlayerController = () => {
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 shootPressed = useKeyboardControls((state) => state[Controls.shoot]);
const [isOnGround, setIsOnGround] = useState(false); const [isOnGround, setIsOnGround] = useState(false);
const body = useRef(); const body = useRef();
const kart = useRef(); const kart = useRef();
@@ -73,6 +76,14 @@ export const PlayerController = () => {
const landingSound = useRef(); const landingSound = useRef();
const turboSound = useRef(); const turboSound = useRef();
const [scale, setScale] = useState(0); const [scale, setScale] = useState(0);
const raycaster = new THREE.Raycaster();
const downDirection = new THREE.Vector3(0, -1, 0);
const [shouldLaunch, setShouldLaunch] = useState(false);
const { actions, shouldSlowDown, item, bananas} = useStore();
const slowDownDuration = useRef(1500);
useFrame(({ pointer, clock }, delta) => { useFrame(({ pointer, clock }, delta) => {
const time = clock.getElapsedTime(); const time = clock.getElapsedTime();
@@ -86,7 +97,6 @@ export const PlayerController = () => {
driftBlueSound.current.setVolume(0.5); driftBlueSound.current.setVolume(0.5);
driftOrangeSound.current.setVolume(0.6); driftOrangeSound.current.setVolume(0.6);
driftPurpleSound.current.setVolume(0.7); driftPurpleSound.current.setVolume(0.7);
// 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;
@@ -121,6 +131,8 @@ export const PlayerController = () => {
targetXPosition = -camMaxOffset * -pointer.x; targetXPosition = -camMaxOffset * -pointer.x;
} }
// ACCELERATING // ACCELERATING
const shouldSlow = actions.getShouldSlowDown();
if (upPressed && currentSpeed < maxSpeed) { if (upPressed && currentSpeed < maxSpeed) {
// Accelerate the kart within the maximum speed limit // Accelerate the kart within the maximum speed limit
@@ -147,6 +159,22 @@ export const PlayerController = () => {
); );
} }
} }
if (shouldSlow) {
setCurrentSpeed(Math.max(currentSpeed - decceleration * 2 * delta * 144, 0));
setCurrentSteeringSpeed(0);
slowDownDuration.current -= 1500 * delta;
setShouldLaunch(true);
if (slowDownDuration.current <= 1) {
actions.setShouldSlowDown(false);
slowDownDuration.current = 1500;
setShouldLaunch(false);
}
}
// REVERSING // REVERSING
if (downPressed && currentSpeed < -maxSpeed) { if (downPressed && currentSpeed < -maxSpeed) {
setCurrentSpeed( setCurrentSpeed(
@@ -359,6 +387,55 @@ export const PlayerController = () => {
// SOUND WORK // SOUND WORK
// MISC
// ITEMS
if(shootPressed && item === "banana") {
const distanceBehind = 2; // Adjust this value as needed
const scaledBackwardDirection = forwardDirection.multiplyScalar(distanceBehind);
// Get the current position of the kart
const kartPosition = new THREE.Vector3(...vec3(body.current.translation()));
// Calculate the position for the new banana
const bananaPosition = kartPosition.sub(scaledBackwardDirection);
const newBanana = {
id: Math.random() + "-" + new Date(),
position: bananaPosition,
player: true,
};
actions.addBanana(newBanana);
actions.useItem();
}
if(shootPressed && item === "shell") {
const distanceBehind = -1; // Adjust this value as needed
const scaledBackwardDirection = forwardDirection.multiplyScalar(distanceBehind);
// Get the current position of the kart
const kartPosition = new THREE.Vector3(
body.current.translation().x,
body.current.translation().y,
body.current.translation().z
);
// Calculate the position for the new banana
const shellPosition = kartPosition.sub(scaledBackwardDirection);
const newShell = {
id: Math.random() + "-" + new Date(),
position: shellPosition,
player: true,
rotation: kartRotation
};
actions.addShell(newShell);
actions.useItem();
}
if(item) console.log(item)
// console.lowg(body.current.translation()) // console.lowg(body.current.translation())
}); });
@@ -367,20 +444,19 @@ export const PlayerController = () => {
<RigidBody <RigidBody
ref={body} ref={body}
colliders={false} colliders={false}
position={[8, 20, -119]} position={[8, 60, -119]}
centerOfMass={[0, -1, 0]} centerOfMass={[0, -1, 0]}
mass={3} mass={3}
ccd ccd
name="player"
> >
<BallCollider <BallCollider
args={[0.5]} args={[0.5]}
mass={3} mass={3}
onCollisionEnter={(event) => { onCollisionEnter={({other}) => {
isOnFloor.current = true; isOnFloor.current = true;
}} }}
// onCollisionExit={(event) => {
// isOnFloor.current = false
// }}
/> />
</RigidBody> </RigidBody>
@@ -391,12 +467,11 @@ export const PlayerController = () => {
steeringAngleWheels={steeringAngleWheels} steeringAngleWheels={steeringAngleWheels}
isBoosting={isBoosting} isBoosting={isBoosting}
/> />
{/* <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} />
/> */}
<mesh position={[0.6, 0.05, 0.5]} scale={scale}> <mesh position={[0.6, 0.05, 0.5]} scale={scale}>
<sphereGeometry args={[0.05, 16, 16]} /> <sphereGeometry args={[0.05, 16, 16]} />
@@ -417,12 +492,11 @@ export const PlayerController = () => {
glowSharpness={1} glowSharpness={1}
/> />
</mesh> </mesh>
{/* <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} />
/> */}
<mesh position={[-0.6, 0.05, 0.5]} scale={scale}> <mesh position={[-0.6, 0.05, 0.5]} scale={scale}>
<sphereGeometry args={[0.05, 16, 16]} /> <sphereGeometry args={[0.05, 16, 16]} />
<meshStandardMaterial <meshStandardMaterial
@@ -448,24 +522,25 @@ export const PlayerController = () => {
<DriftParticlesRight turboColor={turboColor} scale={scale} /> <DriftParticlesRight turboColor={turboColor} scale={scale} />
<PointParticle <PointParticle
position={[-0.6, 0.05, 0.5]} position={[-0.6, 0.05, 0.5]}
png="./circle.png" png="./particles/circle.png"
turboColor={turboColor} turboColor={turboColor}
/> />
<PointParticle <PointParticle
position={[0.6, 0.05, 0.5]} position={[0.6, 0.05, 0.5]}
png="./circle.png" png="./particles/circle.png"
turboColor={turboColor} turboColor={turboColor}
/> />
<PointParticle <PointParticle
position={[-0.6, 0.05, 0.5]} position={[-0.6, 0.05, 0.5]}
png="./star.png" png="./particles/star.png"
turboColor={turboColor} turboColor={turboColor}
/> />
<PointParticle <PointParticle
position={[0.6, 0.05, 0.5]} position={[0.6, 0.05, 0.5]}
png="./star.png" png="./particles/star.png"
turboColor={turboColor} turboColor={turboColor}
/> />
<HitParticles shouldLaunch={shouldLaunch}/>
</group> </group>
{/* <ContactShadows frames={1} /> */} {/* <ContactShadows frames={1} /> */}
-1
View File
@@ -57,7 +57,6 @@ function setItemAt(instances, bodyPosition, bodyRotation, index) {
.add(bodyPosition); .add(bodyPosition);
// Apply the offset to position the skid marks behind the body // 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.position.copy(bodyPosition.x, bodyPosition.y + 2, bodyPosition.z);
o.rotation.set(0, bodyRotation, 0); o.rotation.set(0, bodyRotation, 0);
@@ -3,11 +3,13 @@ Auto-generated by: https://github.com/pmndrs/gltfjsx
Command: npx gltfjsx@6.2.16 .\mariokarttest.glb --shadows Command: npx gltfjsx@6.2.16 .\mariokarttest.glb --shadows
*/ */
import React, { useRef } from 'react' import React, { useEffect, useRef } from 'react'
import { Cylinder, OrbitControls, Sphere, 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 '../../ShaderMaterials/FakeGlow/FakeGlowMaterial' import FakeGlowMaterial from '../../ShaderMaterials/FakeGlow/FakeGlowMaterial'
import FakeFlame from '../../ShaderMaterials/FakeFlame/FakeFlame' import FakeFlame from '../../ShaderMaterials/FakeFlame/FakeFlame'
import { useStore } from '../../store'
import gsap from 'gsap'
export function Mario({ currentSpeed, steeringAngleWheels, isBoosting, ...props }) { export function Mario({ currentSpeed, steeringAngleWheels, isBoosting, ...props }) {
const { nodes, materials } = useGLTF('./models/characters/mariokarttest.glb') const { nodes, materials } = useGLTF('./models/characters/mariokarttest.glb')
@@ -17,6 +19,9 @@ export function Mario({ currentSpeed, steeringAngleWheels, isBoosting, ...props
const rearWheels = useRef() const rearWheels = useRef()
const frontWheels = useRef() const frontWheels = useRef()
const [scale, setScale] = React.useState(1) const [scale, setScale] = React.useState(1)
const { actions } = useStore()
const [shouldSlow, setShouldSlow] = React.useState(false)
const mario = useRef();
// isBoosting = true; // isBoosting = true;
useFrame((_,delta) => { useFrame((_,delta) => {
@@ -30,12 +35,21 @@ export function Mario({ currentSpeed, steeringAngleWheels, isBoosting, ...props
} else { } else {
setScale(Math.max(scale - 0.03 * 144 * delta, 0)) setScale(Math.max(scale - 0.03 * 144 * delta, 0))
} }
setShouldSlow(actions.getShouldSlowDown());
}) })
useEffect(() => {
if (shouldSlow) {
gsap.to(mario.current.rotation, {duration: 1.5, y: Math.PI * 3})
mario.current.rotation.set(0, 0, 0);
}
}, [shouldSlow])
return ( return (
<group <group
{...props} {...props}
rotation={[0, Math.PI, 0]} rotation={[0, Math.PI, 0]}
dispose={null} dispose={null}
ref={mario}
> >
<mesh <mesh
castShadow castShadow
@@ -0,0 +1,58 @@
/*
Auto-generated by: https://github.com/pmndrs/gltfjsx
Command: npx gltfjsx@6.2.16 .\banana_peel_mario_kart.glb --transform --shadows
Files: .\banana_peel_mario_kart.glb [186.36KB] > C:\Users\mouli\dev\r3f-vite-starter\public\models\items\banana_peel_mario_kart-transformed.glb [20.2KB] (89%)
Author: Anthony Yanez (https://sketchfab.com/paulyanez)
License: CC-BY-4.0 (http://creativecommons.org/licenses/by/4.0/)
Source: https://sketchfab.com/3d-models/banana-peel-mario-kart-c7fd163741614859ba02f302ce0bce32
Title: Banana Peel (Mario Kart)
*/
import React, { useRef } from 'react'
import { useGLTF } from '@react-three/drei'
import { BallCollider, RigidBody } from '@react-three/rapier'
import { useFrame } from '@react-three/fiber';
import { useStore } from '../../store';
export function Banana({onCollide, ...props}) {
const { nodes, materials } = useGLTF('./models/items/banana_peel_mario_kart-transformed.glb');
const rigidBody = useRef();
const ref = useRef();
const [scale, setScale] = React.useState(0.002);
const {actions} = useStore();
return (
<>
<RigidBody
ref={rigidBody}
type='fixed'
position={props.position}
sensor
onIntersectionEnter={(event) => {
if(scale === 0.002) {
actions.setShouldSlowDown(true);
console.log(ref.current, rigidBody.current);
ref.current.visible = false;
setScale(0);
rigidBody.setEnable(false);
}
}}
colliders={false}
name='banana'
>
<BallCollider args={[0.5]} />
</RigidBody>
<group {...props} ref={ref} scale={scale} dispose={null}>
<mesh castShadow receiveShadow geometry={nodes['Banana_Peel_02_-_Default_0'].geometry} material={materials['02_-_Default']} position={[39.973, -25.006, -0.017]} rotation={[-Math.PI / 2, 0, 0]} />
<mesh castShadow receiveShadow geometry={nodes['Banana_Peel_07_-_Default_0'].geometry} material={materials['07_-_Default']} position={[39.973, -25.006, -0.017]} rotation={[-Math.PI / 2, 0, 0]} />
<mesh castShadow receiveShadow geometry={nodes['Banana_Peel_03_-_Default_0'].geometry} material={materials['03_-_Default']} position={[39.973, -25.006, -0.017]} rotation={[-Math.PI / 2, 0, 0]} />
</group>
</>
)
}
useGLTF.preload('./models/items/banana_peel_mario_kart-transformed.glb')
@@ -0,0 +1,51 @@
/*
Auto-generated by: https://github.com/pmndrs/gltfjsx
Command: npx gltfjsx@6.2.16 .\mario_shell_red.glb
Author: Thomas Fugier (https://sketchfab.com/thomas.fugier)
License: CC-BY-4.0 (http://creativecommons.org/licenses/by/4.0/)
Source: https://sketchfab.com/3d-models/mario-shell-red-76a81ff57398423d80800259c3d48262
Title: Mario Shell Red
*/
import React, { useEffect, useRef } from 'react'
import { useGLTF } from '@react-three/drei'
import { BallCollider, RigidBody, vec3 } from '@react-three/rapier'
import { useFrame } from '@react-three/fiber';
export function Shell(props) {
const { nodes, materials } = useGLTF('./models/items/mario_shell_red.glb')
const rigidBody = useRef();
const ref = useRef();
const shell_speed = 100;
useEffect(() => {
const velocity = {
x : -Math.sin(props.rotation) * shell_speed,
y : 0,
z : -Math.cos(props.rotation) * shell_speed,
};
rigidBody.current.setLinvel(velocity, true);
},[]);
useFrame((state, delta) => {
const rigidBodyPosition = rigidBody.current.translation();
ref.current.position.set(rigidBodyPosition.x, rigidBodyPosition.y, rigidBodyPosition.z);
ref.current.rotation.z += 0.2 * delta * 144;
});
return (
<group dispose={null}>
<RigidBody ref={rigidBody} type="dynamic" position={props.position} name="shell" colliders={false}>
<BallCollider args={[0.5]} />
</RigidBody>
<mesh ref={ref} geometry={nodes.defaultMaterial.geometry} material={materials.Shell} rotation={[-Math.PI / 2, 0, 0]} scale={0.6} />
</group>
)
}
useGLTF.preload('./models/items/mario_shell_red.glb')
@@ -0,0 +1,51 @@
/*
Auto-generated by: https://github.com/pmndrs/gltfjsx
Command: npx gltfjsx@6.2.16 .\mario_kart_item_box.glb
Author: Bscott5 (https://sketchfab.com/Bscott5)
License: CC-BY-4.0 (http://creativecommons.org/licenses/by/4.0/)
Source: https://sketchfab.com/3d-models/mario-kart-item-box-8f6a2b6b17b844c5b5dfa38375289975
Title: Mario Kart Item Box
*/
import React, { useRef } from "react";
import { useGLTF, Float, MeshTransmissionMaterial, RoundedBox } from "@react-three/drei";
import { RigidBody } from "@react-three/rapier";
import { useStore } from "../../store";
export function ItemBox(props) {
const { actions } = useStore();
return (
<>
<RigidBody type="fixed" name="itemBox"
sensor
onIntersectionEnter={() => {
console.log("item box hit");
actions.setItem();
}}
position={props.position}
>
<mesh>
<boxGeometry args={[1, 1, 1]} />
<meshStandardMaterial color="green" />
</mesh>
</RigidBody>
<group {...props} dispose={null}>
<Float
speed={2} // Animation speed, defaults to 1
rotationIntensity={20} // XYZ rotation intensity, defaults to 1
floatIntensity={1} // Up/down float intensity, works like a multiplier with floatingRange,defaults to 1
floatingRange={[1, 2]} // Range of y-axis values the object will float within, defaults to [-0.1,0.1]
>
<mesh>
<boxGeometry args={[1, 1, 1]} />
<meshBasicMaterial color="green" />
</mesh>
</Float>
</group>
</>
);
}
+49
View File
@@ -7,6 +7,10 @@ export const playAudio = (path, callback) => {
} }
audio.play(); audio.play();
}; };
export const items = [
"banana",
"shell",
]
export const useStore = create((set, get) => ({ export const useStore = create((set, get) => ({
particles1: [], particles1: [],
@@ -14,6 +18,11 @@ export const useStore = create((set, get) => ({
bodyPosition: [0, 0, 0], bodyPosition: [0, 0, 0],
bodyRotation: [0, 0, 0], bodyRotation: [0, 0, 0],
pastPositions: [], pastPositions: [],
shouldSlowdown: false,
bananas: [],
items: ["banana", "shell"],
item: "",
shells: [],
addPastPosition: (position) => { addPastPosition: (position) => {
set((state) => ({ set((state) => ({
pastPositions: [position, ...state.pastPositions.slice(0, 499)], pastPositions: [position, ...state.pastPositions.slice(0, 499)],
@@ -52,5 +61,45 @@ export const useStore = create((set, get) => ({
getBodyRotation: () => { getBodyRotation: () => {
return get().bodyRotation; return get().bodyRotation;
}, },
setShouldSlowDown: (shouldSlowdown) => {
set({ shouldSlowdown });
},
getShouldSlowDown: () => {
return get().shouldSlowdown;
},
addBanana: (banana) => {
set((state) => ({
bananas: [...state.bananas, banana],
}));
},
removeBanana: (banana) => {
set((state) => ({
bananas: state.bananas.filter((b) => b.id !== banana.id),
}));
},
getBananas: () => {
return get().bananas;
},
setItem:() => {
set((state) => ({
item: state.items[Math.floor(Math.random() * state.items.length)],
}));
},
useItem:() => {
set((state) => ({
item: "",
}));
},
addShell: (shell) => {
set((state) => ({
shells: [...state.shells, shell],
}));
},
removeShell: (shell) => {
set((state) => ({
shells: state.shells.filter((s) => s.id !== shell.id),
}));
}
}, },
})); }));
+68
View File
@@ -0,0 +1,68 @@
import { useState, useEffect } from 'react';
export const useGamepad = () => {
const [gamepadInfo, setGamepadInfo] = useState({ connected: false, buttonA: false, buttonB :false, buttonX: false, buttonY:false, joystick: [0, 0], joystickRight : [0,0], RB: false, LB: false, RT: false, LT: false, start: false, select: false, up: false, down: false, left: false, right: false});
// Function to update gamepad state
const updateGamepadState = () => {
const gamepads = navigator.getGamepads ? navigator.getGamepads() : [];
const gamepad = gamepads[0]; // Assuming the first gamepad
if (gamepad) {
const newGamepadInfo = {
connected: true,
buttonA: gamepad.buttons[0].pressed,
buttonB: gamepad.buttons[1].pressed,
buttonX: gamepad.buttons[2].pressed,
buttonY: gamepad.buttons[3].pressed,
joystickRight: [gamepad.axes[2], gamepad.axes[3]],
LT: gamepad.buttons[6].pressed,
RT: gamepad.buttons[7].pressed,
LB: gamepad.buttons[4].pressed,
RB: gamepad.buttons[5].pressed,
start: gamepad.buttons[9].pressed,
select: gamepad.buttons[8].pressed,
up: gamepad.buttons[12].pressed,
down: gamepad.buttons[13].pressed,
left: gamepad.buttons[14].pressed,
right: gamepad.buttons[15].pressed,
joystick: [gamepad.axes[0], gamepad.axes[1]]
};
// Update state only if there's a change
if (JSON.stringify(newGamepadInfo) !== JSON.stringify(gamepadInfo)) {
setGamepadInfo(newGamepadInfo);
}
} else {
if (gamepadInfo.connected) {
setGamepadInfo({ connected: false, buttonA: false, buttonB :false, buttonX: false, buttonY:false, joystick: [0, 0], joystickRight : [0,0], RB: false, LB: false, RT: false, LT: false, start: false, select: false, up: false, down: false, left: false, right: false});
}
}
};
useEffect(() => {
const gamepadConnected = () => {
console.log('Gamepad connected!');
updateGamepadState();
};
const gamepadDisconnected = () => {
console.log('Gamepad disconnected!');
setGamepadInfo({ connected : false, buttonA: false, buttonB :false, buttonX: false, buttonY:false, joystick: [0, 0], joystickRight : [0,0], RB: false, LB: false, RT: false, LT: false, start: false, select: false, up: false, down: false, left: false, right: false});
};
window.addEventListener('gamepadconnected', gamepadConnected);
window.addEventListener('gamepaddisconnected', gamepadDisconnected);
const interval = setInterval(updateGamepadState, 100);
return () => {
window.removeEventListener('gamepadconnected', gamepadConnected);
window.removeEventListener('gamepaddisconnected', gamepadDisconnected);
clearInterval(interval);
};
}, [gamepadInfo]);
return gamepadInfo;
};