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 (
|
||||
<>
|
||||
<Loader />
|
||||
<Canvas
|
||||
shadows
|
||||
dpr={1}
|
||||
gl={{ antialias: false, stencil: false, powerPreference: 'high-performance' }}
|
||||
>
|
||||
<Suspense fallback={null}>
|
||||
<Preload all />
|
||||
<Physics
|
||||
gravity={[0, -90, 0]}
|
||||
timeStep={'vary'}
|
||||
// debug
|
||||
>
|
||||
<KeyboardControls map={map}>
|
||||
<Experience />
|
||||
</KeyboardControls>
|
||||
<Stats />
|
||||
</Physics>
|
||||
</Suspense>
|
||||
</Canvas>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ import {
|
|||
Vignette,
|
||||
} from "@react-three/postprocessing";
|
||||
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 { Shell } from "./models/items/Mario_shell_red";
|
||||
import { Coin } from "./models/misc/Super_mario_bros_coin";
|
||||
|
@ -36,7 +36,7 @@ export const Experience = () => {
|
|||
<Paris position={[0, 0, 0]} />
|
||||
<Banana onCollide={onCollide} position={[-10, 1.8, -119]} />
|
||||
{/* <Shell position={[-20, 2, -119]} /> */}
|
||||
<ItemBox position={[-20, 2, -119]} />
|
||||
<ItemBox position={[-20, 2.5, -119]} />
|
||||
<Coin position={[-30, 2, -119]} />
|
||||
|
||||
<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 { Mario } from "./models/characters/Mario_kart";
|
||||
import { DriftParticlesLeft } from "./Particles/DriftParticlesLeft";
|
||||
import { DriftParticlesRight } from "./Particles/DriftParticlesRight";
|
||||
import { DriftParticlesLeft } from "./Particles/drifts/DriftParticlesLeft";
|
||||
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 { Cylinder } from "@react-three/drei";
|
||||
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 = () => {
|
||||
const upPressed = useKeyboardControls((state) => state[Controls.up]);
|
||||
|
@ -83,7 +85,7 @@ export const PlayerController = () => {
|
|||
const effectiveBoost = useRef(0);
|
||||
|
||||
|
||||
const { actions, shouldSlowDown, item, bananas} = useStore();
|
||||
const { actions, shouldSlowDown, item, bananas, coins} = useStore();
|
||||
const slowDownDuration = useRef(1500);
|
||||
|
||||
|
||||
|
@ -461,7 +463,7 @@ export const PlayerController = () => {
|
|||
actions.useItem();
|
||||
}
|
||||
|
||||
|
||||
console.log("coins", coins);
|
||||
});
|
||||
|
||||
return (
|
||||
|
@ -497,12 +499,8 @@ export const PlayerController = () => {
|
|||
steeringAngleWheels={steeringAngleWheels}
|
||||
isBoosting={isBoosting}
|
||||
/>
|
||||
<pointLight
|
||||
position={[0.6, 0.05, 0.5]}
|
||||
intensity={scale}
|
||||
color={turboColor}
|
||||
/>
|
||||
|
||||
<CoinParticles coins={coins}/>
|
||||
<ItemParticles item={item}/>
|
||||
<mesh position={[0.6, 0.05, 0.5]} scale={scale}>
|
||||
<sphereGeometry args={[0.05, 16, 16]} />
|
||||
<meshStandardMaterial
|
||||
|
@ -522,11 +520,6 @@ export const PlayerController = () => {
|
|||
glowSharpness={1}
|
||||
/>
|
||||
</mesh>
|
||||
<pointLight
|
||||
position={[-0.6, 0.05, 0.5]}
|
||||
intensity={scale}
|
||||
color={turboColor}
|
||||
/>
|
||||
<mesh position={[-0.6, 0.05, 0.5]} scale={scale}>
|
||||
<sphereGeometry args={[0.05, 16, 16]} />
|
||||
<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
|
||||
*/
|
||||
|
||||
import React, { useEffect, useRef } from 'react'
|
||||
import { useGLTF, useAnimations } from '@react-three/drei'
|
||||
import { useFrame } from '@react-three/fiber'
|
||||
import React, { useEffect, useRef } from "react";
|
||||
import { useGLTF, useAnimations } from "@react-three/drei";
|
||||
import { useFrame } from "@react-three/fiber";
|
||||
import { RigidBody } from "@react-three/rapier";
|
||||
import { useStore } from "../../store";
|
||||
|
||||
export function Coin(props) {
|
||||
const group = useRef()
|
||||
const { nodes, materials, animations } = useGLTF('./models/misc/super_mario_bros_coin-transformed.glb')
|
||||
const { actions } = useAnimations(animations, group)
|
||||
|
||||
const group = useRef();
|
||||
const { nodes, materials } = useGLTF(
|
||||
"./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) => {
|
||||
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 (
|
||||
<group ref={group} {...props} dispose={null}>
|
||||
<group name="Sketchfab_Scene">
|
||||
<group name="RootNode" scale={0.588}>
|
||||
<group name="Coin" scale={0.424}>
|
||||
<mesh name="Coin_CoinBlinn_0" castShadow receiveShadow geometry={nodes.Coin_CoinBlinn_0.geometry} material={materials.CoinBlinn} />
|
||||
</group>
|
||||
</group>
|
||||
</group>
|
||||
</group>
|
||||
)
|
||||
<>
|
||||
<RigidBody
|
||||
type="fixed"
|
||||
name="coin"
|
||||
sensor
|
||||
onIntersectionEnter={({ manifold, target, other}) => {
|
||||
if(other.rigidBodyObject.name === "player"){
|
||||
actions.addCoins();
|
||||
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: "",
|
||||
shells: [],
|
||||
skids: [],
|
||||
coins : 0,
|
||||
addPastPosition: (position) => {
|
||||
set((state) => ({
|
||||
pastPositions: [position, ...state.pastPositions.slice(0, 499)],
|
||||
|
@ -111,6 +112,16 @@ export const useStore = create((set, get) => ({
|
|||
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{
|
||||
display: none;
|
||||
position:absolute;
|
||||
top:150px;
|
||||
left:500px;
|
||||
|
|
|
@ -7,6 +7,6 @@ import { HUD } from './HUD'
|
|||
ReactDOM.createRoot(document.getElementById('root')).render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
{/* <HUD /> */}
|
||||
<HUD />
|
||||
</React.StrictMode>,
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue