feat:(game) added interraction and particles for items/coins
parent
cff143c925
commit
db52f49e09
Binary file not shown.
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 68 KiB |
Binary file not shown.
After Width: | Height: | Size: 68 KiB |
Binary file not shown.
After Width: | Height: | Size: 26 KiB |
|
@ -30,24 +30,26 @@ function App() {
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
|
<Loader />
|
||||||
<Canvas
|
<Canvas
|
||||||
shadows
|
shadows
|
||||||
dpr={1}
|
dpr={1}
|
||||||
gl={{ antialias: false, stencil: false, powerPreference: 'high-performance' }}
|
gl={{ antialias: false, stencil: false, powerPreference: 'high-performance' }}
|
||||||
>
|
>
|
||||||
<Suspense fallback={null}>
|
<Suspense fallback={null}>
|
||||||
|
<Preload all />
|
||||||
<Physics
|
<Physics
|
||||||
gravity={[0, -90, 0]}
|
gravity={[0, -90, 0]}
|
||||||
timeStep={'vary'}
|
timeStep={'vary'}
|
||||||
// debug
|
|
||||||
>
|
>
|
||||||
<KeyboardControls map={map}>
|
<KeyboardControls map={map}>
|
||||||
<Experience />
|
<Experience />
|
||||||
</KeyboardControls>
|
</KeyboardControls>
|
||||||
<Stats />
|
|
||||||
</Physics>
|
</Physics>
|
||||||
</Suspense>
|
</Suspense>
|
||||||
</Canvas>
|
</Canvas>
|
||||||
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ export const HUD = () => {
|
||||||
</div>
|
</div>
|
||||||
<div className="wheel">
|
<div className="wheel">
|
||||||
<img
|
<img
|
||||||
ref={wheel}
|
ref={wheel}
|
||||||
src="./steering_wheel.png"
|
src="./steering_wheel.png"
|
||||||
alt="steering wheel"
|
alt="steering wheel"
|
||||||
className="steering-wheel"
|
className="steering-wheel"
|
||||||
|
|
|
@ -19,7 +19,7 @@ import {
|
||||||
Vignette,
|
Vignette,
|
||||||
} from "@react-three/postprocessing";
|
} from "@react-three/postprocessing";
|
||||||
import { Banana } from "./models/items/Banana_peel_mario_kart";
|
import { Banana } from "./models/items/Banana_peel_mario_kart";
|
||||||
import { ItemBox } from "./models/misc/Mario_kart_item_box";
|
import { ItemBox } from "./models/misc/Gift";
|
||||||
import { useStore } from "./store";
|
import { useStore } from "./store";
|
||||||
import { Shell } from "./models/items/Mario_shell_red";
|
import { Shell } from "./models/items/Mario_shell_red";
|
||||||
import { Coin } from "./models/misc/Super_mario_bros_coin";
|
import { Coin } from "./models/misc/Super_mario_bros_coin";
|
||||||
|
@ -36,7 +36,7 @@ export const Experience = () => {
|
||||||
<Paris position={[0, 0, 0]} />
|
<Paris position={[0, 0, 0]} />
|
||||||
<Banana onCollide={onCollide} position={[-10, 1.8, -119]} />
|
<Banana onCollide={onCollide} position={[-10, 1.8, -119]} />
|
||||||
{/* <Shell position={[-20, 2, -119]} /> */}
|
{/* <Shell position={[-20, 2, -119]} /> */}
|
||||||
<ItemBox position={[-20, 2, -119]} />
|
<ItemBox position={[-20, 2.5, -119]} />
|
||||||
<Coin position={[-30, 2, -119]} />
|
<Coin position={[-30, 2, -119]} />
|
||||||
|
|
||||||
<Ground position={[0, 0, 0]} />
|
<Ground position={[0, 0, 0]} />
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
import React, { useEffect,useRef, useState } from "react";
|
||||||
|
import { useLoader, useFrame } from "@react-three/fiber";
|
||||||
|
import * as THREE from "three";
|
||||||
|
|
||||||
|
export const CircleCoinParticle = ({ position, coins }) => {
|
||||||
|
const texture = useLoader(THREE.TextureLoader, "./particles/circle_coin.png");
|
||||||
|
const pointsRef = useRef();
|
||||||
|
const materialRef = useRef();
|
||||||
|
const [size, setSize] = useState(1);
|
||||||
|
const [opacity, setOpacity] = useState(1);
|
||||||
|
|
||||||
|
const points = React.useMemo(() => {
|
||||||
|
const geom = new THREE.BufferGeometry();
|
||||||
|
geom.setAttribute(
|
||||||
|
"position",
|
||||||
|
new THREE.Float32BufferAttribute(position, 3)
|
||||||
|
);
|
||||||
|
return geom;
|
||||||
|
}, [position]);
|
||||||
|
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (materialRef.current) {
|
||||||
|
materialRef.current.color.multiplyScalar(4);
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setSize(0);
|
||||||
|
setOpacity(1);
|
||||||
|
}, [coins]);
|
||||||
|
|
||||||
|
useFrame((_, delta) => {
|
||||||
|
if (size < 5) {
|
||||||
|
setSize((size) => Math.min(size + 0.2 * delta * 144, 5));
|
||||||
|
} else if (opacity > 0) {
|
||||||
|
setOpacity((opacity) => Math.max(opacity - 0.1 * delta * 144, 0));
|
||||||
|
setSize((size) => Math.max(size - 0.1 * delta * 144, 0));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<points ref={pointsRef} geometry={points}>
|
||||||
|
<pointsMaterial
|
||||||
|
ref={materialRef}
|
||||||
|
size={size}
|
||||||
|
alphaMap={texture}
|
||||||
|
transparent={true}
|
||||||
|
depthWrite={false}
|
||||||
|
opacity={opacity}
|
||||||
|
toneMapped={false}
|
||||||
|
color={0xbf8717}
|
||||||
|
/>
|
||||||
|
</points>
|
||||||
|
);
|
||||||
|
};
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { CircleCoinParticle } from "./CircleCoinParticle"
|
||||||
|
import { StarCoinParticle } from "./StarCoinParticle"
|
||||||
|
|
||||||
|
export const CoinParticles = ({ coins }) => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<CircleCoinParticle position={[0,0.8, 0.2]} coins={coins}/>
|
||||||
|
<StarCoinParticle position={[0,0.8, 0.2]} coins={coins} timeModifier={50}/>
|
||||||
|
<StarCoinParticle position={[0,0.8, 0.2]} coins={coins} timeModifier={60}/>
|
||||||
|
<StarCoinParticle position={[0,0.8, 0.2]} coins={coins} timeModifier={40}/>
|
||||||
|
<StarCoinParticle position={[0,0.8, 0.2]} coins={coins} timeModifier={90}/>
|
||||||
|
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
import React, { useEffect, useRef } from "react";
|
||||||
|
import { useLoader, useFrame } from "@react-three/fiber";
|
||||||
|
import * as THREE from "three";
|
||||||
|
|
||||||
|
export const StarCoinParticle = ({ position, coins, timeModifier }) => {
|
||||||
|
const texture = useLoader(THREE.TextureLoader, "./particles/star_coin.png");
|
||||||
|
const pointsRef = useRef();
|
||||||
|
const materialRef = useRef();
|
||||||
|
const sizeRef = useRef(1);
|
||||||
|
const opacityRef = useRef(1);
|
||||||
|
const originalYpos = useRef(0);
|
||||||
|
|
||||||
|
const points = React.useMemo(() => {
|
||||||
|
const geom = new THREE.BufferGeometry();
|
||||||
|
geom.setAttribute(
|
||||||
|
"position",
|
||||||
|
new THREE.Float32BufferAttribute(position, 3)
|
||||||
|
);
|
||||||
|
return geom;
|
||||||
|
}, [position]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (materialRef.current) {
|
||||||
|
materialRef.current.color.multiplyScalar(6);
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
sizeRef.current = 0;
|
||||||
|
opacityRef.current = 1;
|
||||||
|
pointsRef.current.position.x = Math.random() * 1 - 0.5;
|
||||||
|
pointsRef.current.position.y = Math.random() * 0.5 - 0.25;
|
||||||
|
originalYpos.current = pointsRef.current.position.y;
|
||||||
|
}, [coins]);
|
||||||
|
|
||||||
|
useFrame((state, delta) => {
|
||||||
|
const time = state.clock.getElapsedTime();
|
||||||
|
pointsRef.current.position.y += 0.008 * delta * 144;
|
||||||
|
if (sizeRef.current < 1) {
|
||||||
|
sizeRef.current = Math.min(sizeRef.current + 0.01 * delta * 144, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pointsRef.current.position.y > originalYpos.current + 0.01) {
|
||||||
|
opacityRef.current = Math.max(opacityRef.current - 0.01 * delta * 144, 0);
|
||||||
|
} else {
|
||||||
|
opacityRef.current = Math.abs(Math.sin(time * timeModifier * 1500));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update material properties directly
|
||||||
|
if (materialRef.current) {
|
||||||
|
materialRef.current.size = sizeRef.current;
|
||||||
|
materialRef.current.opacity = opacityRef.current;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<points ref={pointsRef} geometry={points}>
|
||||||
|
<pointsMaterial
|
||||||
|
ref={materialRef}
|
||||||
|
alphaMap={texture}
|
||||||
|
transparent={true}
|
||||||
|
depthWrite={false}
|
||||||
|
toneMapped={false}
|
||||||
|
color={0xbf8717}
|
||||||
|
/>
|
||||||
|
</points>
|
||||||
|
);
|
||||||
|
};
|
|
@ -0,0 +1,61 @@
|
||||||
|
import React, { useEffect,useRef, useState } from "react";
|
||||||
|
import { useLoader, useFrame } from "@react-three/fiber";
|
||||||
|
import * as THREE from "three";
|
||||||
|
|
||||||
|
export const CircleItemParticle = ({ position, item, color }) => {
|
||||||
|
const texture = useLoader(THREE.TextureLoader, "./particles/circle_coin.png");
|
||||||
|
const pointsRef = useRef();
|
||||||
|
const materialRef = useRef();
|
||||||
|
const [size, setSize] = useState(1);
|
||||||
|
const [opacity, setOpacity] = useState(1);
|
||||||
|
|
||||||
|
const [currentColor, setCurrentColor] = useState(color);
|
||||||
|
|
||||||
|
const points = React.useMemo(() => {
|
||||||
|
const geom = new THREE.BufferGeometry();
|
||||||
|
geom.setAttribute(
|
||||||
|
"position",
|
||||||
|
new THREE.Float32BufferAttribute(position, 3)
|
||||||
|
);
|
||||||
|
return geom;
|
||||||
|
}, [position]);
|
||||||
|
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (materialRef.current) {
|
||||||
|
materialRef.current.color.multiplyScalar(4);
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if(item){
|
||||||
|
setSize(0);
|
||||||
|
setOpacity(1);
|
||||||
|
}
|
||||||
|
}, [item]);
|
||||||
|
|
||||||
|
useFrame((_, delta) => {
|
||||||
|
if (size < 5) {
|
||||||
|
setSize((size) => Math.min(size + 0.2 * delta * 144, 5));
|
||||||
|
} else if (opacity > 0) {
|
||||||
|
setOpacity((opacity) => Math.max(opacity - 0.1 * delta * 144, 0));
|
||||||
|
setSize((size) => Math.max(size - 0.1 * delta * 144, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<points ref={pointsRef} geometry={points}>
|
||||||
|
<pointsMaterial
|
||||||
|
ref={materialRef}
|
||||||
|
size={size}
|
||||||
|
alphaMap={texture}
|
||||||
|
transparent={true}
|
||||||
|
depthWrite={false}
|
||||||
|
opacity={opacity}
|
||||||
|
toneMapped={false}
|
||||||
|
color={currentColor}
|
||||||
|
/>
|
||||||
|
</points>
|
||||||
|
);
|
||||||
|
};
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { CircleItemParticle } from "./CircleItemParticle"
|
||||||
|
import { StarItemParticle } from "./StarItemParticle"
|
||||||
|
import { SmallCircleParticle } from "./SmallCircleParticle"
|
||||||
|
|
||||||
|
export const ItemParticles = ({item}) => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<CircleItemParticle position={[0,0.8, 0.2]} item={item} color={0x75ff9a}/>
|
||||||
|
<StarItemParticle position={[0,0.8, 0.2]} item={item} timeModifier={50} color={0x75ff9a}/>
|
||||||
|
<StarItemParticle position={[0,0.8, 0.2]} item={item} timeModifier={60} color={0xe872fc}/>
|
||||||
|
<StarItemParticle position={[0,0.8, 0.2]} item={item} timeModifier={40} color={0x72e5fc}/>
|
||||||
|
<StarItemParticle position={[0,0.8, 0.2]} item={item} timeModifier={90} color={0xf0db7f}/>
|
||||||
|
<SmallCircleParticle position={[0,0.8, 0.2]} item={item} timeModifier={50} color={0x75ff9a}/>
|
||||||
|
<SmallCircleParticle position={[0,0.8, 0.2]} item={item} timeModifier={60} color={0xe872fc}/>
|
||||||
|
<SmallCircleParticle position={[0,0.8, 0.2]} item={item} timeModifier={40} color={0x72e5fc}/>
|
||||||
|
<SmallCircleParticle position={[0,0.8, 0.2]} item={item} timeModifier={90} color={0xf0db7f}/>
|
||||||
|
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
import React, { useEffect, useRef } from "react";
|
||||||
|
import { useLoader, useFrame } from "@react-three/fiber";
|
||||||
|
import * as THREE from "three";
|
||||||
|
|
||||||
|
export const SmallCircleParticle = ({ position, item, timeModifier, color }) => {
|
||||||
|
const texture = useLoader(THREE.TextureLoader, "./particles/circle_01.png");
|
||||||
|
const pointsRef = useRef();
|
||||||
|
const materialRef = useRef();
|
||||||
|
const sizeRef = useRef(1);
|
||||||
|
const opacityRef = useRef(1);
|
||||||
|
const originalYpos = useRef(0);
|
||||||
|
|
||||||
|
const points = React.useMemo(() => {
|
||||||
|
const geom = new THREE.BufferGeometry();
|
||||||
|
geom.setAttribute(
|
||||||
|
"position",
|
||||||
|
new THREE.Float32BufferAttribute(position, 3)
|
||||||
|
);
|
||||||
|
return geom;
|
||||||
|
}, [position]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (materialRef.current) {
|
||||||
|
materialRef.current.color.multiplyScalar(6);
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if(item){
|
||||||
|
sizeRef.current = 0;
|
||||||
|
opacityRef.current = 1;
|
||||||
|
pointsRef.current.position.x = Math.random() * 1 - 0.5;
|
||||||
|
pointsRef.current.position.y = Math.random() * 0.5 - 0.25;
|
||||||
|
originalYpos.current = pointsRef.current.position.y;
|
||||||
|
}
|
||||||
|
}, [item]);
|
||||||
|
|
||||||
|
useFrame((state, delta) => {
|
||||||
|
const time = state.clock.getElapsedTime();
|
||||||
|
pointsRef.current.position.y += 0.008 * delta * 144;
|
||||||
|
if (sizeRef.current < 1) {
|
||||||
|
sizeRef.current = Math.min(sizeRef.current + 0.01 * delta * 144, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pointsRef.current.position.y > originalYpos.current + 0.01) {
|
||||||
|
opacityRef.current = Math.max(opacityRef.current - 0.01 * delta * 144, 0);
|
||||||
|
} else {
|
||||||
|
opacityRef.current = Math.abs(Math.sin(time * timeModifier * 1500));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update material properties directly
|
||||||
|
if (materialRef.current) {
|
||||||
|
materialRef.current.size = sizeRef.current;
|
||||||
|
materialRef.current.opacity = opacityRef.current;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<points ref={pointsRef} geometry={points}>
|
||||||
|
<pointsMaterial
|
||||||
|
ref={materialRef}
|
||||||
|
alphaMap={texture}
|
||||||
|
transparent={true}
|
||||||
|
depthWrite={false}
|
||||||
|
toneMapped={false}
|
||||||
|
color={color}
|
||||||
|
/>
|
||||||
|
</points>
|
||||||
|
);
|
||||||
|
};
|
|
@ -0,0 +1,70 @@
|
||||||
|
import React, { useEffect, useRef } from "react";
|
||||||
|
import { useLoader, useFrame } from "@react-three/fiber";
|
||||||
|
import * as THREE from "three";
|
||||||
|
|
||||||
|
export const StarItemParticle = ({ position, item, timeModifier, color }) => {
|
||||||
|
const texture = useLoader(THREE.TextureLoader, "./particles/star_coin.png");
|
||||||
|
const pointsRef = useRef();
|
||||||
|
const materialRef = useRef();
|
||||||
|
const sizeRef = useRef(1);
|
||||||
|
const opacityRef = useRef(1);
|
||||||
|
const originalYpos = useRef(0);
|
||||||
|
|
||||||
|
const points = React.useMemo(() => {
|
||||||
|
const geom = new THREE.BufferGeometry();
|
||||||
|
geom.setAttribute(
|
||||||
|
"position",
|
||||||
|
new THREE.Float32BufferAttribute(position, 3)
|
||||||
|
);
|
||||||
|
return geom;
|
||||||
|
}, [position]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (materialRef.current) {
|
||||||
|
materialRef.current.color.multiplyScalar(6);
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if(item){
|
||||||
|
sizeRef.current = 0;
|
||||||
|
opacityRef.current = 1;
|
||||||
|
pointsRef.current.position.x = Math.random() * 1 - 0.5;
|
||||||
|
pointsRef.current.position.y = Math.random() * 0.5 - 0.25;
|
||||||
|
originalYpos.current = pointsRef.current.position.y;
|
||||||
|
}
|
||||||
|
}, [item]);
|
||||||
|
|
||||||
|
useFrame((state, delta) => {
|
||||||
|
const time = state.clock.getElapsedTime();
|
||||||
|
pointsRef.current.position.y += 0.008 * delta * 144;
|
||||||
|
if (sizeRef.current < 1) {
|
||||||
|
sizeRef.current = Math.min(sizeRef.current + 0.01 * delta * 144, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pointsRef.current.position.y > originalYpos.current + 0.01) {
|
||||||
|
opacityRef.current = Math.max(opacityRef.current - 0.01 * delta * 144, 0);
|
||||||
|
} else {
|
||||||
|
opacityRef.current = Math.abs(Math.sin(time * timeModifier * 1500));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update material properties directly
|
||||||
|
if (materialRef.current) {
|
||||||
|
materialRef.current.size = sizeRef.current;
|
||||||
|
materialRef.current.opacity = opacityRef.current;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<points ref={pointsRef} geometry={points}>
|
||||||
|
<pointsMaterial
|
||||||
|
ref={materialRef}
|
||||||
|
alphaMap={texture}
|
||||||
|
transparent={true}
|
||||||
|
depthWrite={false}
|
||||||
|
toneMapped={false}
|
||||||
|
color={color}
|
||||||
|
/>
|
||||||
|
</points>
|
||||||
|
);
|
||||||
|
};
|
|
@ -14,16 +14,18 @@ import { useRef, useState, useEffect, useCallback } from "react";
|
||||||
import * as THREE from "three";
|
import * as THREE from "three";
|
||||||
|
|
||||||
import { Mario } from "./models/characters/Mario_kart";
|
import { Mario } from "./models/characters/Mario_kart";
|
||||||
import { DriftParticlesLeft } from "./Particles/DriftParticlesLeft";
|
import { DriftParticlesLeft } from "./Particles/drifts/DriftParticlesLeft";
|
||||||
import { DriftParticlesRight } from "./Particles/DriftParticlesRight";
|
import { DriftParticlesRight } from "./Particles/drifts/DriftParticlesRight";
|
||||||
|
|
||||||
import { PointParticle } from "./Particles/PointParticle";
|
import { PointParticle } from "./Particles/drifts/PointParticle";
|
||||||
|
|
||||||
import { FlameParticles } from "./Particles/FlameParticles";
|
import { FlameParticles } from "./Particles/flames/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";
|
import { HitParticles } from "./Particles/hits/HitParticles";
|
||||||
|
import { CoinParticles } from "./Particles/coins/CoinParticles";
|
||||||
|
import { ItemParticles } from "./Particles/items/ItemParticles";
|
||||||
|
|
||||||
export const PlayerController = () => {
|
export const PlayerController = () => {
|
||||||
const upPressed = useKeyboardControls((state) => state[Controls.up]);
|
const upPressed = useKeyboardControls((state) => state[Controls.up]);
|
||||||
|
@ -83,7 +85,7 @@ export const PlayerController = () => {
|
||||||
const effectiveBoost = useRef(0);
|
const effectiveBoost = useRef(0);
|
||||||
|
|
||||||
|
|
||||||
const { actions, shouldSlowDown, item, bananas} = useStore();
|
const { actions, shouldSlowDown, item, bananas, coins} = useStore();
|
||||||
const slowDownDuration = useRef(1500);
|
const slowDownDuration = useRef(1500);
|
||||||
|
|
||||||
|
|
||||||
|
@ -461,7 +463,7 @@ export const PlayerController = () => {
|
||||||
actions.useItem();
|
actions.useItem();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log("coins", coins);
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -497,12 +499,8 @@ export const PlayerController = () => {
|
||||||
steeringAngleWheels={steeringAngleWheels}
|
steeringAngleWheels={steeringAngleWheels}
|
||||||
isBoosting={isBoosting}
|
isBoosting={isBoosting}
|
||||||
/>
|
/>
|
||||||
<pointLight
|
<CoinParticles coins={coins}/>
|
||||||
position={[0.6, 0.05, 0.5]}
|
<ItemParticles item={item}/>
|
||||||
intensity={scale}
|
|
||||||
color={turboColor}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<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
|
||||||
|
@ -522,11 +520,6 @@ export const PlayerController = () => {
|
||||||
glowSharpness={1}
|
glowSharpness={1}
|
||||||
/>
|
/>
|
||||||
</mesh>
|
</mesh>
|
||||||
<pointLight
|
|
||||||
position={[-0.6, 0.05, 0.5]}
|
|
||||||
intensity={scale}
|
|
||||||
color={turboColor}
|
|
||||||
/>
|
|
||||||
<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
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
Auto-generated by: https://github.com/pmndrs/gltfjsx
|
||||||
|
Command: npx gltfjsx@6.2.16 .\gift.glb --shadows --transform
|
||||||
|
Files: .\gift.glb [694.14KB] > C:\Users\mouli\dev\r3f-vite-starter\public\models\misc\gift-transformed.glb [86.34KB] (88%)
|
||||||
|
Author: gorzi (https://sketchfab.com/gorzi90)
|
||||||
|
License: CC-BY-4.0 (http://creativecommons.org/licenses/by/4.0/)
|
||||||
|
Source: https://sketchfab.com/3d-models/gift-f3d8abcd3b9442f39a9a2017d59b56a1
|
||||||
|
Title: Gift
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React, { useRef } from 'react'
|
||||||
|
import { useGLTF, Float } from '@react-three/drei'
|
||||||
|
import { CuboidCollider, RigidBody } from "@react-three/rapier";
|
||||||
|
import { useStore } from "../../store";
|
||||||
|
import { useFrame } from '@react-three/fiber';
|
||||||
|
|
||||||
|
export function ItemBox(props) {
|
||||||
|
const { nodes, materials } = useGLTF('./models/misc/gift-transformed.glb');
|
||||||
|
const { actions } = useStore();
|
||||||
|
const ref = useRef();
|
||||||
|
const [scale, setScale] = React.useState(0.6);
|
||||||
|
const frames = useRef(0);
|
||||||
|
const body = useRef();
|
||||||
|
useFrame((state, delta) => {
|
||||||
|
const time = state.clock.getElapsedTime();
|
||||||
|
ref.current.position.y = Math.sin(time) * 0.1 + 2.5;
|
||||||
|
ref.current.rotation.x = Math.sin(time) * 0.1;
|
||||||
|
ref.current.rotation.y += delta;
|
||||||
|
ref.current.rotation.z = Math.sin(time) * 0.5;
|
||||||
|
if(scale < 0.6 && frames.current > 0){
|
||||||
|
frames.current -= 1 * delta * 144;
|
||||||
|
|
||||||
|
}
|
||||||
|
if(frames.current <= 0){
|
||||||
|
setScale(Math.min(scale + 0.5 * delta, 0.6));
|
||||||
|
if(body.current){
|
||||||
|
body.current.setEnabled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<RigidBody type="fixed" name="itemBox"
|
||||||
|
sensor
|
||||||
|
ref={body}
|
||||||
|
onIntersectionEnter={({other}) => {
|
||||||
|
if(other.rigidBodyObject.name === "player"){
|
||||||
|
|
||||||
|
console.log("item box hit");
|
||||||
|
actions.setItem();
|
||||||
|
setScale(0);
|
||||||
|
frames.current = 400;
|
||||||
|
body.current.setEnabled(false);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
position={props.position}
|
||||||
|
colliders={false}
|
||||||
|
>
|
||||||
|
<CuboidCollider args={[1.5, 1.5, 1.5]} />
|
||||||
|
</RigidBody>
|
||||||
|
<group ref={ref} position={props.position} scale={scale} dispose={null}>
|
||||||
|
<mesh castShadow receiveShadow geometry={nodes.Cube000.geometry} material={materials.Material} position={[0.077, 0.5, -0.019]} rotation={[-Math.PI / 2, 0, 0]} />
|
||||||
|
<mesh castShadow receiveShadow geometry={nodes.Cube000_1.geometry} material={materials['Material.001']} position={[0.077, 0.5, -0.019]} rotation={[-Math.PI / 2, 0, 0]} />
|
||||||
|
</group>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
useGLTF.preload('./models/misc/gift-transformed.glb')
|
|
@ -8,30 +8,64 @@ Source: https://sketchfab.com/3d-models/super-mario-bros-coin-aa97e093847a439f9f
|
||||||
Title: Super Mario Bros Coin
|
Title: Super Mario Bros Coin
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { useEffect, useRef } from 'react'
|
import React, { useEffect, useRef } from "react";
|
||||||
import { useGLTF, useAnimations } from '@react-three/drei'
|
import { useGLTF, useAnimations } from "@react-three/drei";
|
||||||
import { useFrame } from '@react-three/fiber'
|
import { useFrame } from "@react-three/fiber";
|
||||||
|
import { RigidBody } from "@react-three/rapier";
|
||||||
|
import { useStore } from "../../store";
|
||||||
|
|
||||||
export function Coin(props) {
|
export function Coin(props) {
|
||||||
const group = useRef()
|
const group = useRef();
|
||||||
const { nodes, materials, animations } = useGLTF('./models/misc/super_mario_bros_coin-transformed.glb')
|
const { nodes, materials } = useGLTF(
|
||||||
const { actions } = useAnimations(animations, group)
|
"./models/misc/super_mario_bros_coin-transformed.glb"
|
||||||
|
);
|
||||||
|
const { actions } = useStore();
|
||||||
|
const [scale, setScale] = React.useState(0.424);
|
||||||
|
const frames = useRef(0);
|
||||||
useFrame((state, delta) => {
|
useFrame((state, delta) => {
|
||||||
group.current.rotation.y += 4 * delta
|
|
||||||
})
|
group.current.rotation.y += 4 * delta;
|
||||||
|
if(scale < 0.424 && frames.current > 0){
|
||||||
|
frames.current -= 1 * delta * 144;
|
||||||
|
|
||||||
|
}
|
||||||
|
if(frames.current <= 0){
|
||||||
|
setScale(Math.min(scale + 0.5 * delta, 0.424));
|
||||||
|
if(body.current){
|
||||||
|
body.current.setEnable(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const body = useRef();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<group ref={group} {...props} dispose={null}>
|
<>
|
||||||
<group name="Sketchfab_Scene">
|
<RigidBody
|
||||||
<group name="RootNode" scale={0.588}>
|
type="fixed"
|
||||||
<group name="Coin" scale={0.424}>
|
name="coin"
|
||||||
<mesh name="Coin_CoinBlinn_0" castShadow receiveShadow geometry={nodes.Coin_CoinBlinn_0.geometry} material={materials.CoinBlinn} />
|
sensor
|
||||||
</group>
|
onIntersectionEnter={({ manifold, target, other}) => {
|
||||||
</group>
|
if(other.rigidBodyObject.name === "player"){
|
||||||
</group>
|
actions.addCoins();
|
||||||
</group>
|
setScale(0);
|
||||||
)
|
frames.current = 600;
|
||||||
|
body.current.setEnable(false);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
position={props.position}
|
||||||
|
>
|
||||||
|
<mesh
|
||||||
|
ref={group}
|
||||||
|
castShadow
|
||||||
|
receiveShadow
|
||||||
|
geometry={nodes.Coin_CoinBlinn_0.geometry}
|
||||||
|
material={materials.CoinBlinn}
|
||||||
|
scale={scale}
|
||||||
|
/>
|
||||||
|
</RigidBody>
|
||||||
|
</>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
useGLTF.preload('./models/misc/super_mario_bros_coin-transformed.glb')
|
useGLTF.preload("./models/misc/super_mario_bros_coin-transformed.glb");
|
||||||
|
|
|
@ -24,6 +24,7 @@ export const useStore = create((set, get) => ({
|
||||||
item: "",
|
item: "",
|
||||||
shells: [],
|
shells: [],
|
||||||
skids: [],
|
skids: [],
|
||||||
|
coins : 0,
|
||||||
addPastPosition: (position) => {
|
addPastPosition: (position) => {
|
||||||
set((state) => ({
|
set((state) => ({
|
||||||
pastPositions: [position, ...state.pastPositions.slice(0, 499)],
|
pastPositions: [position, ...state.pastPositions.slice(0, 499)],
|
||||||
|
@ -111,6 +112,16 @@ export const useStore = create((set, get) => ({
|
||||||
skids: [...state.skids, skid],
|
skids: [...state.skids, skid],
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
|
addCoins : () => {
|
||||||
|
set((state) => ({
|
||||||
|
coins: state.coins + 1,
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
looseCoins : () => {
|
||||||
|
set((state) => ({
|
||||||
|
coins: state.coins - 1,
|
||||||
|
}));
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
}));
|
}));
|
||||||
|
|
|
@ -39,6 +39,7 @@ pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo{
|
.logo{
|
||||||
|
display: none;
|
||||||
position:absolute;
|
position:absolute;
|
||||||
top:150px;
|
top:150px;
|
||||||
left:500px;
|
left:500px;
|
||||||
|
|
|
@ -7,6 +7,6 @@ import { HUD } from './HUD'
|
||||||
ReactDOM.createRoot(document.getElementById('root')).render(
|
ReactDOM.createRoot(document.getElementById('root')).render(
|
||||||
<React.StrictMode>
|
<React.StrictMode>
|
||||||
<App />
|
<App />
|
||||||
{/* <HUD /> */}
|
<HUD />
|
||||||
</React.StrictMode>,
|
</React.StrictMode>,
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in New Issue