Compare commits

..

1 Commits

Author SHA1 Message Date
Alex a8cf0d1ca4 message 2024-01-26 14:07:58 +01:00
108 changed files with 515 additions and 47816 deletions

View File

@ -1,27 +0,0 @@
{
"name": "Mario Kart Dev Container",
"image": "mcr.microsoft.com/devcontainers/javascript-node",
"customizations": {
"vscode": {
"extensions": [
"eamodio.gitlens",
"esbenp.prettier-vscode",
"VisualStudioExptTeam.vscodeintellicode",
"dbaeumer.vscode-eslint",
"dsznajder.es7-react-js-snippets",
"antfu.vite",
"meganrogge.template-string-converter",
"ambar.bundle-size",
"aaron-bond.better-comments"
]
}
},
"forwardPorts": [4000],
"portsAttributes": {
"4000": {
"label": "Application",
"onAutoForward": "notify"
}
},
"postCreateCommand": "npm install"
}

View File

@ -1,7 +0,0 @@
{
"$schema": "https://triplex.dev/config.schema.json",
"components": ["../src/components/**/*.(j|t)sx"],
"files": ["../src/components/**/*.(j|t)sx"],
"provider": "./provider.tsx",
"assetsDir": "models"
}

View File

@ -1,16 +0,0 @@
import React from "react";
import { Physics } from "@react-three/rapier";
export default function Provider({
children,
physicsDisabled = true,
}: {
children: React.ReactNode;
physicsDisabled?: boolean;
}) {
return (
<Physics gravity={[0, -90, 0]} timeStep="vary" paused={physicsDisabled}>
{children}
</Physics>
);
}

21
LICENSE
View File

@ -1,21 +0,0 @@
MIT License
Copyright (c) [2022] [Ron Waller]
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1,94 +0,0 @@
# Mario Kart 3.js - JavaScript/WebGL Mario Kart
[Link](https://mario-kart-3-js.vercel.app/)
[![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/Lunakepio/Mario-Kart-3.js)
DISCLAIMER : This is not a completed project, I would say around 50% of the work has been done up to now. It takes a lot of time so please enjoy.
## How to install
Fork the repository
Clone the repository or download it
Open your terminal and inside the project folder, run :
```bash
npm install
```
Start the dev server
```bash
npm run dev
```
## How to use (Gameplay)
- Use the <kbd>W</kbd> key to accelerate, the mouse to steer for now (will be updated for mobile/gamepad/keyboard).
- Steer with the mouse.
- Press and hold the space bar to initiate a drift. Steer and counter steer to maintain the drift. release it to get a mini - turbo.
- Press <kbd>E</kbd> key to use the current item.
- Press <kbd>R</kbd> to reset your position, usable anytime.
## How to use (Code)
- Anything needs update.
- You can also edit the README to add elements to the To-do List.
- Feel free to bring your ideas to the project even if you can't code them.
## How to use (Editor)
- [Download Triplex](https://triplex.dev/download)
- Open this project in Triplex from the projects root directory
- Iterate on individual components, set props, have some fun
- [Learn more about Triplex](https://triplex.dev/docs/get-started/user-interface)
## TO - DO
- [ ] Design Landing page
- [ ] Add items
- [ ] Add texture to the flame shaders
- [ ] Add curve/length modifiers to drift particles 3/4
- [ ] Add Skid marks
- [x] Add smokes
- [ ] Add wind screen effect when boosting
- [ ] Improve sound design quality
- [ ] Design UI for HUD
- [ ] Make Time Trial mode
- [ ] Design tracks and checkpoints
- [ ] Improve code quality
- [ ] Add Minimap
- [ ] Items
- [ ] Tennis ball
- [ ] Bomb
- [ ] Real red shell
- [ ] Treats
- [ ] ?
## License
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

46
mario_kart.tsx Normal file
View File

@ -0,0 +1,46 @@
/*
Auto-generated by: https://github.com/pmndrs/gltfjsx
Command: npx gltfjsx@6.2.16 c:\Users\mouli\Downloads\mario_kart.glb -o c:\Users\mouli\Desktop\mario_kart.tsx --types
Author: TheShibeLord (https://sketchfab.com/TheShibeLord)
License: CC-BY-4.0 (http://creativecommons.org/licenses/by/4.0/)
Source: https://sketchfab.com/3d-models/mario-kart-66cc131575344ab69238ec5872f24927
Title: Mario Kart
*/
import * as THREE from 'three'
import React, { useRef } from 'react'
import { useGLTF } from '@react-three/drei'
import { GLTF } from 'three-stdlib'
type GLTFResult = GLTF & {
nodes: {
mt_mario: THREE.Mesh
mt_kart_Mario_S: THREE.Mesh
mt_Kart_Mario_Tire_S: THREE.Mesh
}
materials: {
mt_mario: THREE.MeshStandardMaterial
mt_kart_Mario_S: THREE.MeshStandardMaterial
mt_Kart_Mario_Tire_S: THREE.MeshStandardMaterial
}
animations: GLTFAction[]
}
type ContextType = Record<string, React.ForwardRefExoticComponent<JSX.IntrinsicElements['mesh']>>
export function Model(props: JSX.IntrinsicElements['group']) {
const { nodes, materials } = useGLTF('/mario_kart.glb') as GLTFResult
return (
<group {...props} dispose={null}>
<group rotation={[-Math.PI / 2, 0, 0]}>
<group rotation={[Math.PI / 2, 0, 0]}>
<mesh geometry={nodes.mt_mario.geometry} material={materials.mt_mario} />
<mesh geometry={nodes.mt_kart_Mario_S.geometry} material={materials.mt_kart_Mario_S} />
<mesh geometry={nodes.mt_Kart_Mario_Tire_S.geometry} material={materials.mt_Kart_Mario_Tire_S} />
</group>
</group>
</group>
)
}
useGLTF.preload('/mario_kart.glb')

52
package-lock.json generated
View File

@ -13,14 +13,11 @@
"@react-three/postprocessing": "^2.15.11",
"@react-three/rapier": "^1.2.1",
"gsap": "^3.12.5",
"joymap": "^2.2.4",
"leva": "^0.9.35",
"playroomkit": "^0.0.66",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-gamepad": "^1.0.3",
"react-joystick-component": "^6.2.1",
"three": "^0.160.1",
"three-mesh-bvh": "^0.7.0",
"zustand": "^4.5.0"
},
"devDependencies": {
@ -1397,9 +1394,9 @@
"peer": true
},
"node_modules/@types/three": {
"version": "0.161.2",
"resolved": "https://registry.npmjs.org/@types/three/-/three-0.161.2.tgz",
"integrity": "sha512-DazpZ+cIfBzbW/p0zm6G8CS03HBMd748A3R1ZOXHpqaXZLv2I5zNgQUrRG//UfJ6zYFp2cUoCQaOLaz8ubH07w==",
"version": "0.160.0",
"resolved": "https://registry.npmjs.org/@types/three/-/three-0.160.0.tgz",
"integrity": "sha512-jWlbUBovicUKaOYxzgkLlhkiEQJkhCVvg4W2IYD2trqD2om3VK4DGLpHH5zQHNr7RweZK/5re/4IVhbhvxbV9w==",
"peer": true,
"dependencies": {
"@types/stats.js": "*",
@ -1865,6 +1862,11 @@
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
},
"node_modules/fast-memoize": {
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/fast-memoize/-/fast-memoize-2.5.2.tgz",
"integrity": "sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw=="
},
"node_modules/fflate": {
"version": "0.6.10",
"resolved": "https://registry.npmjs.org/fflate/-/fflate-0.6.10.tgz",
@ -2143,6 +2145,16 @@
"@types/react": "*"
}
},
"node_modules/joymap": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/joymap/-/joymap-2.2.4.tgz",
"integrity": "sha512-5N0VMbym49AwrfUz0vD6tE++I50SFjBYtwcJsdgE086GgAraGB2YQFsgVj+cG2fd8eUFmK+8U36Ecud3/UYTRg==",
"dependencies": {
"@babel/runtime": "^7.9.2",
"fast-memoize": "^2.5.2",
"lodash": "^4.17.15"
}
},
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@ -2425,15 +2437,6 @@
"integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
"dev": true
},
"node_modules/playroomkit": {
"version": "0.0.66",
"resolved": "https://registry.npmjs.org/playroomkit/-/playroomkit-0.0.66.tgz",
"integrity": "sha512-lBYSLR/0AebQhWteMgkXiMXyMPxMqGz2uptA3QrBig4NCn5r3ViIXWIFmsdbLSG9spKrFPVTaYRClUq3fSCxDw==",
"peerDependencies": {
"react": ">=17.0.2 <= 18",
"react-dom": ">=17.0.2 <= 18"
}
},
"node_modules/postcss": {
"version": "8.4.33",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.33.tgz",
@ -2595,28 +2598,11 @@
"react": ">= 16.8"
}
},
"node_modules/react-gamepad": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/react-gamepad/-/react-gamepad-1.0.3.tgz",
"integrity": "sha512-gMwITmfoHtCaMFpDaEshcjeibHAgynXD28NnS2pa+dG+stwNoN66YDVizN7GfyIrYiW5Ft1ubRxs6/2xW9sRhQ==",
"peerDependencies": {
"react": ">=15.0.0"
}
},
"node_modules/react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
},
"node_modules/react-joystick-component": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/react-joystick-component/-/react-joystick-component-6.2.1.tgz",
"integrity": "sha512-0G5Y5aX4hNuXB3xJCwz6Q+nYQOtC6kprNGKmZxmfoPvhepNYUiid0DbLEGZxmr/UKip3S/LUbcQUobtRCuB8IQ==",
"peerDependencies": {
"react": ">=17.0.2",
"react-dom": ">=17.0.2"
}
},
"node_modules/react-merge-refs": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/react-merge-refs/-/react-merge-refs-1.1.0.tgz",

View File

@ -4,7 +4,7 @@
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite --host",
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
@ -14,14 +14,11 @@
"@react-three/postprocessing": "^2.15.11",
"@react-three/rapier": "^1.2.1",
"gsap": "^3.12.5",
"joymap": "^2.2.4",
"leva": "^0.9.35",
"playroomkit": "^0.0.66",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-gamepad": "^1.0.3",
"react-joystick-component": "^6.2.1",
"three": "^0.160.1",
"three-mesh-bvh": "^0.7.0",
"zustand": "^4.5.0"
},
"devDependencies": {

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 42 KiB

File diff suppressed because it is too large Load Diff

View File

Before

Width:  |  Height:  |  Size: 93 KiB

After

Width:  |  Height:  |  Size: 93 KiB

View File

Before

Width:  |  Height:  |  Size: 82 KiB

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 932 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 500 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 408 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 393 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 510 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 450 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 641 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 35 KiB

View File

@ -1,12 +1,8 @@
import { Canvas } from '@react-three/fiber'
import { Experience } from './components/Experience'
import { Suspense, useEffect, useMemo } from 'react'
import { Suspense, useMemo } from 'react'
import { Physics } from '@react-three/rapier'
import { Environment, KeyboardControls, Loader, OrbitControls, Preload, Stats } from '@react-three/drei'
import { insertCoin, onPlayerJoin } from 'playroomkit'
import { useStore } from "./components/store";
import * as THREE from "three";
import { ParisBis } from './components/models/tracks/Paris-bis'
import { KeyboardControls, Loader, OrbitControls, Preload, Stats } from '@react-three/drei'
export const Controls = {
up: 'up',
@ -16,10 +12,8 @@ export const Controls = {
boost: 'boost',
shoot: 'shoot',
slow: 'slow',
reset: 'reset',
escape: 'escape'
reset: 'reset'
}
function App() {
const map = useMemo(
() => [
@ -30,46 +24,18 @@ function App() {
{ name: Controls.jump, keys: ['Space'] },
{ name: Controls.slow, keys: ['Shift'] },
{ name: Controls.shoot, keys: ['KeyE', 'Click'] },
{ name: Controls.reset, keys: ['KeyR'] },
{ name: Controls.escape, keys: ['Escape']}
{ name: Controls.reset, keys: ['KeyR'] }
],
[]
)
const { actions } = useStore();
const start = async () => {
await insertCoin({ skipLobby: true});
onPlayerJoin((state) => {
actions.addPlayer(state);
actions.setId(state.id);
state.onQuit(() => {
actions.removePlayer(state);
});
});
}
useEffect(() => {
start();
}, [])
return (
<>
<Loader />
<Canvas
// shadows
shadows
dpr={1}
gl={{ antialias: false, stencil: false, depth:false, powerPreference: 'high-performance' }}
mode="concurrent"
onCreated={({ gl, camera }) => {
gl.toneMapping = THREE.AgXToneMapping
gl.setClearColor(0x000000, 0)
}}>
gl={{ antialias: false, stencil: false, powerPreference: 'high-performance' }}
>
<Suspense fallback={null}>
<Preload all />
<Physics
gravity={[0, -90, 0]}
timeStep={'vary'}
@ -77,10 +43,10 @@ function App() {
<KeyboardControls map={map}>
<Experience />
</KeyboardControls>
<Stats />
</Physics>
</Suspense>
</Canvas>
</>
)
}

View File

@ -1,11 +1,7 @@
import React, { useEffect, useRef, useState } from "react";
import { useStore } from "./components/store";
import { Joystick } from "react-joystick-component";
import React, { useEffect, useRef } from "react";
export const HUD = () => {
const wheel = useRef();
const [image, setImage] = useState("");
const { item, gameStarted, actions, controls } = useStore();
useEffect(() => {
const handleMouseMove = (e) => {
@ -27,118 +23,24 @@ export const HUD = () => {
};
}, []);
const handleMove = (e) => {
actions.setJoystickX(e.x);
};
const handleStop = () => {
actions.setJoystickX(0);
};
useEffect(() => {
switch (item) {
case "banana":
setImage("./images/banana.webp");
break;
case "mushroom":
setImage("./images/mushroom.png");
break;
case "shell":
setImage("./images/shell.webp");
break;
default:
setImage("");
}
}, [item]);
return (
<div className="overlay">
{gameStarted && (
<>
<div className="item">
<div className="borderOut">
<div className="borderIn">
<div className="background">
{image && <img src={image} alt="item" width={90} />}
</div>
</div>
</div>
</div>
{controls === "touch" && (
<>
<div className="controls joystick">
<Joystick
size={100}
sticky={false}
baseColor="rgba(255, 255, 255, 0.5)"
stickColor="rgba(255, 255, 255, 0.5)"
move={handleMove}
stop={handleStop}
></Joystick>
</div>
<div
className="controls drift"
onMouseDown={(e) => {
actions.setDriftButton(true);
}}
onMouseUp={(e) => {
actions.setDriftButton(false);
}}
onTouchStart={(e) => {
e.preventDefault();
actions.setDriftButton(true);
}}
onTouchEnd={(e) => {
e.preventDefault();
actions.setDriftButton(false);
}}
>
drift
</div>
<div
className="controls itemButton"
onMouseDown={(e) => {
actions.setItemButton(true);
}}
onMouseUp={(e) => {
actions.setItemButton(false);
}}
onTouchStart={(e) => {
e.preventDefault();
actions.setItemButton(true);
}}
onTouchEnd={(e) => {
e.preventDefault();
actions.setItemButton(false);
}}
>
item
</div>
<div
className="controls menuButton"
onMouseDown={(e) => {
actions.setMenuButton(true);
}}
onMouseUp={(e) => {
actions.setMenuButton(false);
}}
onTouchStart={(e) => {
e.preventDefault();
actions.setMenuButton(true);
}}
onTouchEnd={(e) => {
e.preventDefault();
actions.setMenuButton(false);
}}
>
menu
</div>
</>
)}
</>
)}
<div className="overlay"> dadasd
<div className="logo">
<img src="./logo.png" alt="logo" />
</div>
<div className="wheel">
<img
ref={wheel}
src="./steering_wheel.png"
alt="steering wheel"
className="steering-wheel"
style={{
position: "absolute",
pointerEvents: "none",
transformOrigin: "center",
}}
/>
</div>
</div>
);
};

View File

@ -1,128 +0,0 @@
import React, { useEffect, useRef, useState } from "react";
import { useStore } from "./components/store";
import gsap from "gsap";
export const Landing = () => {
const { gameStarted, actions } = useStore();
const logo = useRef();
const startButton = useRef();
const homeRef = useRef();
const [setupStatus, setSetupStatus] = useState(0);
const [controlStyle, setControlStyle] = useState("");
useEffect(() => {
const tl = gsap.timeline();
if (setupStatus === 0) {
if (logo.current && startButton.current) {
tl.from(logo.current, {
scale: 122,
opacity: 0,
duration: 0,
ease: "power4.out",
})
.to(logo.current, {
scale: 1,
opacity: 1,
duration: 1.5,
ease: "power4.out",
})
.to(startButton.current, {
opacity: 1,
duration: 3,
delay: 1,
ease: "power4.out",
});
}
}
const handleKeyDown = (event) => {
if (event.key === 'Enter') {
setSetupStatus(1);
}
};
document.body.addEventListener('keydown', handleKeyDown);
return () => {
document.body.removeEventListener('keydown', handleKeyDown);
};
}, [setupStatus]);
if (gameStarted) {
return null;
}
return (
<>
{setupStatus === 0 && (
<div className="home" ref={homeRef}>
<div className="logo">
<img ref={logo} src="./logo.png" alt="logo" />
</div>
<div className="start" ref={startButton}>
<button className="start-button"
onClick={() => setSetupStatus(1)}
onKeyDown={(event) => {
if (event.key === 'Enter') {
setSetupStatus(1);
}}} autoFocus>
PRESS ENTER TO START
</button>
</div>
</div>
)}
{setupStatus === 1 && (
<div className="home">
<div className="glassy">
<h1>CHOOSE YOUR CONTROL STYLE</h1>
<div className="articles">
<div className={controlStyle === "keyboard" ? "article selected" : "article"} onClick={() =>
setControlStyle("keyboard")}>
<img src="./images/keyboard.png" alt="keyboard" />
<div className="article_label">
<p>Keyboard</p>
</div>
</div>
<div className={controlStyle === "gamepad" ? "article selected" : "article"} onClick={() =>
setControlStyle("gamepad")}>
<img src="./images/gamepad.png" alt="gamepad" />
<div className="article_label">
<p>Gamepad</p>
</div>
</div>
<div className={controlStyle === "mouseKeyboard" ? "article selected" : "article"} onClick={() =>
setControlStyle("mouseKeyboard")}>
<img src="./images/mousekeyboard.png" alt="mouse & keyboard" />
<div className="article_label">
<p>Mouse & Keyboard</p>
</div>
</div>
<div className={controlStyle === "touch" ? "article selected" : "article"} onClick={() =>
setControlStyle("touch")}>
<img src="./images/mobile.png" alt="mobile" />
<div className="article_label">
<p>Mobile</p>
</div>
</div>
</div>
<div className={controlStyle != "" ? "submit" : "submit disabled"}>
<button
className={controlStyle != "" ? "submit-button" : "submit-button disabled"}
onClick={() => {
actions.setControls(controlStyle);
actions.setGameStarted(true);
}}
>
CONFIRM
</button>
</div>
</div>
</div>
)}
</>
);
};

View File

@ -1,87 +0,0 @@
import { Euler, Object3D, Vector3, Matrix4, DoubleSide, Quaternion, TextureLoader, BackSide } from 'three'
import { useRef, useLayoutEffect } from 'react'
import { useFrame, useLoader } from '@react-three/fiber'
import { vec3 } from '@react-three/rapier'
import { useStore } from './store'
const e = new Euler()
const m = new Matrix4()
const o = new Object3D()
const v = new Vector3()
const q = new Quaternion()
export function Dust({ count = 500, opacity = 0.1, size = 0.6 }) {
const smoke01 = useLoader(TextureLoader, './particles/smokes/smoke_01.png');
const smoke02 = useLoader(TextureLoader, './particles/smokes/smoke_02.png');
const smoke03 = useLoader(TextureLoader, './particles/smokes/smoke_03.png');
const smoke04 = useLoader(TextureLoader, './particles/smokes/smoke_04.png');
const smoke05 = useLoader(TextureLoader, './particles/smokes/smoke_05.png');
const smoke06 = useLoader(TextureLoader, './particles/smokes/smoke_06.png');
const smoke07 = useLoader(TextureLoader, './particles/smokes/smoke_07.png');
const smoke08 = useLoader(TextureLoader, './particles/smokes/smoke_08.png');
const texture = [smoke01, smoke02, smoke03, smoke04, smoke05, smoke06, smoke07, smoke08]
const ref = useRef(null);
const { leftWheel, rightWheel } = useStore();
let index = 0
let time = 0
let i = 0
useFrame((state,delta ) => {
if(!leftWheel && !rightWheel) return;
const rotation = leftWheel.kartRotation;
if (state.clock.getElapsedTime() - time > 0.02 && leftWheel && rightWheel && ref.current && leftWheel.isSpinning) {
time = state.clock.getElapsedTime()
setItemAt(ref.current, rotation, leftWheel, index++);
setItemAt(ref.current, rotation, rightWheel, index++);
if (index === count) index = 0
} else {
// Shrink old one
for (i = 0; i < count; i++) {
const direction = new Vector3(Math.sin(time * 6 + i * 10) , 2, 0);
ref.current.getMatrixAt(i, m)
m.decompose(o.position, q, v)
o.scale.setScalar(Math.max(0, v.x - 0.005))
o.position.addScaledVector(direction, 0.01)
o.updateMatrix()
ref.current.setMatrixAt(i, o.matrix)
ref.current.instanceMatrix.needsUpdate = true
}
}
})
useLayoutEffect(() => {
if(ref.current){
ref.current.geometry.rotateY(-Math.PI / 2)
return () => {
ref.current.geometry.rotateY(Math.PI / 2)
}
}
})
return (
<instancedMesh frustumCulled={false} ref={ref} args={[undefined, undefined, count]}>
<planeGeometry args={[size, size]} />
<meshBasicMaterial color={0xfcebc5} transparent map={smoke01} opacity={1} depthWrite={false} side={DoubleSide} />
</instancedMesh>
)
}
function setItemAt(instances, rotation, body, index) {
const randomOffset = (Math.random() - 0.5) * 0.3 ;
const pos = body.getWorldPosition(v);
o.rotation.set(0, rotation + Math.PI / 2, 0);
pos.x += randomOffset
// pos.y += randomOffset
pos.z += randomOffset
o.position.copy(pos);
o.scale.setScalar(1)
o.updateMatrix()
instances.setMatrixAt(index, o.matrix)
instances.instanceMatrix.needsUpdate = true
}

View File

@ -1,182 +1,21 @@
import {
Environment,
OrbitControls,
PerspectiveCamera,
Lightformer,
Bvh,
} from "@react-three/drei";
import { Ground } from "./Ground";
import { PlayerController } from "./PlayerController";
import { PlayerControllerGamepad } from "./PlayerControllerGamepad";
import { PlayerControllerKeyboard } from "./PlayerControllerKeyboard";
import { PlayerControllerTouch } from "./PlayerControllerTouch";
import { Paris } from "./models/tracks/Tour_paris_promenade";
import {
EffectComposer,
N8AO,
Bloom,
TiltShift2,
HueSaturation,
SMAA,
ChromaticAberration,
Vignette,
LUT,
} from "@react-three/postprocessing";
import { Banana } from "./models/items/Banana_peel_mario_kart";
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";
import {
RPC,
getState,
insertCoin,
isHost,
myPlayer,
onPlayerJoin,
useMultiplayerState,
} from "playroomkit";
import { PlayerDummies } from "./PlayerDummies";
import { useEffect, useState, useRef } from "react";
import { useFrame, useLoader } from "@react-three/fiber";
import { LUTPass, LUTCubeLoader } from "three-stdlib";
import { useCurvedPathPoints } from "./useCurvedPath";
import { ParisBis } from "./models/tracks/Paris-bis";
import { Skid } from "./Skid";
import { Dust } from "./Dust";
import { Environment, OrbitControls, PerspectiveCamera, Lightformer } 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'
export const Experience = () => {
const onCollide = (event) => {};
const { gameStarted, bananas, shells, players, id, actions, controls } =
useStore();
const [networkBananas, setNetworkBananas] = useMultiplayerState(
"bananas",
[]
);
const { points, loading, error } = useCurvedPathPoints("./CurvedPath.json");
const [networkShells, setNetworkShells] = useMultiplayerState("shells", []);
const [pointest, setPointest] = useState([]);
const [currentPoint, setCurrentPoint] = useState(0);
useEffect(() => {
if (points) {
//This is adjusted to Paris scale
const scaledPoints = points.map((point) => ({
x: point.x * 50,
y: point.y * 50,
z: point.z * 50,
}));
setPointest(scaledPoints.reverse());
}
}, [points]);
const testing = getState("bananas");
const cam = useRef();
const lookAtTarget = useRef();
// useEffect(() => {
// setNetworkBananas(bananas);
// }, [bananas]);
// useEffect(() => {
// setNetworkShells(shells);
// }, [shells]);
const speedFactor = 5;
const { texture } = useLoader(LUTCubeLoader, "./cubicle-99.CUBE");
useFrame((state, delta) => {
if (!gameStarted) {
const camera = cam.current;
if (currentPoint < pointest.length - 1) {
camera.position.lerp(pointest[currentPoint], delta * speedFactor);
lookAtTarget.current.position.lerp(
pointest[currentPoint + 1],
delta * speedFactor
);
camera.lookAt(lookAtTarget.current.position);
if (camera.position.distanceTo(pointest[currentPoint]) < 5) {
setCurrentPoint(currentPoint + 1);
}
} else {
setCurrentPoint(0);
}
}
});
return (
<>
{gameStarted &&
players.map((player) => {
const ControllerComponent =
controls === "keyboard"
? PlayerControllerKeyboard
: controls === "gamepad"
? PlayerControllerGamepad
: controls === "touch"
? PlayerControllerTouch
: PlayerController;
return (
<ControllerComponent
key={player.id}
player={player}
userPlayer={player.id === myPlayer()?.id}
setNetworkBananas={setNetworkBananas}
setNetworkShells={setNetworkShells}
networkBananas={networkBananas}
networkShells={networkShells}
/>
);
})}
{gameStarted &&
players.map((player) => (
<PlayerDummies
key={player.id}
player={player}
userPlayer={player.id === myPlayer()?.id}
/>
))}
{!gameStarted && (
<>
<mesh ref={lookAtTarget}></mesh>
<PerspectiveCamera
ref={cam}
makeDefault
position={[0, 2, 0]}
far={5000}
/>
</>
)}
{/* <Paris position={[0, 0, 0]} /> */}
<ParisBis position={[0, 0, 0]} />
<ItemBox position={[-20, 2.5, -119]} />
<Coin position={[-30, 2, -119]} />
<Skid />
<Dust />
<PlayerController />
{/* <Skid /> */}
<Ground position={[0, 0, 0]} />
<Environment resolution={256} preset="lobby" />
{networkBananas.map((banana) => (
<Banana
key={banana.id}
position={banana.position}
setNetworkBananas={setNetworkBananas}
networkBananas={networkBananas}
id={banana.id}
/>
))}
{networkShells.map((shell) => (
<Shell
key={shell.id}
id={shell.id}
position={shell.position}
rotation={shell.rotation}
setNetworkShells={setNetworkShells}
networkShells={networkShells}
/>
))}
<Environment
resolution={256}
preset='lobby'
/>
<directionalLight
position={[10, 50, -30]}
@ -186,29 +25,32 @@ export const Experience = () => {
shadow-camera-left={-300}
shadow-camera-right={300}
shadow-camera-top={300}
shadow-camera-bottom={-300}
shadow-camera-bottom={-3000}
castShadow
/>
<Paris position={[0, 0, 0]} />
<EffectComposer
multisampling={0}
disableNormalPass
disableSSAO
disableDepthPass
>
<SMAA />
{/* <N8AO distanceFalloff={1} aoRadius={1} intensity={3} /> */}
<N8AO distanceFalloff={1} aoRadius={1} intensity={3} />
<Bloom
luminanceThreshold={0}
mipmapBlur
luminanceSmoothing={0.01}
intensity={0.5}
/>
<TiltShift2 />
{/* <ChromaticAberration offset={[0.0006, 0.0006]} /> */}
<HueSaturation saturation={0.05} />
{/* <Vignette eskil={false} offset={0.1} darkness={0.4} /> */}
<TiltShift2/>
<ChromaticAberration offset={[0.0006, 0.0006]} />
<HueSaturation saturation={0.1} />
<Vignette eskil={false} offset={0.1} darkness={0.4} />
</EffectComposer>
</>
);
};
)
}

View File

@ -10,23 +10,15 @@ export const DriftParticlesLeft = ({turboColor,scale, ...props}) => {
return (
<group {...props}>
<Particles1 turboColor={turboColor} scale={scale} />
{/* <Particles1 turboColor={turboColor} scale={scale} />
<Particles1 turboColor={turboColor} scale={scale} />
<Particles1 turboColor={turboColor} scale={scale} />
<Particles1 turboColor={turboColor} scale={scale} />
<Particles1 turboColor={turboColor} scale={scale} />
<Particles1 turboColor={turboColor} scale={scale} />
<Particles1 turboColor={turboColor} scale={scale} />
<Particles1 turboColor={turboColor} scale={scale} />
<Particles1 turboColor={turboColor} scale={scale} />
<Particles1 turboColor={turboColor} scale={scale} />
<Particles1 turboColor={turboColor} scale={scale} />
<Particles1 turboColor={turboColor} scale={scale} />
<Particles1 turboColor={turboColor} scale={scale} />
<Particles1 turboColor={turboColor} scale={scale} />
<Particles1 turboColor={turboColor} scale={scale} />
<Particles1 turboColor={turboColor} scale={scale} />
<Particles1 turboColor={turboColor} scale={scale} />
<Particles1 turboColor={turboColor} scale={scale} />
<Particles1 turboColor={turboColor} scale={scale} /> */}
{/* <Particles3 turboColor={turboColor} scale={scale} /> */}
</group>

View File

@ -0,0 +1,16 @@
import { Particles2 } from "./Particles2";
import { Particles4 } from "./Particles4";
export const DriftParticlesRight = ({turboColor,scale, ...props}) => {
// if(scale < 0.8) {
// return null;
// }
return (
<group {...props}>
<Particles2 turboColor={turboColor} scale={scale} />
</group>
)
}

View File

@ -58,7 +58,7 @@ export const FlameParticle = ({ position, png, isBoosting, delay = 0 }) => {
alphaMap={texture}
transparent={true}
depthWrite={false}
color={0xff9900}
color={0x000000}
opacity={1}
toneMapped={false}
/>

View File

@ -0,0 +1,57 @@
import { useRef, useMemo } from "react";
import { useFrame } from "@react-three/fiber";
import * as THREE from 'three';
export const Particles1 = ({ turboColor, scale, numParticles = 50, ...props }) => {
const instancedMeshRef = useRef();
const particlesData = useMemo(() => {
return new Array(numParticles).fill().map(() => ({
position: new THREE.Vector3(-0.6, 0.05, 0.5),
velocity: new THREE.Vector3(-Math.random() * 0.05, Math.random() * 0.05, Math.random() * 0.02),
gravity: -0.003
}));
}, [numParticles]);
useFrame((state, delta) => {
if (!instancedMeshRef.current) {
return;
}
// Manage visibility directly in the animation loop
instancedMeshRef.current.visible = scale >= 0.8;
if (scale < 0.8) {
return;
}
const deltaScaled = delta * 144; // Scale for 144 FPS
particlesData.forEach((particle, i) => {
particle.velocity.y += particle.gravity * deltaScaled;
particle.position.x += particle.velocity.x * deltaScaled;
particle.position.y += particle.velocity.y * deltaScaled;
particle.position.z += particle.velocity.z * deltaScaled;
if (particle.position.y < 0.05) {
particle.position.set(-0.6, 0.05, 0.5);
particle.velocity.set(-Math.random() * 0.05, Math.random() * 0.05, Math.random() * 0.02);
}
const matrix = new THREE.Matrix4();
matrix.setPosition(particle.position);
instancedMeshRef.current.setMatrixAt(i, matrix);
});
instancedMeshRef.current.instanceMatrix.needsUpdate = true;
});
return (
<instancedMesh ref={instancedMeshRef} args={[null, null, numParticles]} visible={scale >= 0.8}>
<sphereGeometry args={[0.01, 16, 16]} />
<meshStandardMaterial
emissive={turboColor}
toneMapped={false}
emissiveIntensity={5}
/>
</instancedMesh>
);
};

View File

@ -0,0 +1,57 @@
import { useRef, useMemo } from "react";
import { useFrame } from "@react-three/fiber";
import * as THREE from 'three';
export const Particles2 = ({ turboColor, scale, numParticles = 50, ...props }) => {
const instancedMeshRef = useRef();
const particlesData = useMemo(() => {
return new Array(numParticles).fill().map(() => ({
position: new THREE.Vector3(0.6, 0.05, 0.5),
velocity: new THREE.Vector3(Math.random() * 0.05, Math.random() * 0.05, Math.random() * 0.02),
gravity: -0.003
}));
}, [numParticles]);
useFrame((state, delta) => {
if (!instancedMeshRef.current) {
return;
}
// Manage visibility directly in the animation loop
instancedMeshRef.current.visible = scale >= 0.8;
if (scale < 0.8) {
return;
}
const deltaScaled = delta * 144; // Scale for 144 FPS
particlesData.forEach((particle, i) => {
particle.velocity.y += particle.gravity * deltaScaled;
particle.position.x += particle.velocity.x * deltaScaled;
particle.position.y += particle.velocity.y * deltaScaled;
particle.position.z += particle.velocity.z * deltaScaled;
if (particle.position.y < 0.05) {
particle.position.set(0.6, 0.05, 0.5);
particle.velocity.set(Math.random() * 0.05, Math.random() * 0.05, Math.random() * 0.02);
}
const matrix = new THREE.Matrix4();
matrix.setPosition(particle.position);
instancedMeshRef.current.setMatrixAt(i, matrix);
});
instancedMeshRef.current.instanceMatrix.needsUpdate = true;
});
return (
<instancedMesh ref={instancedMeshRef} args={[null, null, numParticles]} visible={scale >= 0.8}>
<sphereGeometry args={[0.01, 16, 16]} />
<meshStandardMaterial
emissive={turboColor}
toneMapped={false}
emissiveIntensity={5}
/>
</instancedMesh>
);
};

View File

@ -5,7 +5,6 @@ import * as THREE from "three";
export const PointParticle = ({ position, png, turboColor }) => {
const texture = useLoader(THREE.TextureLoader, png);
const pointsRef = useRef();
const materialRef = useRef();
const [size, setSize] = useState(0);
const [opacity, setOpacity] = useState(1);
@ -19,9 +18,7 @@ export const PointParticle = ({ position, png, turboColor }) => {
}, [position]);
useEffect(() => {
if (materialRef.current) {
materialRef.current.color.multiplyScalar(10);
}
setSize(0);
setOpacity(1);
}, [turboColor]);
@ -39,7 +36,6 @@ export const PointParticle = ({ position, png, turboColor }) => {
return (
<points ref={pointsRef} geometry={points}>
<pointsMaterial
ref={materialRef}
size={size}
alphaMap={texture}
transparent={true}

View File

@ -1,56 +0,0 @@
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>
);
};

View File

@ -1,15 +0,0 @@
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}/>
</>
)
}

View File

@ -1,68 +0,0 @@
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>
);
};

View File

@ -1,33 +0,0 @@
import { Particles2 } from "./Particles2";
import { Particles4 } from "./Particles4";
export const DriftParticlesRight = ({turboColor,scale, ...props}) => {
// if(scale < 0.8) {
// return null;
// }
return (
<group {...props}>
<Particles2 turboColor={turboColor} scale={scale} />
<Particles2 turboColor={turboColor} scale={scale} />
<Particles2 turboColor={turboColor} scale={scale} />
<Particles2 turboColor={turboColor} scale={scale} />
<Particles2 turboColor={turboColor} scale={scale} />
<Particles2 turboColor={turboColor} scale={scale} />
<Particles2 turboColor={turboColor} scale={scale} />
<Particles2 turboColor={turboColor} scale={scale} />
<Particles2 turboColor={turboColor} scale={scale} />
<Particles2 turboColor={turboColor} scale={scale} />
<Particles2 turboColor={turboColor} scale={scale} />
<Particles2 turboColor={turboColor} scale={scale} />
<Particles2 turboColor={turboColor} scale={scale} />
<Particles2 turboColor={turboColor} scale={scale} />
<Particles2 turboColor={turboColor} scale={scale} />
<Particles2 turboColor={turboColor} scale={scale} />
<Particles2 turboColor={turboColor} scale={scale} />
<Particles2 turboColor={turboColor} scale={scale} />
</group>
)
}

View File

@ -1,55 +0,0 @@
import { useRef } from "react";
import { useFrame } from "@react-three/fiber";
import * as THREE from 'three';
export const Particles1 = ({ turboColor, scale, ...props }) => {
const ref = useRef();
const velocity = useRef({
x: -Math.random() * 0.05,
y: Math.random() * 0.05,
z: Math.random() * 0.02,
});
const gravity = -0.003;
useFrame((state, delta) => {
let position = ref.current.position;
let velocityVector = new THREE.Vector3(velocity.current.x, velocity.current.y, velocity.current.z);
// Adjust gravity and velocity based on delta
velocity.current.y += gravity * delta * 144; // Multiply by 144 to scale for 144 FPS
// Scale velocity changes by delta
position.x += velocity.current.x * delta * 144;
position.y += velocity.current.y * delta * 144;
position.z += velocity.current.z * delta * 144;
if (!velocityVector.equals(new THREE.Vector3(0, 0, 0))) {
const alignmentQuaternion = new THREE.Quaternion();
alignmentQuaternion.setFromUnitVectors(new THREE.Vector3(0, 1, 0), velocityVector.normalize());
ref.current.quaternion.slerp(alignmentQuaternion, 0.1);
}
if (position.y < 0.05) {
position.set(-0.6, 0.05, 0.5);
velocity.current = {
x: -Math.random() * 0.05,
y: Math.random() * 0.05,
z: Math.random() * 0.02,
};
}
ref.current.position.set(position.x, position.y, position.z);
});
return (
<mesh ref={ref} position={[-0.6, 0.05, 0.5]} scale={[scale, scale * 5, scale]}>
<sphereGeometry args={[0.01, 16, 16]} />
<meshStandardMaterial
emissive={turboColor}
toneMapped={false}
emissiveIntensity={5}
/>
</mesh>
);
};

View File

@ -1,54 +0,0 @@
import { useRef } from "react";
import { useFrame } from "@react-three/fiber";
import * as THREE from 'three';
export const Particles2 = ({ turboColor, scale, ...props }) => {
const ref = useRef();
const velocity = useRef({
x: Math.random() * 0.05,
y: Math.random() * 0.05,
z: Math.random() * 0.02,
});
const gravity = -0.003;
useFrame((state, delta) => {
let position = ref.current.position;
let velocityVector = new THREE.Vector3(velocity.current.x, velocity.current.y, velocity.current.z);
velocity.current.y += gravity * delta * 144;
position.x += velocity.current.x * delta * 144;
position.y += velocity.current.y * delta * 144;
position.z += velocity.current.z * delta * 144;
if (!velocityVector.equals(new THREE.Vector3(0, 0, 0))) {
const alignmentQuaternion = new THREE.Quaternion();
alignmentQuaternion.setFromUnitVectors(new THREE.Vector3(0, 1, 0), velocityVector.normalize());
ref.current.quaternion.slerp(alignmentQuaternion, 0.1);
}
if (position.y < 0.05) {
position.set(0.6, 0.05, 0.5);
velocity.current = {
x: Math.random() * 0.05,
y: Math.random() * 0.05,
z: Math.random() * 0.02,
};
}
ref.current.position.set(position.x, position.y, position.z);
});
return (
<mesh ref={ref} position={[0.6, 0.05, 0.5]} scale={[scale, scale * 5, scale]}>
<sphereGeometry args={[0.01, 16, 16]} />
<meshStandardMaterial
emissive={turboColor}
toneMapped={false}
emissiveIntensity={5}
/>
</mesh>
);
};

View File

@ -1,139 +0,0 @@
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 });

View File

@ -1,72 +0,0 @@
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>
);
};

View File

@ -1,19 +0,0 @@
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}/>
</>
)
}

View File

@ -1,61 +0,0 @@
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>
);
};

View File

@ -1,20 +0,0 @@
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}/>
</>
)
}

View File

@ -1,70 +0,0 @@
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>
);
};

View File

@ -1,70 +0,0 @@
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>
);
};

View File

@ -1,82 +0,0 @@
import React, { useRef, useMemo } from "react";
import { useLoader, useFrame } from "@react-three/fiber";
import * as THREE from "three";
export const SmokeParticle = ({ position, png, leftDrift, rightDrift, delay = 0 }) => {
const texture = useLoader(THREE.TextureLoader, png);
const pointsRef = useRef();
const initialized = useRef(false);
// Initialize after delay
useMemo(() => {
const timer = setTimeout(() => {
initialized.current = true;
}, delay);
return () => clearTimeout(timer);
}, [delay]);
const points = useMemo(() => {
const geom = new THREE.BufferGeometry();
geom.setAttribute(
"position",
new THREE.Float32BufferAttribute(position, 3)
);
return geom;
}, [position]);
useFrame(({clock}, delta) => {
if (!initialized.current) return;
const pointsCurrent = pointsRef.current;
if(leftDrift || rightDrift){
pointsCurrent.position.z += 0.1 * delta * 144;
//Set inclination
if(leftDrift){
pointsCurrent.position.x -= 0.09 * delta * 144;
}
if(rightDrift){
pointsCurrent.position.x += 0.09 * delta * 144;
}
if(pointsCurrent.position.x < -1.8 || pointsCurrent.position.x > 1.8) {
pointsCurrent.position.z = 0;
pointsCurrent.position.x = 0;
pointsCurrent.material.opacity = 1.5;
pointsCurrent.material.size = 4;
}
if(pointsCurrent.material.opacity > 0) {
pointsCurrent.material.opacity -= 0.01 * delta * 144;
}
if(pointsCurrent.material.size > 0) {
//Shrinking effect
pointsCurrent.material.size -= 0.1* delta * 144;
}
} else {
pointsCurrent.position.z = 0;
pointsCurrent.position.x = 0;
pointsCurrent.material.opacity = 0;
pointsCurrent.material.size = 0;
}
});
return (
<points ref={pointsRef} geometry={points}>
<pointsMaterial
size={1}
alphaMap={texture}
transparent={true}
depthWrite={false}
color={0xBFBFBF}
opacity={1}
toneMapped={false}
/>
</points>
);
};

View File

@ -1,24 +0,0 @@
import { SmokeParticle } from "./SmokeParticle";
export const SmokeParticles = ({ driftRight, driftLeft }) => {
return (
<group>
<SmokeParticle
position={[-0.6, 0.05, 0.5]}
png="./particles/fire_02.png"
leftDrift={driftLeft}
rightDrift={driftRight}
delay={200}
/>
<SmokeParticle
position={[0.6, 0.05, 0.5]}
png="./particles/fire_01.png"
leftDrift={driftLeft}
rightDrift={driftRight}
delay={200}
/>
</group>
);
};

View File

@ -3,45 +3,33 @@ import { BallCollider, RigidBody, useRapier, vec3 } from "@react-three/rapier";
import {
useKeyboardControls,
PerspectiveCamera,
ContactShadows,
Sphere,
OrbitControls,
Trail,
PositionalAudio,
} from "@react-three/drei";
import { useFrame, useThree, extend } from "@react-three/fiber";
import { useFrame, useThree } from "@react-three/fiber";
import { useRef, useState, useEffect, useCallback } from "react";
import * as THREE from "three";
import { Mario } from "./models/characters/Mario_kart";
import { DriftParticlesLeft } from "./Particles/drifts/DriftParticlesLeft";
import { DriftParticlesRight } from "./Particles/drifts/DriftParticlesRight";
import { DriftParticlesLeft } from "./Particles/DriftParticlesLeft";
import { DriftParticlesRight } from "./Particles/DriftParticlesRight";
import { PointParticle } from "./Particles/drifts/PointParticle";
import { PointParticle } from "./Particles/PointParticle";
import { SmokeParticles } from "./Particles/smoke/SmokeParticles";
import { FlameParticles } from "./Particles/FlameParticles";
import { useStore } from "./store";
import { Cylinder } from "@react-three/drei";
import FakeGlowMaterial from "./ShaderMaterials/FakeGlow/FakeGlowMaterial";
import { HitParticles } from "./Particles/hits/HitParticles";
import { CoinParticles } from "./Particles/coins/CoinParticles";
import { ItemParticles } from "./Particles/items/ItemParticles";
import { geometry } from "maath";
extend(geometry);
import { useGamepad } from "./useGamepad";
export const PlayerController = ({
player,
userPlayer,
setNetworkBananas,
setNetworkShells,
networkBananas,
networkShells,
}) => {
export const PlayerController = () => {
const upPressed = useKeyboardControls((state) => state[Controls.up]);
const downPressed = useKeyboardControls((state) => state[Controls.down]);
const leftPressed = useKeyboardControls((state) => state[Controls.left]);
const rightPressed = useKeyboardControls((state) => state[Controls.right]);
const jumpPressed = useKeyboardControls((state) => state[Controls.jump]);
const shootPressed = useKeyboardControls((state) => state[Controls.shoot]);
const resetPressed = useKeyboardControls((state) => state[Controls.reset]);
const escPressed = useKeyboardControls((state) => state[Controls.escape]);
const [isOnGround, setIsOnGround] = useState(false);
const body = useRef();
const kart = useRef();
@ -76,46 +64,16 @@ export const PlayerController = ({
let targetZPosition = 8;
const [steeringAngleWheels, setSteeringAngleWheels] = useState(0);
const engineSound = useRef();
const driftSound = useRef();
const driftTwoSound = useRef();
const driftOrangeSound = useRef();
const driftPurpleSound = useRef();
const driftBlueSound = useRef();
const jumpSound = useRef();
const landingSound = useRef();
const turboSound = useRef();
const { buttonA, joystick, RB } = useGamepad();
const [scale, setScale] = useState(0);
const raycaster = new THREE.Raycaster();
const downDirection = new THREE.Vector3(0, -1, 0);
const [shouldLaunch, setShouldLaunch] = useState(false);
const effectiveBoost = useRef(0);
const text = useRef();
const { actions, shouldSlowDown, item, bananas, coins, id, controls } =
useStore();
const slowDownDuration = useRef(1500);
const rightWheel = useRef();
const leftWheel = useRef();
useEffect(() => {
if (leftWheel.current && rightWheel.current && body.current) {
actions.setLeftWheel(leftWheel.current);
actions.setRightWheel(rightWheel.current);
}
}, [body.current]);
useFrame(({ pointer, clock }, delta) => {
if (player.id !== id) return;
const time = clock.getElapsedTime();
if (!body.current && !mario.current) return;
engineSound.current.setVolume(currentSpeed / 300 + 0.2);
engineSound.current.setPlaybackRate(currentSpeed / 10 + 0.1);
jumpSound.current.setPlaybackRate(1.5);
jumpSound.current.setVolume(0.5);
driftSound.current.setVolume(0.2);
driftBlueSound.current.setVolume(0.5);
driftOrangeSound.current.setVolume(0.6);
driftPurpleSound.current.setVolume(0.7);
// console.log(buttonA, joystick);
// HANDLING AND STEERING
const kartRotation =
kart.current.rotation.y - driftDirection.current * driftForce.current;
@ -125,24 +83,12 @@ export const PlayerController = ({
-Math.cos(kartRotation)
);
if (escPressed) {
actions.setGameStarted(false);
}
if(kartRotation){
leftWheel.current.kartRotation = kartRotation;
}
if (leftPressed && currentSpeed > 0) {
steeringAngle = currentSteeringSpeed;
targetXPosition = -camMaxOffset;
} else if (rightPressed && currentSpeed > 0) {
steeringAngle = -currentSteeringSpeed;
targetXPosition = camMaxOffset;
} else if (rightPressed && currentSpeed < 0) {
steeringAngle = currentSteeringSpeed;
targetXPosition = -camMaxOffset;
} else if (leftPressed && currentSpeed < 0) {
steeringAngle = -currentSteeringSpeed;
targetXPosition = camMaxOffset;
} else {
steeringAngle = 0;
targetXPosition = 0;
@ -150,19 +96,32 @@ export const PlayerController = ({
}
// mouse steering
const steer = joystick[0] * 0.8;
if (!driftLeft.current && !driftRight.current) {
steeringAngle = currentSteeringSpeed * -pointer.x;
targetXPosition = -camMaxOffset * -pointer.x;
} else if (driftLeft.current && !driftRight.current) {
steeringAngle = currentSteeringSpeed * -(pointer.x - 1);
steeringAngle = currentSteeringSpeed * -(pointer.x - 0.5);
targetXPosition = -camMaxOffset * -pointer.x;
} else if (driftRight.current && !driftLeft.current) {
steeringAngle = currentSteeringSpeed * -(pointer.x + 1);
steeringAngle = currentSteeringSpeed * -(pointer.x + 0.5);
targetXPosition = -camMaxOffset * -pointer.x;
}
if (steer) {
if (!driftLeft.current && !driftRight.current) {
steeringAngle = currentSteeringSpeed * -joystick[0];
targetXPosition = -camMaxOffset * -joystick[0];
} else if (driftLeft.current && !driftRight.current) {
steeringAngle = currentSteeringSpeed * -(joystick[0] - 1);
targetXPosition = -camMaxOffset * -joystick[0];
} else if (driftRight.current && !driftLeft.current) {
steeringAngle = currentSteeringSpeed * -(joystick[0] + 1);
targetXPosition = -camMaxOffset * -joystick[0];
}
}
// ACCELERATING
const shouldSlow = actions.getShouldSlowDown();
if (upPressed && currentSpeed < maxSpeed) {
// Accelerate the kart within the maximum speed limit
@ -172,7 +131,7 @@ export const PlayerController = ({
} else if (
upPressed &&
currentSpeed > maxSpeed &&
effectiveBoost.current > 0
boostDuration.current > 0
) {
setCurrentSpeed(
Math.max(currentSpeed - decceleration * delta * 144, maxSpeed)
@ -189,25 +148,23 @@ export const PlayerController = ({
);
}
}
if (shouldSlow) {
rightWheel.current.isSpinning = true;
if (buttonA && currentSpeed < maxSpeed) {
// Accelerate the kart within the maximum speed limit
setCurrentSpeed(
Math.max(currentSpeed - decceleration * 2 * delta * 144, 0)
Math.min(currentSpeed + acceleration * delta * 144, maxSpeed)
);
} else if (
buttonA &&
currentSpeed > maxSpeed &&
boostDuration.current > 0
) {
setCurrentSpeed(
Math.max(currentSpeed - decceleration * delta * 144, maxSpeed)
);
setCurrentSteeringSpeed(0);
slowDownDuration.current -= 1500 * delta;
setShouldLaunch(true);
if (slowDownDuration.current <= 1) {
rightWheel.current.isSpinning = false;
actions.setShouldSlowDown(false);
slowDownDuration.current = 1500;
setShouldLaunch(false);
}
}
// REVERSING
if (downPressed) {
if (buttonA) {
if (currentSteeringSpeed < MaxSteeringSpeed) {
setCurrentSteeringSpeed(
Math.min(
@ -218,13 +175,14 @@ export const PlayerController = ({
}
}
if (downPressed && currentSpeed <= 0) {
// REVERSING
if (downPressed && currentSpeed < -maxSpeed) {
setCurrentSpeed(
Math.max(currentSpeed - acceleration * delta * 144, -maxSpeed)
);
}
// DECELERATING
else if (!upPressed) {
else if (!buttonA && !downPressed) {
if (currentSteeringSpeed > 0) {
setCurrentSteeringSpeed(
Math.max(currentSteeringSpeed - 0.00005 * delta * 144, 0)
@ -257,50 +215,62 @@ export const PlayerController = ({
);
// JUMPING
if (jumpPressed && isOnGround && !jumpIsHeld.current) {
if (jumpPressed && isOnFloor.current && !jumpIsHeld.current) {
jumpForce.current += 10;
isOnFloor.current = false;
jumpIsHeld.current = true;
} else if (RB && isOnFloor.current && !jumpIsHeld.current) {
jumpForce.current += 10;
isOnFloor.current = false;
jumpIsHeld.current = true;
jumpSound.current.play();
setIsOnGround(false);
if (jumpSound.current.isPlaying) {
jumpSound.current.stop();
jumpSound.current.play();
}
}
if (isOnFloor.current && jumpForce.current > 0) {
landingSound.current.play();
}
if (!isOnGround && jumpForce.current > 0) {
if (!isOnFloor.current && jumpForce.current > 0) {
jumpForce.current -= 1 * delta * 144;
}
if (!jumpPressed) {
if (!jumpPressed && !RB) {
jumpIsHeld.current = false;
driftDirection.current = 0;
driftForce.current = 0;
driftLeft.current = false;
driftRight.current = false;
}
console.log(jumpIsHeld.current);
// DRIFTING
if (
jumpIsHeld.current &&
currentSteeringSpeed > 0 &&
upPressed &&
pointer.x < -0.1 &&
!driftRight.current
) {
driftLeft.current = true;
}
if (
jumpIsHeld.current &&
currentSteeringSpeed > 0 &&
upPressed &&
pointer.x > 0.1 &&
!driftLeft.current
) {
driftRight.current = true;
// if (
// jumpIsHeld.current &&
// currentSteeringSpeed > 0 &&
// pointer.x < -0.1 &&
// !driftRight.current
// ) {
// driftLeft.current = true;
// }
// if (
// jumpIsHeld.current &&
// currentSteeringSpeed > 0 &&
// pointer.x > 0.1 &&
// !driftLeft.current
// ) {
// driftRight.current = true;
// }
if (steer) {
if (
jumpIsHeld.current &&
currentSteeringSpeed > 0 &&
steer < -0.1 &&
!driftRight.current
) {
driftLeft.current = true;
}
if (
jumpIsHeld.current &&
currentSteeringSpeed > 0 &&
steer > 0.1 &&
!driftLeft.current
) {
driftRight.current = true;
}
}
if (!jumpIsHeld.current && !driftLeft.current && !driftRight.current) {
@ -311,10 +281,6 @@ export const PlayerController = ({
);
setTurboColor(0xffffff);
accumulatedDriftPower.current = 0;
driftSound.current.stop();
driftTwoSound.current.stop();
driftOrangeSound.current.stop();
driftPurpleSound.current.stop();
}
if (driftLeft.current) {
@ -322,28 +288,20 @@ export const PlayerController = ({
driftForce.current = 0.4;
mario.current.rotation.y = THREE.MathUtils.lerp(
mario.current.rotation.y,
steeringAngle * 25 + 0.4,
steeringAngle * 50 + 0.5,
0.05 * delta * 144
);
if (isOnFloor.current) {
leftWheel.current.isSpinning = true;
accumulatedDriftPower.current +=
0.1 * (steeringAngle + 1) * delta * 144;
}
accumulatedDriftPower.current += 0.1 * (steeringAngle + 1) * delta * 144;
}
if (driftRight.current) {
driftDirection.current = -1;
driftForce.current = 0.4;
mario.current.rotation.y = THREE.MathUtils.lerp(
mario.current.rotation.y,
-(-steeringAngle * 25 + 0.4),
-(-steeringAngle * 50 + 0.5),
0.05 * delta * 144
);
if(isOnFloor.current){
leftWheel.current.isSpinning = true;
accumulatedDriftPower.current += 0.1 * (-steeringAngle + 1) * delta * 144;
}
accumulatedDriftPower.current += 0.1 * (-steeringAngle + 1) * delta * 144;
}
if (!driftLeft.current && !driftRight.current) {
mario.current.rotation.y = THREE.MathUtils.lerp(
@ -352,68 +310,46 @@ export const PlayerController = ({
0.05 * delta * 144
);
setScale(0);
if((pointer.x > 0.8 || pointer.x < -0.8) && currentSpeed > 20 && isOnFloor.current){
leftWheel.current.isSpinning = true;
} else {
leftWheel.current.isSpinning = false;
}
}
if (accumulatedDriftPower.current > blueTurboThreshold) {
setTurboColor(0x00ffff);
boostDuration.current = 50;
driftBlueSound.current.play();
}
if (accumulatedDriftPower.current > orangeTurboThreshold) {
setTurboColor(0xffcf00);
boostDuration.current = 100;
driftBlueSound.current.stop();
driftOrangeSound.current.play();
}
if (accumulatedDriftPower.current > purpleTurboThreshold) {
setTurboColor(0xff00ff);
boostDuration.current = 250;
driftOrangeSound.current.stop();
driftPurpleSound.current.play();
}
if (driftLeft.current || driftRight.current) {
const oscillation = Math.sin(time * 1000) * 0.1;
const vibration = oscillation + 0.9;
if (turboColor === 0xffffff) {
setScale(vibration * 0.8);
} else {
setScale(vibration);
}
if (isOnFloor.current && !driftSound.current.isPlaying) {
driftSound.current.play();
driftTwoSound.current.play();
landingSound.current.play();
}
}
// RELEASING DRIFT
if (boostDuration.current > 1 && !jumpIsHeld.current) {
setIsBoosting(true);
effectiveBoost.current = boostDuration.current;
boostDuration.current = 0;
} else if (effectiveBoost.current <= 1) {
} else if (boostDuration.current <= 1) {
targetZPosition = 8;
setIsBoosting(false);
}
if (isBoosting && effectiveBoost.current > 1) {
if (isBoosting && boostDuration.current > 1) {
setCurrentSpeed(boostSpeed);
effectiveBoost.current -= 1 * delta * 144;
boostDuration.current -= 1 * delta * 144;
targetZPosition = 10;
if (!turboSound.current.isPlaying) turboSound.current.play();
driftTwoSound.current.play();
driftBlueSound.current.stop();
driftOrangeSound.current.stop();
driftPurpleSound.current.stop();
} else if (effectiveBoost.current <= 1) {
} else if (boostDuration.current <= 1) {
setIsBoosting(false);
targetZPosition = 8;
turboSound.current.stop();
}
// CAMERA WORK
@ -446,117 +382,34 @@ export const PlayerController = ({
// SOUND WORK
// MISC
if (resetPressed) {
body.current.setTranslation({ x: 8, y: 2, z: -119 });
body.current.setLinvel({ x: 0, y: 0, z: 0 });
body.current.setAngvel({ x: 0, y: 0, z: 0 });
setCurrentSpeed(0);
setCurrentSteeringSpeed(0);
setIsBoosting(false);
effectiveBoost.current = 0;
setIsOnGround(false);
jumpForce.current = 0;
driftDirection.current = 0;
kart.current.rotation.y = Math.PI / 2;
}
// ITEMS
if (shootPressed && item === "banana") {
const distanceBehind = 2;
const scaledBackwardDirection =
forwardDirection.multiplyScalar(distanceBehind);
const kartPosition = new THREE.Vector3(
...vec3(body.current.translation())
);
const bananaPosition = kartPosition.sub(scaledBackwardDirection);
const newBanana = {
id: Math.random() + "-" + +new Date(),
position: bananaPosition,
player: true,
};
setNetworkBananas([...networkBananas, newBanana]);
actions.useItem();
}
if (shootPressed && item === "shell") {
const distanceBehind = -2;
const scaledBackwardDirection =
forwardDirection.multiplyScalar(distanceBehind);
const kartPosition = new THREE.Vector3(
body.current.translation().x,
body.current.translation().y,
body.current.translation().z
);
const shellPosition = kartPosition.sub(scaledBackwardDirection);
const newShell = {
id: Math.random() + "-" + +new Date(),
position: shellPosition,
player: true,
rotation: kartRotation,
};
setNetworkShells([...networkShells, newShell]);
actions.useItem();
}
if (shootPressed && item === "mushroom") {
setIsBoosting(true);
effectiveBoost.current = 300;
actions.useItem();
}
player.setState("position", body.current.translation());
player.setState("rotation", kartRotation + mario.current.rotation.y);
player.setState("isBoosting", isBoosting);
player.setState("shouldLaunch", shouldLaunch);
player.setState("turboColor", turboColor);
player.setState("scale", scale);
player.setState("bananas", bananas);
// console.lowg(body.current.translation())
});
return player.id === id ? (
return (
<group>
<RigidBody
ref={body}
colliders={false}
position={[8, 60, -119]}
position={[8, 100, -96]}
centerOfMass={[0, -1, 0]}
mass={3}
ccd
name="player"
type={player.id === id ? "dynamic" : "kinematic"}
>
<BallCollider
args={[0.5]}
mass={3}
onCollisionEnter={({ other }) => {
onCollisionEnter={(event) => {
isOnFloor.current = true;
setIsOnGround(true);
}}
onCollisionExit={({ other }) => {
isOnFloor.current = false;
setIsOnGround(false);
}}
/>
</RigidBody>
<group ref={kart} rotation={[0, Math.PI / 2, 0]}>
<group ref={mario}>
<Mario
currentSpeed={currentSpeed}
steeringAngleWheels={steeringAngleWheels}
isBoosting={isBoosting}
shouldLaunch={shouldLaunch}
/>
<CoinParticles coins={coins} />
<ItemParticles item={item} />
<mesh position={[0.6, 0.05, 0.5]} scale={scale}>
<sphereGeometry args={[0.05, 16, 16]} />
<meshStandardMaterial
@ -567,15 +420,6 @@ export const PlayerController = ({
opacity={0.4}
/>
</mesh>
<mesh position={[0.6, 0.05, 0.5]} scale={scale * 10}>
<sphereGeometry args={[0.05, 16, 16]} />
<FakeGlowMaterial
falloff={3}
glowInternalRadius={1}
glowColor={turboColor}
glowSharpness={1}
/>
</mesh>
<mesh position={[-0.6, 0.05, 0.5]} scale={scale}>
<sphereGeometry args={[0.05, 16, 16]} />
<meshStandardMaterial
@ -586,112 +430,37 @@ export const PlayerController = ({
opacity={0.4}
/>
</mesh>
<mesh position={[-0.46, 0.05, 0.3]} ref={leftWheel}></mesh>
<mesh position={[0.46, 0.05, 0.3]} ref={rightWheel}></mesh>
<mesh position={[-0.6, 0.05, 0.5]} scale={scale * 10}>
<sphereGeometry args={[0.05, 16, 16]} />
<FakeGlowMaterial
falloff={3}
glowInternalRadius={1}
glowColor={turboColor}
glowSharpness={1}
/>
</mesh>
{/* <FlameParticles isBoosting={isBoosting} /> */}
<FlameParticles isBoosting={isBoosting} />
<DriftParticlesLeft turboColor={turboColor} scale={scale} />
<DriftParticlesRight turboColor={turboColor} scale={scale} />
<SmokeParticles
driftRight={driftRight.current}
driftLeft={driftLeft.current}
/>
<PointParticle
position={[-0.6, 0.05, 0.5]}
png="./particles/circle.png"
png="./circle.png"
turboColor={turboColor}
/>
<PointParticle
position={[0.6, 0.05, 0.5]}
png="./particles/circle.png"
png="./circle.png"
turboColor={turboColor}
/>
<PointParticle
position={[-0.6, 0.05, 0.5]}
png="./particles/star.png"
png="./star.png"
turboColor={turboColor}
/>
<PointParticle
position={[0.6, 0.05, 0.5]}
png="./particles/star.png"
png="./star.png"
turboColor={turboColor}
/>
<HitParticles shouldLaunch={shouldLaunch} />
</group>
{/* <ContactShadows frames={1} /> */}
<PerspectiveCamera
makeDefault
position={[0, 2, 8]}
fov={50}
ref={cam}
far={5000}
/>
<PositionalAudio
ref={engineSound}
url="./sounds/engine.wav"
autoplay
loop
distance={1000}
/>
<PositionalAudio
ref={driftSound}
url="./sounds/drifting.mp3"
loop
distance={1000}
/>
<PositionalAudio
ref={driftTwoSound}
url="./sounds/driftingTwo.mp3"
loop
distance={1000}
/>
<PositionalAudio
ref={driftOrangeSound}
url="./sounds/driftOrange.wav"
loop={false}
distance={1000}
/>
<PositionalAudio
ref={driftBlueSound}
url="./sounds/driftBlue.wav"
loop={false}
distance={1000}
/>
<PositionalAudio
ref={driftPurpleSound}
url="./sounds/driftPurple.wav"
loop={false}
distance={1000}
/>
<PositionalAudio
ref={jumpSound}
url="./sounds/jump.mp3"
loop={false}
distance={1000}
/>
<PositionalAudio
ref={landingSound}
url="./sounds/landing.wav"
loop={false}
distance={1000}
/>
<PositionalAudio
ref={turboSound}
url="./sounds/turbo.wav"
loop={false}
distance={1000}
/>
</group>
</group>
) : null;
);
};

View File

@ -1,670 +0,0 @@
import { Controls } from "../App";
import { BallCollider, RigidBody, useRapier, vec3 } from "@react-three/rapier";
import {
useKeyboardControls,
PerspectiveCamera,
PositionalAudio,
} from "@react-three/drei";
import { useFrame, useThree, extend } from "@react-three/fiber";
import { useRef, useState, useEffect, useCallback } from "react";
import * as THREE from "three";
import { Mario } from "./models/characters/Mario_kart";
import { DriftParticlesLeft } from "./Particles/drifts/DriftParticlesLeft";
import { DriftParticlesRight } from "./Particles/drifts/DriftParticlesRight";
import { PointParticle } from "./Particles/drifts/PointParticle";
import { useStore } from "./store";
import { Cylinder } from "@react-three/drei";
import FakeGlowMaterial from "./ShaderMaterials/FakeGlow/FakeGlowMaterial";
import { HitParticles } from "./Particles/hits/HitParticles";
import { CoinParticles } from "./Particles/coins/CoinParticles";
import { ItemParticles } from "./Particles/items/ItemParticles";
import { geometry } from "maath";
import { useGamepad } from "./useGamepad";
extend(geometry);
export const PlayerControllerGamepad = ({
player,
userPlayer,
setNetworkBananas,
setNetworkShells,
networkBananas,
networkShells,
}) => {
const [isOnGround, setIsOnGround] = useState(false);
const body = useRef();
const kart = useRef();
const cam = useRef();
const initialSpeed = 0;
const maxSpeed = 30;
const boostSpeed = 50;
const acceleration = 0.1;
const decceleration = 0.2;
const damping = -0.1;
const MaxSteeringSpeed = 0.01;
const [currentSteeringSpeed, setCurrentSteeringSpeed] = useState(0);
const [currentSpeed, setCurrentSpeed] = useState(initialSpeed);
const camMaxOffset = 1;
let steeringAngle = 0;
const isOnFloor = useRef(false);
const jumpForce = useRef(0);
const jumpIsHeld = useRef(false);
const driftDirection = useRef(0);
const driftLeft = useRef(false);
const driftRight = useRef(false);
const driftForce = useRef(0);
const mario = useRef();
const accumulatedDriftPower = useRef(0);
const blueTurboThreshold = 10;
const orangeTurboThreshold = 30;
const purpleTurboThreshold = 60;
const [turboColor, setTurboColor] = useState(0xffffff);
const boostDuration = useRef(0);
const [isBoosting, setIsBoosting] = useState(false);
let targetXPosition = 0;
let targetZPosition = 8;
const [steeringAngleWheels, setSteeringAngleWheels] = useState(0);
const engineSound = useRef();
const driftSound = useRef();
const driftTwoSound = useRef();
const driftOrangeSound = useRef();
const driftPurpleSound = useRef();
const driftBlueSound = useRef();
const jumpSound = useRef();
const landingSound = useRef();
const turboSound = useRef();
const [scale, setScale] = useState(0);
const raycaster = new THREE.Raycaster();
const downDirection = new THREE.Vector3(0, -1, 0);
const [shouldLaunch, setShouldLaunch] = useState(false);
const effectiveBoost = useRef(0);
const text = useRef();
const { actions, shouldSlowDown, item, bananas, coins, id, controls } =
useStore();
const slowDownDuration = useRef(1500);
const { buttonA, buttonB, RB, LB, joystick, select, start } = useGamepad();
const skidRotation = useRef(0);
const rightWheel = useRef();
const leftWheel = useRef();
const isDrifting = useRef(false);
useEffect(() => {
if (leftWheel.current && rightWheel.current && body.current) {
actions.setLeftWheel(leftWheel.current);
actions.setRightWheel(rightWheel.current);
}
}, [body.current]);
useFrame(({ pointer, clock }, delta) => {
if (player.id !== id) return;
const time = clock.getElapsedTime();
if (!body.current && !mario.current) return;
isDrifting.current = driftLeft.current || driftRight.current;
engineSound.current.setVolume(currentSpeed / 300 + 0.2);
engineSound.current.setPlaybackRate(currentSpeed / 10 + 0.1);
jumpSound.current.setPlaybackRate(1.5);
jumpSound.current.setVolume(0.5);
driftSound.current.setVolume(0.2);
driftBlueSound.current.setVolume(0.5);
driftOrangeSound.current.setVolume(0.6);
driftPurpleSound.current.setVolume(0.7);
// HANDLING AND STEERING
const kartRotation =
kart.current.rotation.y - driftDirection.current * driftForce.current;
const forwardDirection = new THREE.Vector3(
-Math.sin(kartRotation),
0,
-Math.cos(kartRotation)
);
if (start) {
actions.setGameStarted(false);
}
leftWheel.current.kartRotation = kartRotation ;
if (!driftLeft.current && !driftRight.current) {
steeringAngle = currentSteeringSpeed * -joystick[0];
targetXPosition = -camMaxOffset * -joystick[0];
} else if (driftLeft.current && !driftRight.current) {
steeringAngle = currentSteeringSpeed * -(joystick[0] - 1);
targetXPosition = -camMaxOffset * -joystick[0];
} else if (driftRight.current && !driftLeft.current) {
steeringAngle = currentSteeringSpeed * -(joystick[0] + 1);
targetXPosition = -camMaxOffset * -joystick[0];
}
// ACCELERATING
const shouldSlow = actions.getShouldSlowDown();
if (buttonA && currentSpeed < maxSpeed) {
// Accelerate the kart within the maximum speed limit
setCurrentSpeed(
Math.min(currentSpeed + acceleration * delta * 144, maxSpeed)
);
} else if (
buttonA &&
currentSpeed > maxSpeed &&
effectiveBoost.current > 0
) {
setCurrentSpeed(
Math.max(currentSpeed - decceleration * delta * 144, maxSpeed)
);
}
if (buttonA) {
if (currentSteeringSpeed < MaxSteeringSpeed) {
setCurrentSteeringSpeed(
Math.min(
currentSteeringSpeed + 0.0001 * delta * 144,
MaxSteeringSpeed
)
);
}
}
if (shouldSlow) {
rightWheel.current.isSpinning = true;
setCurrentSpeed(
Math.max(currentSpeed - decceleration * 2 * delta * 144, 0)
);
setCurrentSteeringSpeed(0);
slowDownDuration.current -= 1500 * delta;
setShouldLaunch(true);
if (slowDownDuration.current <= 1) {
rightWheel.current.isSpinning = false;
actions.setShouldSlowDown(false);
slowDownDuration.current = 1500;
setShouldLaunch(false);
}
}
// REVERSING
if (buttonB) {
if (currentSteeringSpeed < MaxSteeringSpeed) {
setCurrentSteeringSpeed(
Math.min(
currentSteeringSpeed + 0.0001 * delta * 144,
MaxSteeringSpeed
)
);
}
}
if (buttonB && currentSpeed <= 0) {
setCurrentSpeed(
Math.max(currentSpeed - acceleration * delta * 144, -maxSpeed)
);
}
// DECELERATING
else if (!buttonA) {
if (currentSteeringSpeed > 0) {
setCurrentSteeringSpeed(
Math.max(currentSteeringSpeed - 0.00005 * delta * 144, 0)
);
} else if (currentSteeringSpeed < 0) {
setCurrentSteeringSpeed(
Math.min(currentSteeringSpeed + 0.00005 * delta * 144, 0)
);
}
setCurrentSpeed(Math.max(currentSpeed - decceleration * delta * 144, 0));
}
// Update the kart's rotation based on the steering angle
kart.current.rotation.y += steeringAngle * delta * 144;
// Apply damping to simulate slowdown when no keys are pressed
body.current.applyImpulse(
{
x: -body.current.linvel().x * (1 - damping) * delta * 144,
y: 0,
z: -body.current.linvel().z * (1 - damping) * delta * 144,
},
true
);
const bodyPosition = body.current.translation();
kart.current.position.set(
bodyPosition.x,
bodyPosition.y - 0.5,
bodyPosition.z
);
// JUMPING
if (RB && isOnGround && !jumpIsHeld.current) {
jumpForce.current += 10;
isOnFloor.current = false;
jumpIsHeld.current = true;
jumpSound.current.play();
setIsOnGround(false);
if (jumpSound.current.isPlaying) {
jumpSound.current.stop();
jumpSound.current.play();
}
}
if (isOnFloor.current && jumpForce.current > 0) {
landingSound.current.play();
}
if (!isOnGround && jumpForce.current > 0) {
jumpForce.current -= 1 * delta * 144;
}
if (!RB) {
jumpIsHeld.current = false;
driftDirection.current = 0;
driftForce.current = 0;
driftLeft.current = false;
driftRight.current = false;
}
// DRIFTING
if (
jumpIsHeld.current &&
currentSteeringSpeed > 0 &&
joystick[0] < -0.1 &&
!driftRight.current
) {
driftLeft.current = true;
}
if (
jumpIsHeld.current &&
currentSteeringSpeed > 0 &&
joystick[0] > 0.1 &&
!driftLeft.current
) {
driftRight.current = true;
}
if (!jumpIsHeld.current && !driftLeft.current && !driftRight.current) {
mario.current.rotation.y = THREE.MathUtils.lerp(
mario.current.rotation.y,
0,
0.0001 * delta * 144
);
setTurboColor(0xffffff);
accumulatedDriftPower.current = 0;
driftSound.current.stop();
driftTwoSound.current.stop();
driftOrangeSound.current.stop();
driftPurpleSound.current.stop();
}
if (driftLeft.current) {
driftDirection.current = 1;
driftForce.current = 0.4;
mario.current.rotation.y = THREE.MathUtils.lerp(
mario.current.rotation.y,
steeringAngle * 25 + 0.4,
0.05 * delta * 144
);
if(isOnFloor.current){
leftWheel.current.isSpinning = true;
accumulatedDriftPower.current += 0.1 * (steeringAngle + 1) * delta * 144;
}
}
if (driftRight.current ) {
driftDirection.current = -1;
driftForce.current = 0.4;
mario.current.rotation.y = THREE.MathUtils.lerp(
mario.current.rotation.y,
-(-steeringAngle * 25 + 0.4),
0.05 * delta * 144
);
if(isOnFloor.current){
leftWheel.current.isSpinning = true;
accumulatedDriftPower.current += 0.1 * (-steeringAngle + 1) * delta * 144;
}
}
if (!driftLeft.current && !driftRight.current) {
mario.current.rotation.y = THREE.MathUtils.lerp(
mario.current.rotation.y,
steeringAngle * 30,
0.05 * delta * 144
);
setScale(0);
if((joystick[0] > 0.8 || joystick[0] < -0.8) && currentSpeed > 20 && isOnFloor.current){
leftWheel.current.isSpinning = true;
} else {
leftWheel.current.isSpinning = false;
}
}
if (accumulatedDriftPower.current > blueTurboThreshold) {
setTurboColor(0x00ffff);
boostDuration.current = 50;
driftBlueSound.current.play();
}
if (accumulatedDriftPower.current > orangeTurboThreshold) {
setTurboColor(0xffcf00);
boostDuration.current = 100;
driftBlueSound.current.stop();
driftOrangeSound.current.play();
}
if (accumulatedDriftPower.current > purpleTurboThreshold) {
setTurboColor(0xff00ff);
boostDuration.current = 250;
driftOrangeSound.current.stop();
driftPurpleSound.current.play();
}
if (driftLeft.current || driftRight.current) {
const oscillation = Math.sin(time * 1000) * 0.1;
const vibration = oscillation + 0.9;
if (turboColor === 0xffffff) {
setScale(vibration * 0.8);
} else {
setScale(vibration);
}
if (isOnFloor.current && !driftSound.current.isPlaying) {
driftSound.current.play();
driftTwoSound.current.play();
landingSound.current.play();
}
}
// RELEASING DRIFT
if (boostDuration.current > 1 && !jumpIsHeld.current) {
setIsBoosting(true);
effectiveBoost.current = boostDuration.current;
boostDuration.current = 0;
} else if (effectiveBoost.current <= 1) {
targetZPosition = 8;
setIsBoosting(false);
}
if (isBoosting && effectiveBoost.current > 1) {
setCurrentSpeed(boostSpeed);
effectiveBoost.current -= 1 * delta * 144;
targetZPosition = 10;
if (!turboSound.current.isPlaying) turboSound.current.play();
driftTwoSound.current.play();
driftBlueSound.current.stop();
driftOrangeSound.current.stop();
driftPurpleSound.current.stop();
} else if (effectiveBoost.current <= 1) {
setIsBoosting(false);
targetZPosition = 8;
turboSound.current.stop();
}
// CAMERA WORK
cam.current.updateMatrixWorld();
cam.current.position.x = THREE.MathUtils.lerp(
cam.current.position.x,
targetXPosition,
0.01 * delta * 144
);
cam.current.position.z = THREE.MathUtils.lerp(
cam.current.position.z,
targetZPosition,
0.01 * delta * 144
);
body.current.applyImpulse(
{
x: forwardDirection.x * currentSpeed * delta * 144,
y: 0 + jumpForce.current * delta * 144,
z: forwardDirection.z * currentSpeed * delta * 144,
},
true
);
// Update the kart's rotation based on the steering angle
setSteeringAngleWheels(steeringAngle * 25);
// SOUND WORK
// MISC
if (select) {
body.current.setTranslation({ x: 8, y: 2, z: -119 });
body.current.setLinvel({ x: 0, y: 0, z: 0 });
body.current.setAngvel({ x: 0, y: 0, z: 0 });
setCurrentSpeed(0);
setCurrentSteeringSpeed(0);
setIsBoosting(false);
effectiveBoost.current = 0;
setIsOnGround(false);
jumpForce.current = 0;
driftDirection.current = 0;
kart.current.rotation.y = Math.PI / 2;
}
// ITEMS
if (LB && item === "banana") {
const distanceBehind = 2;
const scaledBackwardDirection =
forwardDirection.multiplyScalar(distanceBehind);
const kartPosition = new THREE.Vector3(
...vec3(body.current.translation())
);
const bananaPosition = kartPosition.sub(scaledBackwardDirection);
const newBanana = {
id: Math.random() + "-" + +new Date(),
position: bananaPosition,
player: true,
};
setNetworkBananas([...networkBananas, newBanana]);
actions.useItem();
}
if (LB && item === "shell") {
const distanceBehind = -2;
const scaledBackwardDirection =
forwardDirection.multiplyScalar(distanceBehind);
const kartPosition = new THREE.Vector3(
body.current.translation().x,
body.current.translation().y,
body.current.translation().z
);
const shellPosition = kartPosition.sub(scaledBackwardDirection);
const newShell = {
id: Math.random() + "-" + +new Date(),
position: shellPosition,
player: true,
rotation: kartRotation,
};
setNetworkShells([...networkShells, newShell]);
actions.useItem();
}
if (LB && item === "mushroom") {
setIsBoosting(true);
effectiveBoost.current = 300;
actions.useItem();
}
player.setState("position", body.current.translation());
player.setState("rotation", kartRotation + mario.current.rotation.y);
player.setState("isBoosting", isBoosting);
player.setState("shouldLaunch", shouldLaunch);
player.setState("turboColor", turboColor);
player.setState("scale", scale);
player.setState("bananas", bananas);
skidRotation.current = kartRotation + mario.current.rotation.y;
});
return player.id === id ? (
<group>
<RigidBody
ref={body}
colliders={false}
position={[8, 60, -119]}
centerOfMass={[0, -1, 0]}
mass={3}
ccd
name="player"
type={player.id === id ? "dynamic" : "kinematic"}
>
<BallCollider
args={[0.5]}
mass={3}
onCollisionEnter={({ other }) => {
isOnFloor.current = true;
setIsOnGround(true);
}}
onCollisionExit={({ other }) => {
isOnFloor.current = false;
setIsOnGround(false);
}}
/>
</RigidBody>
<group ref={kart} rotation={[0, Math.PI / 2, 0]}>
<group ref={mario}>
<Mario
currentSpeed={currentSpeed}
steeringAngleWheels={steeringAngleWheels}
isBoosting={isBoosting}
shouldLaunch={shouldLaunch}
/>
<CoinParticles coins={coins} />
<ItemParticles item={item} />
<mesh position={[0.6, 0.05, 0.5]} scale={scale} ref={rightWheel}>
<sphereGeometry args={[0.05, 16, 16]} />
<meshStandardMaterial
emissive={turboColor}
toneMapped={false}
emissiveIntensity={100}
transparent
opacity={0.4}
/>
</mesh>
<mesh position={[0.6, 0.05, 0.5]} scale={scale * 10}>
<sphereGeometry args={[0.05, 16, 16]} />
<FakeGlowMaterial
falloff={3}
glowInternalRadius={1}
glowColor={turboColor}
glowSharpness={1}
/>
</mesh>
<mesh position={[-0.6, 0.05, 0.5]} scale={scale}>
<sphereGeometry args={[0.05, 16, 16]} />
<meshStandardMaterial
emissive={turboColor}
toneMapped={false}
emissiveIntensity={100}
transparent
opacity={0.4}
/>
</mesh>
<mesh position={[-0.46, 0.05, 0.3]} ref={leftWheel}></mesh>
<mesh position={[-0.6, 0.05, 0.5]} scale={scale * 10}>
<sphereGeometry args={[0.05, 16, 16]} />
<FakeGlowMaterial
falloff={3}
glowInternalRadius={1}
glowColor={turboColor}
glowSharpness={1}
/>
</mesh>
<mesh position={[0.46, 0.05, 0.3]} ref={rightWheel}></mesh>
{/* <FlameParticles isBoosting={isBoosting} /> */}
<DriftParticlesLeft turboColor={turboColor} scale={scale} />
<DriftParticlesRight turboColor={turboColor} scale={scale} />
<PointParticle
position={[-0.6, 0.05, 0.5]}
png="./particles/circle.png"
turboColor={turboColor}
/>
<PointParticle
position={[0.6, 0.05, 0.5]}
png="./particles/circle.png"
turboColor={turboColor}
/>
<PointParticle
position={[-0.6, 0.05, 0.5]}
png="./particles/star.png"
turboColor={turboColor}
/>
<PointParticle
position={[0.6, 0.05, 0.5]}
png="./particles/star.png"
turboColor={turboColor}
/>
<HitParticles shouldLaunch={shouldLaunch} />
</group>
{/* <ContactShadows frames={1} /> */}
<PerspectiveCamera
makeDefault
position={[0, 2, 8]}
fov={50}
ref={cam}
far={5000}
/>
<PositionalAudio
ref={engineSound}
url="./sounds/engine.wav"
autoplay
loop
distance={1000}
/>
<PositionalAudio
ref={driftSound}
url="./sounds/drifting.mp3"
loop
distance={1000}
/>
<PositionalAudio
ref={driftTwoSound}
url="./sounds/driftingTwo.mp3"
loop
distance={1000}
/>
<PositionalAudio
ref={driftOrangeSound}
url="./sounds/driftOrange.wav"
loop={false}
distance={1000}
/>
<PositionalAudio
ref={driftBlueSound}
url="./sounds/driftBlue.wav"
loop={false}
distance={1000}
/>
<PositionalAudio
ref={driftPurpleSound}
url="./sounds/driftPurple.wav"
loop={false}
distance={1000}
/>
<PositionalAudio
ref={jumpSound}
url="./sounds/jump.mp3"
loop={false}
distance={1000}
/>
<PositionalAudio
ref={landingSound}
url="./sounds/landing.wav"
loop={false}
distance={1000}
/>
<PositionalAudio
ref={turboSound}
url="./sounds/turbo.wav"
loop={false}
distance={1000}
/>
</group>
</group>
) : null;
};

View File

@ -1,686 +0,0 @@
import { Controls } from "../App";
import { BallCollider, RigidBody, useRapier, vec3 } from "@react-three/rapier";
import {
useKeyboardControls,
PerspectiveCamera,
PositionalAudio,
} from "@react-three/drei";
import { useFrame, useThree, extend } from "@react-three/fiber";
import { useRef, useState, useEffect, useCallback } from "react";
import * as THREE from "three";
import { Mario } from "./models/characters/Mario_kart";
import { DriftParticlesLeft } from "./Particles/drifts/DriftParticlesLeft";
import { DriftParticlesRight } from "./Particles/drifts/DriftParticlesRight";
import { PointParticle } from "./Particles/drifts/PointParticle";
import { SmokeParticles } from "./Particles/smoke/SmokeParticles";
import { FlameParticle } from "./Particles/flames/FlameParticle";
import { useStore } from "./store";
import { Cylinder } from "@react-three/drei";
import FakeGlowMaterial from "./ShaderMaterials/FakeGlow/FakeGlowMaterial";
import { HitParticles } from "./Particles/hits/HitParticles";
import { CoinParticles } from "./Particles/coins/CoinParticles";
import { ItemParticles } from "./Particles/items/ItemParticles";
import { geometry } from "maath";
extend(geometry);
export const PlayerControllerKeyboard = ({
player,
userPlayer,
setNetworkBananas,
setNetworkShells,
networkBananas,
networkShells,
}) => {
const upPressed = useKeyboardControls((state) => state[Controls.up]);
const downPressed = useKeyboardControls((state) => state[Controls.down]);
const leftPressed = useKeyboardControls((state) => state[Controls.left]);
const rightPressed = useKeyboardControls((state) => state[Controls.right]);
const jumpPressed = useKeyboardControls((state) => state[Controls.jump]);
const shootPressed = useKeyboardControls((state) => state[Controls.shoot]);
const resetPressed = useKeyboardControls((state) => state[Controls.reset]);
const escPressed = useKeyboardControls((state) => state[Controls.escape]);
const [isOnGround, setIsOnGround] = useState(false);
const body = useRef();
const kart = useRef();
const cam = useRef();
const initialSpeed = 0;
const maxSpeed = 30;
const boostSpeed = 50;
const acceleration = 0.1;
const decceleration = 0.2;
const damping = -0.1;
const MaxSteeringSpeed = 0.01;
const [currentSteeringSpeed, setCurrentSteeringSpeed] = useState(0);
const [currentSpeed, setCurrentSpeed] = useState(initialSpeed);
const camMaxOffset = 1;
let steeringAngle = 0;
const isOnFloor = useRef(false);
const jumpForce = useRef(0);
const jumpIsHeld = useRef(false);
const driftDirection = useRef(0);
const driftLeft = useRef(false);
const driftRight = useRef(false);
const driftForce = useRef(0);
const mario = useRef();
const accumulatedDriftPower = useRef(0);
const blueTurboThreshold = 10;
const orangeTurboThreshold = 30;
const purpleTurboThreshold = 60;
const [turboColor, setTurboColor] = useState(0xffffff);
const boostDuration = useRef(0);
const [isBoosting, setIsBoosting] = useState(false);
let targetXPosition = 0;
let targetZPosition = 8;
const [steeringAngleWheels, setSteeringAngleWheels] = useState(0);
const engineSound = useRef();
const driftSound = useRef();
const driftTwoSound = useRef();
const driftOrangeSound = useRef();
const driftPurpleSound = useRef();
const driftBlueSound = useRef();
const jumpSound = useRef();
const landingSound = useRef();
const turboSound = useRef();
const [scale, setScale] = useState(0);
const raycaster = new THREE.Raycaster();
const downDirection = new THREE.Vector3(0, -1, 0);
const [shouldLaunch, setShouldLaunch] = useState(false);
const effectiveBoost = useRef(0);
const text = useRef();
const { actions, shouldSlowDown, item, bananas, coins, id, controls } =
useStore();
const slowDownDuration = useRef(1500);
const rightWheel = useRef();
const leftWheel = useRef();
const isDrifting = useRef(false);
useEffect(() => {
if (leftWheel.current && rightWheel.current && body.current) {
actions.setLeftWheel(leftWheel.current);
actions.setRightWheel(rightWheel.current);
}
}, [body.current]);
useFrame(({ pointer, clock }, delta) => {
if (player.id !== id) return;
const time = clock.getElapsedTime();
if (!body.current && !mario.current) return;
engineSound.current.setVolume(currentSpeed / 300 + 0.2);
engineSound.current.setPlaybackRate(currentSpeed / 10 + 0.1);
jumpSound.current.setPlaybackRate(1.5);
jumpSound.current.setVolume(0.5);
driftSound.current.setVolume(0.2);
driftBlueSound.current.setVolume(0.5);
driftOrangeSound.current.setVolume(0.6);
driftPurpleSound.current.setVolume(0.7);
// HANDLING AND STEERING
const kartRotation =
kart.current.rotation.y - driftDirection.current * driftForce.current;
const forwardDirection = new THREE.Vector3(
-Math.sin(kartRotation),
0,
-Math.cos(kartRotation)
);
leftWheel.current.kartRotation = kartRotation;
if (escPressed) {
actions.setGameStarted(false);
}
if (leftPressed && currentSpeed > 0) {
steeringAngle = currentSteeringSpeed;
targetXPosition = -camMaxOffset;
} else if (rightPressed && currentSpeed > 0) {
steeringAngle = -currentSteeringSpeed;
targetXPosition = camMaxOffset;
} else if (rightPressed && currentSpeed < 0) {
steeringAngle = currentSteeringSpeed;
targetXPosition = -camMaxOffset;
} else if (leftPressed && currentSpeed < 0) {
steeringAngle = -currentSteeringSpeed;
targetXPosition = camMaxOffset;
} else {
steeringAngle = 0;
targetXPosition = 0;
1;
}
// ACCELERATING
const shouldSlow = actions.getShouldSlowDown();
if (upPressed && currentSpeed < maxSpeed) {
// Accelerate the kart within the maximum speed limit
setCurrentSpeed(
Math.min(currentSpeed + acceleration * delta * 144, maxSpeed)
);
} else if (
upPressed &&
currentSpeed > maxSpeed &&
effectiveBoost.current > 0
) {
setCurrentSpeed(
Math.max(currentSpeed - decceleration * delta * 144, maxSpeed)
);
}
if (upPressed) {
if (currentSteeringSpeed < MaxSteeringSpeed) {
setCurrentSteeringSpeed(
Math.min(
currentSteeringSpeed + 0.0001 * delta * 144,
MaxSteeringSpeed
)
);
}
}
if (shouldSlow) {
rightWheel.current.isSpinning = true;
setCurrentSpeed(
Math.max(currentSpeed - decceleration * 2 * delta * 144, 0)
);
setCurrentSteeringSpeed(0);
slowDownDuration.current -= 1500 * delta;
setShouldLaunch(true);
if (slowDownDuration.current <= 1) {
rightWheel.current.isSpinning = false;
actions.setShouldSlowDown(false);
slowDownDuration.current = 1500;
setShouldLaunch(false);
}
}
// REVERSING
if (downPressed) {
if (currentSteeringSpeed < MaxSteeringSpeed) {
setCurrentSteeringSpeed(
Math.min(
currentSteeringSpeed + 0.0001 * delta * 144,
MaxSteeringSpeed
)
);
}
}
if (downPressed && currentSpeed <= 0) {
setCurrentSpeed(
Math.max(currentSpeed - acceleration * delta * 144, -maxSpeed)
);
}
// DECELERATING
else if (!upPressed) {
if (currentSteeringSpeed > 0) {
setCurrentSteeringSpeed(
Math.max(currentSteeringSpeed - 0.00005 * delta * 144, 0)
);
} else if (currentSteeringSpeed < 0) {
setCurrentSteeringSpeed(
Math.min(currentSteeringSpeed + 0.00005 * delta * 144, 0)
);
}
setCurrentSpeed(Math.max(currentSpeed - decceleration * delta * 144, 0));
}
// Update the kart's rotation based on the steering angle
kart.current.rotation.y += steeringAngle * delta * 144;
// Apply damping to simulate slowdown when no keys are pressed
body.current.applyImpulse(
{
x: -body.current.linvel().x * (1 - damping) * delta * 144,
y: 0,
z: -body.current.linvel().z * (1 - damping) * delta * 144,
},
true
);
const bodyPosition = body.current.translation();
kart.current.position.set(
bodyPosition.x,
bodyPosition.y - 0.5,
bodyPosition.z
);
// JUMPING
if (jumpPressed && isOnGround && !jumpIsHeld.current) {
jumpForce.current += 10;
isOnFloor.current = false;
jumpIsHeld.current = true;
jumpSound.current.play();
setIsOnGround(false);
if (jumpSound.current.isPlaying) {
jumpSound.current.stop();
jumpSound.current.play();
}
}
if (isOnFloor.current && jumpForce.current > 0) {
landingSound.current.play();
}
if (!isOnGround && jumpForce.current > 0) {
jumpForce.current -= 1 * delta * 144;
}
if (!jumpPressed) {
jumpIsHeld.current = false;
driftDirection.current = 0;
driftForce.current = 0;
driftLeft.current = false;
driftRight.current = false;
}
// DRIFTING
if (
jumpIsHeld.current &&
currentSteeringSpeed > 0 &&
upPressed &&
leftPressed &&
!driftRight.current
) {
driftLeft.current = true;
}
if (
jumpIsHeld.current &&
currentSteeringSpeed > 0 &&
upPressed &&
rightPressed > 0.1 &&
!driftLeft.current
) {
driftRight.current = true;
}
if (!jumpIsHeld.current && !driftLeft.current && !driftRight.current) {
mario.current.rotation.y = THREE.MathUtils.lerp(
mario.current.rotation.y,
0,
0.0001 * delta * 144
);
setTurboColor(0xffffff);
accumulatedDriftPower.current = 0;
driftSound.current.stop();
driftTwoSound.current.stop();
driftOrangeSound.current.stop();
driftPurpleSound.current.stop();
}
if (driftLeft.current) {
driftDirection.current = 1;
driftForce.current = 0.4;
mario.current.rotation.y = THREE.MathUtils.lerp(
mario.current.rotation.y,
steeringAngle * 25 + 0.4,
0.05 * delta * 144
);
if (isOnFloor.current) {
leftWheel.current.isSpinning = true;
accumulatedDriftPower.current +=
0.1 * (steeringAngle + 1) * delta * 144;
}
}
if (driftRight.current) {
driftDirection.current = -1;
driftForce.current = 0.4;
mario.current.rotation.y = THREE.MathUtils.lerp(
mario.current.rotation.y,
-(-steeringAngle * 25 + 0.4),
0.05 * delta * 144
);
if (isOnFloor.current) {
leftWheel.current.isSpinning = true;
accumulatedDriftPower.current +=
0.1 * (-steeringAngle + 1) * delta * 144;
}
}
if (!driftLeft.current && !driftRight.current) {
mario.current.rotation.y = THREE.MathUtils.lerp(
mario.current.rotation.y,
steeringAngle * 30,
0.05 * delta * 144
);
setScale(0);
if((leftPressed || rightPressed) && currentSpeed > 20 && isOnFloor.current){
leftWheel.current.isSpinning = true;
} else {
leftWheel.current.isSpinning = false;
}
}
if (accumulatedDriftPower.current > blueTurboThreshold) {
setTurboColor(0x00ffff);
boostDuration.current = 50;
driftBlueSound.current.play();
}
if (accumulatedDriftPower.current > orangeTurboThreshold) {
setTurboColor(0xffcf00);
boostDuration.current = 100;
driftBlueSound.current.stop();
driftOrangeSound.current.play();
}
if (accumulatedDriftPower.current > purpleTurboThreshold) {
setTurboColor(0xff00ff);
boostDuration.current = 250;
driftOrangeSound.current.stop();
driftPurpleSound.current.play();
}
if (driftLeft.current || driftRight.current) {
const oscillation = Math.sin(time * 1000) * 0.1;
const vibration = oscillation + 0.9;
if (turboColor === 0xffffff) {
setScale(vibration * 0.8);
} else {
setScale(vibration);
}
if (isOnFloor.current && !driftSound.current.isPlaying) {
driftSound.current.play();
driftTwoSound.current.play();
landingSound.current.play();
}
}
// RELEASING DRIFT
if (boostDuration.current > 1 && !jumpIsHeld.current) {
setIsBoosting(true);
effectiveBoost.current = boostDuration.current;
boostDuration.current = 0;
} else if (effectiveBoost.current <= 1) {
targetZPosition = 8;
setIsBoosting(false);
}
if (isBoosting && effectiveBoost.current > 1) {
setCurrentSpeed(boostSpeed);
effectiveBoost.current -= 1 * delta * 144;
targetZPosition = 10;
if (!turboSound.current.isPlaying) turboSound.current.play();
driftTwoSound.current.play();
driftBlueSound.current.stop();
driftOrangeSound.current.stop();
driftPurpleSound.current.stop();
} else if (effectiveBoost.current <= 1) {
setIsBoosting(false);
targetZPosition = 8;
turboSound.current.stop();
}
// CAMERA WORK
cam.current.updateMatrixWorld();
cam.current.position.x = THREE.MathUtils.lerp(
cam.current.position.x,
targetXPosition,
0.01 * delta * 144
);
cam.current.position.z = THREE.MathUtils.lerp(
cam.current.position.z,
targetZPosition,
0.01 * delta * 144
);
body.current.applyImpulse(
{
x: forwardDirection.x * currentSpeed * delta * 144,
y: 0 + jumpForce.current * delta * 144,
z: forwardDirection.z * currentSpeed * delta * 144,
},
true
);
// Update the kart's rotation based on the steering angle
setSteeringAngleWheels(steeringAngle * 25);
// SOUND WORK
// MISC
if (resetPressed) {
body.current.setTranslation({ x: 8, y: 2, z: -119 });
body.current.setLinvel({ x: 0, y: 0, z: 0 });
body.current.setAngvel({ x: 0, y: 0, z: 0 });
setCurrentSpeed(0);
setCurrentSteeringSpeed(0);
setIsBoosting(false);
effectiveBoost.current = 0;
setIsOnGround(false);
jumpForce.current = 0;
driftDirection.current = 0;
kart.current.rotation.y = Math.PI / 2;
}
// ITEMS
if (shootPressed && item === "banana") {
const distanceBehind = 2;
const scaledBackwardDirection =
forwardDirection.multiplyScalar(distanceBehind);
const kartPosition = new THREE.Vector3(
...vec3(body.current.translation())
);
const bananaPosition = kartPosition.sub(scaledBackwardDirection);
const newBanana = {
id: Math.random() + "-" + +new Date(),
position: bananaPosition,
player: true,
};
setNetworkBananas([...networkBananas, newBanana]);
actions.useItem();
}
if (shootPressed && item === "shell") {
const distanceBehind = -2;
const scaledBackwardDirection =
forwardDirection.multiplyScalar(distanceBehind);
const kartPosition = new THREE.Vector3(
body.current.translation().x,
body.current.translation().y,
body.current.translation().z
);
const shellPosition = kartPosition.sub(scaledBackwardDirection);
const newShell = {
id: Math.random() + "-" + +new Date(),
position: shellPosition,
player: true,
rotation: kartRotation,
};
setNetworkShells([...networkShells, newShell]);
actions.useItem();
}
if (shootPressed && item === "mushroom") {
setIsBoosting(true);
effectiveBoost.current = 300;
actions.useItem();
}
player.setState("position", body.current.translation());
player.setState("rotation", kartRotation + mario.current.rotation.y);
player.setState("isBoosting", isBoosting);
player.setState("shouldLaunch", shouldLaunch);
player.setState("turboColor", turboColor);
player.setState("scale", scale);
player.setState("bananas", bananas);
});
return player.id === id ? (
<group>
<RigidBody
ref={body}
colliders={false}
position={[8, 60, -119]}
centerOfMass={[0, -1, 0]}
mass={3}
ccd
name="player"
type={player.id === id ? "dynamic" : "kinematic"}
>
<BallCollider
args={[0.5]}
mass={3}
onCollisionEnter={({ other }) => {
isOnFloor.current = true;
setIsOnGround(true);
}}
onCollisionExit={({ other }) => {
isOnFloor.current = false;
setIsOnGround(false);
}}
/>
</RigidBody>
<group ref={kart} rotation={[0, Math.PI / 2, 0]}>
<group ref={mario}>
<Mario
currentSpeed={currentSpeed}
steeringAngleWheels={steeringAngleWheels}
isBoosting={isBoosting}
shouldLaunch={shouldLaunch}
/>
<CoinParticles coins={coins} />
<ItemParticles item={item} />
<mesh position={[0.6, 0.05, 0.5]} scale={scale}>
<sphereGeometry args={[0.05, 16, 16]} />
<meshStandardMaterial
emissive={turboColor}
toneMapped={false}
emissiveIntensity={100}
transparent
opacity={0.4}
/>
</mesh>
<mesh position={[-0.46, 0.05, 0.3]} ref={leftWheel}></mesh>
<mesh position={[0.46, 0.05, 0.3]} ref={rightWheel}></mesh>
<mesh position={[0.6, 0.05, 0.5]} scale={scale * 10}>
<sphereGeometry args={[0.05, 16, 16]} />
<FakeGlowMaterial
falloff={3}
glowInternalRadius={1}
glowColor={turboColor}
glowSharpness={1}
/>
</mesh>
<mesh position={[-0.6, 0.05, 0.5]} scale={scale}>
<sphereGeometry args={[0.05, 16, 16]} />
<meshStandardMaterial
emissive={turboColor}
toneMapped={false}
emissiveIntensity={100}
transparent
opacity={0.4}
/>
</mesh>
<mesh position={[-0.6, 0.05, 0.5]} scale={scale * 10}>
<sphereGeometry args={[0.05, 16, 16]} />
<FakeGlowMaterial
falloff={3}
glowInternalRadius={1}
glowColor={turboColor}
glowSharpness={1}
/>
</mesh>
{/* <FlameParticles isBoosting={isBoosting} /> */}
<DriftParticlesLeft turboColor={turboColor} scale={scale} />
<DriftParticlesRight turboColor={turboColor} scale={scale} />
<SmokeParticles
driftRight={driftRight.current}
driftLeft={driftLeft.current}
/>
<PointParticle
position={[-0.6, 0.05, 0.5]}
png="./particles/circle.png"
turboColor={turboColor}
/>
<PointParticle
position={[0.6, 0.05, 0.5]}
png="./particles/circle.png"
turboColor={turboColor}
/>
<PointParticle
position={[-0.6, 0.05, 0.5]}
png="./particles/star.png"
turboColor={turboColor}
/>
<PointParticle
position={[0.6, 0.05, 0.5]}
png="./particles/star.png"
turboColor={turboColor}
/>
<HitParticles shouldLaunch={shouldLaunch} />
</group>
{/* <ContactShadows frames={1} /> */}
<PerspectiveCamera
makeDefault
position={[0, 2, 8]}
fov={50}
ref={cam}
far={5000}
/>
<PositionalAudio
ref={engineSound}
url="./sounds/engine.wav"
autoplay
loop
distance={1000}
/>
<PositionalAudio
ref={driftSound}
url="./sounds/drifting.mp3"
loop
distance={1000}
/>
<PositionalAudio
ref={driftTwoSound}
url="./sounds/driftingTwo.mp3"
loop
distance={1000}
/>
<PositionalAudio
ref={driftOrangeSound}
url="./sounds/driftOrange.wav"
loop={false}
distance={1000}
/>
<PositionalAudio
ref={driftBlueSound}
url="./sounds/driftBlue.wav"
loop={false}
distance={1000}
/>
<PositionalAudio
ref={driftPurpleSound}
url="./sounds/driftPurple.wav"
loop={false}
distance={1000}
/>
<PositionalAudio
ref={jumpSound}
url="./sounds/jump.mp3"
loop={false}
distance={1000}
/>
<PositionalAudio
ref={landingSound}
url="./sounds/landing.wav"
loop={false}
distance={1000}
/>
<PositionalAudio
ref={turboSound}
url="./sounds/turbo.wav"
loop={false}
distance={1000}
/>
</group>
</group>
) : null;
};

View File

@ -1,619 +0,0 @@
import { Controls } from "../App";
import { BallCollider, RigidBody, useRapier, vec3 } from "@react-three/rapier";
import {
useKeyboardControls,
PerspectiveCamera,
PositionalAudio,
} from "@react-three/drei";
import { useFrame, useThree, extend } from "@react-three/fiber";
import { useRef, useState, useEffect, useCallback } from "react";
import * as THREE from "three";
import { Mario } from "./models/characters/Mario_kart";
import { DriftParticlesLeft } from "./Particles/drifts/DriftParticlesLeft";
import { DriftParticlesRight } from "./Particles/drifts/DriftParticlesRight";
import { PointParticle } from "./Particles/drifts/PointParticle";
import { SmokeParticles } from "./Particles/smoke/SmokeParticles";
import { useStore } from "./store";
import { Cylinder } from "@react-three/drei";
import FakeGlowMaterial from "./ShaderMaterials/FakeGlow/FakeGlowMaterial";
import { HitParticles } from "./Particles/hits/HitParticles";
import { CoinParticles } from "./Particles/coins/CoinParticles";
import { ItemParticles } from "./Particles/items/ItemParticles";
import { geometry } from "maath";
import { useGamepad } from "./useGamepad";
extend(geometry);
export const PlayerControllerTouch = ({
player,
userPlayer,
setNetworkBananas,
setNetworkShells,
networkBananas,
networkShells,
}) => {
const [isOnGround, setIsOnGround] = useState(false);
const body = useRef();
const kart = useRef();
const cam = useRef();
const initialSpeed = 0;
const maxSpeed = 30;
const boostSpeed = 50;
const acceleration = 0.1;
const decceleration = 0.2;
const damping = -0.1;
const MaxSteeringSpeed = 0.01;
const [currentSteeringSpeed, setCurrentSteeringSpeed] = useState(0);
const [currentSpeed, setCurrentSpeed] = useState(initialSpeed);
const camMaxOffset = 1;
let steeringAngle = 0;
const isOnFloor = useRef(false);
const jumpForce = useRef(0);
const jumpIsHeld = useRef(false);
const driftDirection = useRef(0);
const driftLeft = useRef(false);
const driftRight = useRef(false);
const driftForce = useRef(0);
const mario = useRef();
const accumulatedDriftPower = useRef(0);
const blueTurboThreshold = 10;
const orangeTurboThreshold = 30;
const purpleTurboThreshold = 60;
const [turboColor, setTurboColor] = useState(0xffffff);
const boostDuration = useRef(0);
const [isBoosting, setIsBoosting] = useState(false);
let targetXPosition = 0;
let targetZPosition = 8;
const [steeringAngleWheels, setSteeringAngleWheels] = useState(0);
const engineSound = useRef();
const driftSound = useRef();
const driftTwoSound = useRef();
const driftOrangeSound = useRef();
const driftPurpleSound = useRef();
const driftBlueSound = useRef();
const jumpSound = useRef();
const landingSound = useRef();
const turboSound = useRef();
const [scale, setScale] = useState(0);
const raycaster = new THREE.Raycaster();
const downDirection = new THREE.Vector3(0, -1, 0);
const [shouldLaunch, setShouldLaunch] = useState(false);
const effectiveBoost = useRef(0);
const text = useRef();
const { actions, shouldSlowDown, item, bananas, coins, id, controls, joystickX, driftButton, itemButton, menuButton } = useStore();
const slowDownDuration = useRef(1500);
const rightWheel = useRef();
const leftWheel = useRef();
const isDrifting = useRef(false);
useEffect(() => {
if (leftWheel.current && rightWheel.current && body.current) {
actions.setLeftWheel(leftWheel.current);
actions.setRightWheel(rightWheel.current);
}
}, [body.current]);
useFrame(({ pointer, clock }, delta) => {
if (player.id !== id) return;
const time = clock.getElapsedTime();
if (!body.current && !mario.current) return;
engineSound.current.setVolume(currentSpeed / 300 + 0.2);
engineSound.current.setPlaybackRate(currentSpeed / 10 + 0.1);
jumpSound.current.setPlaybackRate(1.5);
jumpSound.current.setVolume(0.5);
driftSound.current.setVolume(0.2);
driftBlueSound.current.setVolume(0.5);
driftOrangeSound.current.setVolume(0.6);
driftPurpleSound.current.setVolume(0.7);
// HANDLING AND STEERING
const kartRotation =
kart.current.rotation.y - driftDirection.current * driftForce.current;
const forwardDirection = new THREE.Vector3(
-Math.sin(kartRotation),
0,
-Math.cos(kartRotation)
);
leftWheel.current.kartRotation = kartRotation;
if (menuButton) {
actions.setGameStarted(false);
}
// mouse steering
if (!driftLeft.current && !driftRight.current) {
steeringAngle = currentSteeringSpeed * -joystickX;
targetXPosition = -camMaxOffset * -joystickX;
} else if (driftLeft.current && !driftRight.current) {
steeringAngle = currentSteeringSpeed * -(joystickX - 1);
targetXPosition = -camMaxOffset * -joystickX;
} else if (driftRight.current && !driftLeft.current) {
steeringAngle = currentSteeringSpeed * -(joystickX + 1);
targetXPosition = -camMaxOffset * -joystickX;
}
// ACCELERATING
const shouldSlow = actions.getShouldSlowDown();
if ( currentSpeed < maxSpeed) {
// Accelerate the kart within the maximum speed limit
setCurrentSpeed(
Math.min(currentSpeed + acceleration * delta * 144, maxSpeed)
);
} else if (
currentSpeed > maxSpeed &&
effectiveBoost.current > 0
) {
setCurrentSpeed(
Math.max(currentSpeed - decceleration * delta * 144, maxSpeed)
);
}
if (currentSteeringSpeed < MaxSteeringSpeed) {
setCurrentSteeringSpeed(
Math.min(
currentSteeringSpeed + 0.0001 * delta * 144,
MaxSteeringSpeed
)
);
}
if (shouldSlow) {
rightWheel.current.isSpinning = true;
setCurrentSpeed(
Math.max(currentSpeed - decceleration * 2 * delta * 144, 0)
);
setCurrentSteeringSpeed(0);
slowDownDuration.current -= 1500 * delta;
setShouldLaunch(true);
if (slowDownDuration.current <= 1) {
rightWheel.current.isSpinning = false;
actions.setShouldSlowDown(false);
slowDownDuration.current = 1500;
setShouldLaunch(false);
}
}
// Update the kart's rotation based on the steering angle
kart.current.rotation.y += steeringAngle * delta * 144;
// Apply damping to simulate slowdown when no keys are pressed
body.current.applyImpulse(
{
x: -body.current.linvel().x * (1 - damping) * delta * 144,
y: 0,
z: -body.current.linvel().z * (1 - damping) * delta * 144,
},
true
);
const bodyPosition = body.current.translation();
kart.current.position.set(
bodyPosition.x,
bodyPosition.y - 0.5,
bodyPosition.z
);
// JUMPING
if (driftButton && isOnGround && !jumpIsHeld.current) {
jumpForce.current += 10;
isOnFloor.current = false;
jumpIsHeld.current = true;
jumpSound.current.play();
setIsOnGround(false);
if (jumpSound.current.isPlaying) {
jumpSound.current.stop();
jumpSound.current.play();
}
}
if (isOnFloor.current && jumpForce.current > 0) {
landingSound.current.play();
}
if (!isOnGround && jumpForce.current > 0) {
jumpForce.current -= 1 * delta * 144;
}
if (!driftButton) {
jumpIsHeld.current = false;
driftDirection.current = 0;
driftForce.current = 0;
driftLeft.current = false;
driftRight.current = false;
}
// DRIFTING
if (
jumpIsHeld.current &&
currentSteeringSpeed > 0 &&
joystickX < -0.1 &&
!driftRight.current
) {
driftLeft.current = true;
}
if (
jumpIsHeld.current &&
currentSteeringSpeed > 0 &&
joystickX > 0.1 &&
!driftLeft.current
) {
driftRight.current = true;
}
if (!jumpIsHeld.current && !driftLeft.current && !driftRight.current) {
mario.current.rotation.y = THREE.MathUtils.lerp(
mario.current.rotation.y,
0,
0.0001 * delta * 144
);
setTurboColor(0xffffff);
accumulatedDriftPower.current = 0;
driftSound.current.stop();
driftTwoSound.current.stop();
driftOrangeSound.current.stop();
driftPurpleSound.current.stop();
}
if (driftLeft.current) {
driftDirection.current = 1;
driftForce.current = 0.4;
mario.current.rotation.y = THREE.MathUtils.lerp(
mario.current.rotation.y,
steeringAngle * 25 + 0.4,
0.05 * delta * 144
);
if(isOnFloor.current){
leftWheel.current.isSpinning = true;
accumulatedDriftPower.current += 0.1 * (steeringAngle + 1) * delta * 144;
}
}
if (driftRight.current) {
driftDirection.current = -1;
driftForce.current = 0.4;
mario.current.rotation.y = THREE.MathUtils.lerp(
mario.current.rotation.y,
-(-steeringAngle * 25 + 0.4),
0.05 * delta * 144
);
if(isOnFloor.current){
leftWheel.current.isSpinning = true;
accumulatedDriftPower.current += 0.1 * (-steeringAngle + 1) * delta * 144;
}
}
if (!driftLeft.current && !driftRight.current) {
mario.current.rotation.y = THREE.MathUtils.lerp(
mario.current.rotation.y,
steeringAngle * 30,
0.05 * delta * 144
);
setScale(0);
if((joystickX > 0.8 || joystickX < -0.8) && currentSpeed > 20 && isOnFloor.current){
leftWheel.current.isSpinning = true;
} else {
leftWheel.current.isSpinning = false;
}
}
if (accumulatedDriftPower.current > blueTurboThreshold) {
setTurboColor(0x00ffff);
boostDuration.current = 50;
driftBlueSound.current.play();
}
if (accumulatedDriftPower.current > orangeTurboThreshold) {
setTurboColor(0xffcf00);
boostDuration.current = 100;
driftBlueSound.current.stop();
driftOrangeSound.current.play();
}
if (accumulatedDriftPower.current > purpleTurboThreshold) {
setTurboColor(0xff00ff);
boostDuration.current = 250;
driftOrangeSound.current.stop();
driftPurpleSound.current.play();
}
if (driftLeft.current || driftRight.current) {
const oscillation = Math.sin(time * 1000) * 0.1;
const vibration = oscillation + 0.9;
if (turboColor === 0xffffff) {
setScale(vibration * 0.8);
} else {
setScale(vibration);
}
if (isOnFloor.current && !driftSound.current.isPlaying) {
driftSound.current.play();
driftTwoSound.current.play();
landingSound.current.play();
}
}
// RELEASING DRIFT
if (boostDuration.current > 1 && !jumpIsHeld.current) {
setIsBoosting(true);
effectiveBoost.current = boostDuration.current;
boostDuration.current = 0;
} else if (effectiveBoost.current <= 1) {
targetZPosition = 8;
setIsBoosting(false);
}
if (isBoosting && effectiveBoost.current > 1) {
setCurrentSpeed(boostSpeed);
effectiveBoost.current -= 1 * delta * 144;
targetZPosition = 10;
if (!turboSound.current.isPlaying) turboSound.current.play();
driftTwoSound.current.play();
driftBlueSound.current.stop();
driftOrangeSound.current.stop();
driftPurpleSound.current.stop();
} else if (effectiveBoost.current <= 1) {
setIsBoosting(false);
targetZPosition = 8;
turboSound.current.stop();
}
// CAMERA WORK
cam.current.updateMatrixWorld();
cam.current.position.x = THREE.MathUtils.lerp(
cam.current.position.x,
targetXPosition,
0.01 * delta * 144
);
cam.current.position.z = THREE.MathUtils.lerp(
cam.current.position.z,
targetZPosition,
0.01 * delta * 144
);
body.current.applyImpulse(
{
x: forwardDirection.x * currentSpeed * delta * 144,
y: 0 + jumpForce.current * delta * 144,
z: forwardDirection.z * currentSpeed * delta * 144,
},
true
);
// Update the kart's rotation based on the steering angle
setSteeringAngleWheels(steeringAngle * 25);
// SOUND WORK
// ITEMS
if (itemButton && item === "banana") {
const distanceBehind = 2;
const scaledBackwardDirection =
forwardDirection.multiplyScalar(distanceBehind);
const kartPosition = new THREE.Vector3(
...vec3(body.current.translation())
);
const bananaPosition = kartPosition.sub(scaledBackwardDirection);
const newBanana = {
id: Math.random() + "-" + +new Date(),
position: bananaPosition,
player: true,
};
setNetworkBananas([...networkBananas, newBanana]);
actions.useItem();
}
if (itemButton && item === "shell") {
const distanceBehind = -2;
const scaledBackwardDirection =
forwardDirection.multiplyScalar(distanceBehind);
const kartPosition = new THREE.Vector3(
body.current.translation().x,
body.current.translation().y,
body.current.translation().z
);
const shellPosition = kartPosition.sub(scaledBackwardDirection);
const newShell = {
id: Math.random() + "-" + +new Date(),
position: shellPosition,
player: true,
rotation: kartRotation,
};
setNetworkShells([...networkShells, newShell]);
actions.useItem();
}
if (itemButton && item === "mushroom") {
setIsBoosting(true);
effectiveBoost.current = 300;
actions.useItem();
}
player.setState("position", body.current.translation());
player.setState("rotation", kartRotation + mario.current.rotation.y);
player.setState("isBoosting", isBoosting);
player.setState("shouldLaunch", shouldLaunch);
player.setState("turboColor", turboColor);
player.setState("scale", scale);
player.setState("bananas", bananas);
});
return player.id === id ? (
<group>
<RigidBody
ref={body}
colliders={false}
position={[8, 60, -119]}
centerOfMass={[0, -1, 0]}
mass={3}
ccd
name="player"
type={player.id === id ? "dynamic" : "kinematic"}
>
<BallCollider
args={[0.5]}
mass={3}
onCollisionEnter={({ other }) => {
isOnFloor.current = true;
setIsOnGround(true);
}}
onCollisionExit={({ other }) => {
isOnFloor.current = false;
setIsOnGround(false);
}}
/>
</RigidBody>
<group ref={kart} rotation={[0, Math.PI / 2, 0]}>
<group ref={mario}>
<Mario
currentSpeed={currentSpeed}
steeringAngleWheels={steeringAngleWheels}
isBoosting={isBoosting}
shouldLaunch={shouldLaunch}
/>
<CoinParticles coins={coins} />
<ItemParticles item={item} />
<mesh position={[0.6, 0.05, 0.5]} scale={scale}>
<sphereGeometry args={[0.05, 16, 16]} />
<meshStandardMaterial
emissive={turboColor}
toneMapped={false}
emissiveIntensity={100}
transparent
opacity={0.4}
/>
</mesh>
<mesh position={[-0.46, 0.05, 0.3]} ref={leftWheel}></mesh>
<mesh position={[0.46, 0.05, 0.3]} ref={rightWheel}></mesh>
<mesh position={[0.6, 0.05, 0.5]} scale={scale * 10}>
<sphereGeometry args={[0.05, 16, 16]} />
<FakeGlowMaterial
falloff={3}
glowInternalRadius={1}
glowColor={turboColor}
glowSharpness={1}
/>
</mesh>
<mesh position={[-0.6, 0.05, 0.5]} scale={scale}>
<sphereGeometry args={[0.05, 16, 16]} />
<meshStandardMaterial
emissive={turboColor}
toneMapped={false}
emissiveIntensity={100}
transparent
opacity={0.4}
/>
</mesh>
<mesh position={[-0.6, 0.05, 0.5]} scale={scale * 10}>
<sphereGeometry args={[0.05, 16, 16]} />
<FakeGlowMaterial
falloff={3}
glowInternalRadius={1}
glowColor={turboColor}
glowSharpness={1}
/>
</mesh>
{/* <FlameParticles isBoosting={isBoosting} /> */}
<DriftParticlesLeft turboColor={turboColor} scale={scale} />
<DriftParticlesRight turboColor={turboColor} scale={scale} />
<SmokeParticles driftRight={driftRight.current} driftLeft={driftLeft.current} />
<PointParticle
position={[-0.6, 0.05, 0.5]}
png="./particles/circle.png"
turboColor={turboColor}
/>
<PointParticle
position={[0.6, 0.05, 0.5]}
png="./particles/circle.png"
turboColor={turboColor}
/>
<PointParticle
position={[-0.6, 0.05, 0.5]}
png="./particles/star.png"
turboColor={turboColor}
/>
<PointParticle
position={[0.6, 0.05, 0.5]}
png="./particles/star.png"
turboColor={turboColor}
/>
<HitParticles shouldLaunch={shouldLaunch} />
</group>
{/* <ContactShadows frames={1} /> */}
<PerspectiveCamera
makeDefault
position={[0, 2, 8]}
fov={50}
ref={cam}
far={5000}
/>
<PositionalAudio
ref={engineSound}
url="./sounds/engine.wav"
autoplay
loop
distance={1000}
/>
<PositionalAudio
ref={driftSound}
url="./sounds/drifting.mp3"
loop
distance={1000}
/>
<PositionalAudio
ref={driftTwoSound}
url="./sounds/driftingTwo.mp3"
loop
distance={1000}
/>
<PositionalAudio
ref={driftOrangeSound}
url="./sounds/driftOrange.wav"
loop={false}
distance={1000}
/>
<PositionalAudio
ref={driftBlueSound}
url="./sounds/driftBlue.wav"
loop={false}
distance={1000}
/>
<PositionalAudio
ref={driftPurpleSound}
url="./sounds/driftPurple.wav"
loop={false}
distance={1000}
/>
<PositionalAudio
ref={jumpSound}
url="./sounds/jump.mp3"
loop={false}
distance={1000}
/>
<PositionalAudio
ref={landingSound}
url="./sounds/landing.wav"
loop={false}
distance={1000}
/>
<PositionalAudio
ref={turboSound}
url="./sounds/turbo.wav"
loop={false}
distance={1000}
/>
</group>
</group>
) : null;
};

View File

@ -1,271 +0,0 @@
import { Controls } from "../App";
import { BallCollider, RigidBody, useRapier, vec3 } from "@react-three/rapier";
import {
useKeyboardControls,
PerspectiveCamera,
ContactShadows,
Sphere,
OrbitControls,
Trail,
PositionalAudio,
Text,
Billboard,
} from "@react-three/drei";
import { useFrame, useThree } from "@react-three/fiber";
import { useRef, useState, useEffect, useCallback } from "react";
import * as THREE from "three";
import { Mario } from "./models/characters/Mario_kart";
import { DriftParticlesLeft } from "./Particles/drifts/DriftParticlesLeft";
import { DriftParticlesRight } from "./Particles/drifts/DriftParticlesRight";
import { PointParticle } from "./Particles/drifts/PointParticle";
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/hits/HitParticles";
import { CoinParticles } from "./Particles/coins/CoinParticles";
import { ItemParticles } from "./Particles/items/ItemParticles";
import { isHost } from "playroomkit";
import { Banana } from "./models/items/Banana_peel_mario_kart";
export const PlayerDummies = ( { player, userPlayer }) => {
const upPressed = useKeyboardControls((state) => state[Controls.up]);
const downPressed = useKeyboardControls((state) => state[Controls.down]);
const leftPressed = useKeyboardControls((state) => state[Controls.left]);
const rightPressed = useKeyboardControls((state) => state[Controls.right]);
const jumpPressed = useKeyboardControls((state) => state[Controls.jump]);
const shootPressed = useKeyboardControls((state) => state[Controls.shoot]);
const resetPressed = useKeyboardControls((state) => state[Controls.reset]);
const [isOnGround, setIsOnGround] = useState(false);
const body = useRef();
const kart = useRef();
const cam = useRef();
const text = useRef();
const initialSpeed = 0;
const maxSpeed = 30;
const boostSpeed = 50;
const acceleration = 0.1;
const decceleration = 0.2;
const damping = -0.1;
const MaxSteeringSpeed = 0.01;
const [currentSteeringSpeed, setCurrentSteeringSpeed] = useState(0);
const [currentSpeed, setCurrentSpeed] = useState(initialSpeed);
const camMaxOffset = 1;
let steeringAngle = 0;
const isOnFloor = useRef(false);
const jumpForce = useRef(0);
const jumpIsHeld = useRef(false);
const driftDirection = useRef(0);
const driftLeft = useRef(false);
const driftRight = useRef(false);
const driftForce = useRef(0);
const mario = useRef();
const accumulatedDriftPower = useRef(0);
const blueTurboThreshold = 10;
const orangeTurboThreshold = 30;
const purpleTurboThreshold = 60;
const [turboColor, setTurboColor] = useState(0xffffff);
const boostDuration = useRef(0);
const [isBoosting, setIsBoosting] = useState(false);
let targetXPosition = 0;
let targetZPosition = 8;
const [steeringAngleWheels, setSteeringAngleWheels] = useState(0);
const engineSound = useRef();
const driftSound = useRef();
const driftTwoSound = useRef();
const driftOrangeSound = useRef();
const driftPurpleSound = useRef();
const driftBlueSound = useRef();
const jumpSound = useRef();
const landingSound = useRef();
const turboSound = useRef();
const [scale, setScale] = useState(0);
const raycaster = new THREE.Raycaster();
const downDirection = new THREE.Vector3(0, -1, 0);
const [shouldLaunch, setShouldLaunch] = useState(false);
const effectiveBoost = useRef(0);
const [networkBananas, setNetworkBananas] = useState([]);
const [networkShells, setNetworkShells] = useState([]);
const { actions, shouldSlowDown, item, coins, id} = useStore();
const slowDownDuration = useRef(1500);
useFrame((state, delta) => {
const bodyPosition = player.getState("position");
const bodyRotation = player.getState("rotation");
setIsBoosting(player.getState("isBoosting"));
setShouldLaunch(player.getState("shouldLaunch"));
setTurboColor(player.getState("turboColor"));
setScale(player.getState("scale"));
if(bodyPosition && bodyRotation && kart.current && mario.current){
kart.current.position.set(bodyPosition.x, bodyPosition.y -.5, bodyPosition.z);
kart.current.rotation.set(0, bodyRotation, 0);
body.current.setTranslation([bodyPosition.x, bodyPosition.y, bodyPosition.z]);
}
});
return player.id != id? (
<>
<group>
<RigidBody
type="kinematic"
ref={body}
position={[0, 0, 0]}
rotation={[0, 0, 0]}
colliders={false}
name="player"
>
<BallCollider args={[0.5]} />
</RigidBody>
<group ref={kart} rotation={[0, Math.PI / 2, 0]}>
<group ref={mario}>
<Billboard>
<Text font={"./fonts/HK.ttf"} ref={text} fontSize={0.4} outlineWidth={0.03} position={[0, 2, 0]}>{player.state.profile.name}</Text>
</Billboard>
<Mario
currentSpeed={currentSpeed}
steeringAngleWheels={steeringAngleWheels}
isBoosting={isBoosting}
shouldLaunch={shouldLaunch}
/>
<CoinParticles coins={coins}/>
<ItemParticles item={item}/>
<mesh position={[0.6, 0.05, 0.5]} scale={scale}>
<sphereGeometry args={[0.05, 16, 16]} />
<meshStandardMaterial
emissive={turboColor}
toneMapped={false}
emissiveIntensity={100}
transparent
opacity={0.4}
/>
</mesh>
<mesh position={[0.6, 0.05, 0.5]} scale={scale * 10}>
<sphereGeometry args={[0.05, 16, 16]} />
<FakeGlowMaterial
falloff={3}
glowInternalRadius={1}
glowColor={turboColor}
glowSharpness={1}
/>
</mesh>
<mesh position={[-0.6, 0.05, 0.5]} scale={scale}>
<sphereGeometry args={[0.05, 16, 16]} />
<meshStandardMaterial
emissive={turboColor}
toneMapped={false}
emissiveIntensity={100}
transparent
opacity={0.4}
/>
</mesh>
<mesh position={[-0.6, 0.05, 0.5]} scale={scale * 10}>
<sphereGeometry args={[0.05, 16, 16]} />
<FakeGlowMaterial
falloff={3}
glowInternalRadius={1}
glowColor={turboColor}
glowSharpness={1}
/>
</mesh>
{/* <FlameParticles isBoosting={isBoosting} /> */}
<DriftParticlesLeft turboColor={turboColor} scale={scale} />
<DriftParticlesRight turboColor={turboColor} scale={scale} />
<PointParticle
position={[-0.6, 0.05, 0.5]}
png="./particles/circle.png"
turboColor={turboColor}
/>
<PointParticle
position={[0.6, 0.05, 0.5]}
png="./particles/circle.png"
turboColor={turboColor}
/>
<PointParticle
position={[-0.6, 0.05, 0.5]}
png="./particles/star.png"
turboColor={turboColor}
/>
<PointParticle
position={[0.6, 0.05, 0.5]}
png="./particles/star.png"
turboColor={turboColor}
/>
<HitParticles shouldLaunch={shouldLaunch}/>
</group>
{/* <ContactShadows frames={1} /> */}
<PositionalAudio
ref={engineSound}
url="./sounds/engine.wav"
autoplay
loop
distance={1000}
/>
<PositionalAudio
ref={driftSound}
url="./sounds/drifting.mp3"
loop
distance={1000}
/>
<PositionalAudio
ref={driftTwoSound}
url="./sounds/driftingTwo.mp3"
loop
distance={1000}
/>
<PositionalAudio
ref={driftOrangeSound}
url="./sounds/driftOrange.wav"
loop={false}
distance={1000}
/>
<PositionalAudio
ref={driftBlueSound}
url="./sounds/driftBlue.wav"
loop={false}
distance={1000}
/>
<PositionalAudio
ref={driftPurpleSound}
url="./sounds/driftPurple.wav"
loop={false}
distance={1000}
/>
<PositionalAudio
ref={jumpSound}
url="./sounds/jump.mp3"
loop={false}
distance={1000}
/>
<PositionalAudio
ref={landingSound}
url="./sounds/landing.wav"
loop={false}
distance={1000}
/>
<PositionalAudio
ref={turboSound}
url="./sounds/turbo.wav"
loop={false}
distance={1000}
/>
</group>
</group>
</>
) : null;
};

View File

@ -39,11 +39,11 @@ export default function FakeFlame({ falloff = 3, glowInternalRadius = 1.0, glowC
float glitchStrength = sin(glitchTime) + sin(glitchTime * .05) + sin(glitchTime * .36);
glitchStrength /= 2.0;
glitchStrength = smoothstep(0.2, 0.8, glitchStrength);
glitchStrength *= 0.;
glitchStrength *= 0.05;
modelPosition.x += (random2D(modelNormal.xx + time) - 0.5) * glitchStrength;
modelPosition.x += (random2D(modelNormal.xx - time) - 0.2) * glitchStrength;
modelPosition.y += sin(smoothstep(0.4, vUv.y - 2.5, position.y) * 2.) * sin(time * 48.);
modelPosition.z += sin(smoothstep(0., vUv.x - 1.8, position.z) * 2.) * sin(time * 24.);
modelPosition.y += sin(smoothstep(0.3, vUv.y - 2.2, position.y) * 2.) * sin(time * 48.);
modelPosition.z += sin(smoothstep(0., vUv.x - 0.8, position.z) * 2.) * sin(time * 24.) * .6;
gl_Position = projectionMatrix * viewMatrix * modelPosition;
@ -107,7 +107,7 @@ export default function FakeFlame({ falloff = 3, glowInternalRadius = 1.0, glowC
q.x *= 2.;
q.y *= 2.;
float strength = floor(q.x+1.5);
float T3 = max(2.,2.25*strength)*time * 4.;
float T3 = max(2.,2.25*strength)*time * 3.;
q.x = mod(q.x,1.)-0.5;
q.y -= 0.05;
float n = fbm(strength*q + vec2(0,T3));

View File

@ -1,56 +1,68 @@
import { Euler, Object3D, Vector3, Matrix4, DoubleSide } from 'three'
import { useRef, useLayoutEffect } from 'react'
import { useFrame } from '@react-three/fiber'
import { vec3 } from '@react-three/rapier'
import { Euler, Object3D, BackSide, Vector3 } from "three";
import { useRef, useLayoutEffect } from "react";
import { useFrame } from "@react-three/fiber";
import { useStore } from "./store";
const o = new Object3D();
import { useStore } from './store'
const e = new Euler()
const m = new Matrix4()
const o = new Object3D()
const v = new Vector3()
export function Skid({ count = 50000, opacity = 0.5, size = 0.3 }) {
export function Skid({ count = 500, opacity = 1, size = 0.4 }) {
const ref = useRef(null);
const { leftWheel, rightWheel } = useStore();
let index = 0
const [bodyPosition, bodyRotation] = useStore((state) => [
state.bodyPosition,
state.bodyRotation,
]);
let index = 0;
useFrame(() => {
if(!leftWheel && !rightWheel) return;
const rotation = leftWheel.kartRotation;
if (leftWheel && rightWheel && ref.current && (leftWheel.isSpinning || rightWheel.isSpinning)) {
setItemAt(ref.current, rotation, leftWheel, index++);
setItemAt(ref.current, rotation, rightWheel, index++);
if (index === count) index = 0
// console.log(bodyPosition, bodyRotation);
if (ref.current && bodyPosition && bodyRotation !== undefined) {
setItemAt(ref.current, bodyPosition, bodyRotation, index++);
if (index === count) index = 0;
}
})
});
useLayoutEffect(() => {
if(ref.current){
ref.current.geometry.rotateX(-Math.PI / 2)
if (ref.current) {
ref.current.geometry.rotateX(-Math.PI / 2);
return () => {
ref.current.geometry.rotateX(Math.PI / 2)
}
ref.current.geometry.rotateX(Math.PI / 2);
};
}
})
});
return (
<instancedMesh frustumCulled={false} ref={ref} args={[undefined, undefined, count]}>
<planeGeometry args={[size, size]} />
<meshBasicMaterial color="black" side={DoubleSide} transparent opacity={opacity} />
<instancedMesh ref={ref} args={[undefined, undefined, count]}>
<planeGeometry args={[size, size * 2]} />
<meshBasicMaterial
color={0x000000}
transparent
opacity={opacity}
depthWrite={false}
side={BackSide}
/>
</instancedMesh>
)
);
}
function setItemAt(instances, rotation, body, index) {
o.position.copy(body.getWorldPosition(v));
o.rotation.set(0, rotation, 0);
o.scale.setScalar(1)
o.updateMatrix()
instances.setMatrixAt(index, o.matrix)
instances.instanceMatrix.needsUpdate = true
function setItemAt(instances, bodyPosition, bodyRotation, index) {
// Calculate the backward offset
const backwardOffset = 0.5; // Adjust this value as needed
const forwardDirection = new Vector3(
-Math.sin(bodyRotation),
0,
-Math.cos(bodyRotation)
);
const backwardPosition = forwardDirection
.multiplyScalar(-backwardOffset)
.add(bodyPosition);
// 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.rotation.set(0, bodyRotation, 0);
o.scale.setScalar(1);
o.updateMatrix();
instances.setMatrixAt(index, o.matrix);
instances.instanceMatrix.needsUpdate = true;
}

View File

@ -3,15 +3,13 @@ Auto-generated by: https://github.com/pmndrs/gltfjsx
Command: npx gltfjsx@6.2.16 .\mariokarttest.glb --shadows
*/
import React, { useEffect, useRef } from 'react'
import React, { useRef } from 'react'
import { Cylinder, OrbitControls, Sphere, useGLTF } from '@react-three/drei'
import { useFrame } from '@react-three/fiber'
import FakeGlowMaterial from '../../ShaderMaterials/FakeGlow/FakeGlowMaterial'
import FakeFlame from '../../ShaderMaterials/FakeFlame/FakeFlame'
import { useStore } from '../../store'
import gsap from 'gsap'
export function Mario({ currentSpeed, steeringAngleWheels, isBoosting, shouldLaunch, ...props }) {
export function Mario({ currentSpeed, steeringAngleWheels, isBoosting, ...props }) {
const { nodes, materials } = useGLTF('./models/characters/mariokarttest.glb')
const frontLeftWheel = useRef()
@ -19,9 +17,6 @@ export function Mario({ currentSpeed, steeringAngleWheels, isBoosting, shouldLau
const rearWheels = useRef()
const frontWheels = useRef()
const [scale, setScale] = React.useState(1)
const { actions } = useStore()
const [shouldSlow, setShouldSlow] = React.useState(false)
const mario = useRef();
// isBoosting = true;
useFrame((_,delta) => {
@ -35,21 +30,12 @@ export function Mario({ currentSpeed, steeringAngleWheels, isBoosting, shouldLau
} else {
setScale(Math.max(scale - 0.03 * 144 * delta, 0))
}
setShouldSlow(actions.getShouldSlowDown());
})
useEffect(() => {
if (shouldLaunch) {
gsap.to(mario.current.rotation, {duration: 1.5, y: Math.PI * 3})
mario.current.rotation.set(0, 0, 0);
}
}, [shouldLaunch])
return (
<group
{...props}
rotation={[0, Math.PI, 0]}
dispose={null}
ref={mario}
>
<mesh
castShadow
@ -100,7 +86,7 @@ export function Mario({ currentSpeed, steeringAngleWheels, isBoosting, shouldLau
<Cylinder
args={[0.1, 0, 1, 128, 64, true]}
position={[0.3, 0.65, -1.35]}
position={[0.3, 0.6, -1.2]}
rotation={[Math.PI / 1.5, 0, 0]}
scale={scale}
@ -110,7 +96,7 @@ export function Mario({ currentSpeed, steeringAngleWheels, isBoosting, shouldLau
<Cylinder
args={[0.1, 0, 1, 128, 64, true]}
position={[-0.3, 0.65, -1.35]}
position={[-0.3, 0.6, -1.2]}
rotation={[Math.PI / 1.5, 0, 0]}
scale={scale}
>
@ -118,17 +104,17 @@ export function Mario({ currentSpeed, steeringAngleWheels, isBoosting, shouldLau
</Cylinder>
<Cylinder
args={[0.09, 0, 1, 128, 64, true]}
position={[0.18, 0.75, -1.1]}
position={[0.18, 0.7, -0.8]}
rotation={[Math.PI / 1.5, 0, 0]}
scale={scale * 0.8}
scale={scale}
>
<FakeFlame isBoosting={isBoosting} />
</Cylinder>
<Cylinder
args={[0.09, 0, 1, 128, 64, true]}
position={[-0.18, 0.75, -1.1]}
position={[-0.18, 0.7, -0.8]}
rotation={[Math.PI / 1.5, 0, 0]}
scale={scale * 0.8}
scale={scale}
>
<FakeFlame isBoosting={isBoosting}/>
</Cylinder>

View File

@ -1,55 +0,0 @@
/*
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/Yanez-Designs)
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, { useEffect, 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, id, position, setNetworkBananas, networkBananas}) {
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={[position.x, position.y, position.z]}
sensor
onIntersectionEnter={({other}) => {
if(other.rigidBodyObject.name === "player"){
actions.setShouldSlowDown(true);
setNetworkBananas(networkBananas.filter((banana) => banana.id !== id));
}
}}
colliders={false}
name='banana'
>
<BallCollider args={[0.5]} />
</RigidBody>
<group position={[position.x, position.y, position.z]} 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')

View File

@ -1,76 +0,0 @@
/*
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";
import { useStore } from "../../store";
export function Shell({ id, position, rotation, setNetworkShells, networkShells, ...props}) {
const { nodes, materials } = useGLTF("./models/items/mario_shell_red.glb");
const rigidBody = useRef();
const ref = useRef();
const shell_speed = 100;
const {actions} = useStore();
useEffect(() => {
const velocity = {
x: -Math.sin(rotation) * shell_speed,
y: 0,
z: -Math.cos(rotation) * shell_speed,
};
rigidBody.current.setLinvel(velocity, true);
}, []);
useFrame((state, delta) => {
if(rigidBody.current && ref.current){
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={[position.x, position.y, position.z]}
name="shell"
colliders={false}
onCollisionEnter={(other) => {
if (other.rigidBodyObject.name === "player") {
actions.setShouldSlowDown(true);
setNetworkShells(
networkShells.filter((shell) => shell.id !== id)
);
}
}}
>
<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");

View File

@ -1,70 +0,0 @@
/*
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"){
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')

View File

@ -1,50 +0,0 @@
/*
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={() => {
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>
</>
);
}

View File

@ -1,71 +0,0 @@
/*
Auto-generated by: https://github.com/pmndrs/gltfjsx
Command: npx gltfjsx@6.2.16 .\super_mario_bros_coin.glb --shadows --transform
Files: .\super_mario_bros_coin.glb [48.84KB] > C:\Users\mouli\dev\r3f-vite-starter\public\models\misc\super_mario_bros_coin-transformed.glb [6.12KB] (87%)
Author: BranHelsing (https://sketchfab.com/BranHelsing)
License: CC-BY-4.0 (http://creativecommons.org/licenses/by/4.0/)
Source: https://sketchfab.com/3d-models/super-mario-bros-coin-aa97e093847a439f9feb064134813806
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 { RigidBody } from "@react-three/rapier";
import { useStore } from "../../store";
export function Coin(props) {
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;
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 (
<>
<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");

View File

@ -1,109 +0,0 @@
/*
Auto-generated by: https://github.com/pmndrs/gltfjsx
Command: npx gltfjsx@6.2.16 .\paris-bis.glb --shadows
*/
import React, { useRef } from 'react'
import { useGLTF } from '@react-three/drei'
import { RigidBody } from '@react-three/rapier'
export function ParisBis(props) {
const { nodes, materials } = useGLTF('./models/tracks/paris-bis.glb')
materials.M_Cmn_ShadowCollision.opacity = 0
materials.M_Cmn_ShadowCollision.transparent = true
return (
<group {...props} scale={50} position={[0,-3.6,0]} dispose={null}>
<group scale={0.01}>
<mesh castShadow receiveShadow geometry={nodes.N_Audience_NoMove_01_M_Cmn_AudienceModel_0.geometry} material={materials.M_Cmn_AudienceModel} />
<mesh castShadow receiveShadow geometry={nodes.F_Building_M_Cmn_MainColor_Detail_0.geometry} material={materials.M_Cmn_MainColor_Detail} />
<mesh castShadow receiveShadow geometry={nodes.F_Building_M_Mobp1_Textures01_0.geometry} material={materials.M_Mobp1_Textures01} />
<mesh castShadow receiveShadow geometry={nodes.F_Obj_01_M_Cmn_MainColor_Detail_0.geometry} material={materials.M_Cmn_MainColor_Detail} />
<mesh castShadow receiveShadow geometry={nodes.M_GeneralMansion_Roof_M_Cmn_MainColor_Detail_0.geometry} material={materials.M_Cmn_MainColor_Detail} />
<mesh castShadow receiveShadow geometry={nodes.M_GeneralMansion_Roof_M_Mobp1_Textures01_0.geometry} material={materials.M_Mobp1_Textures01} />
<mesh castShadow receiveShadow geometry={nodes.N_MansionObj_01_M_Cmn_MainColor_Detail_0.geometry} material={materials.M_Cmn_MainColor_Detail} />
<mesh castShadow receiveShadow geometry={nodes.N_MansionObj_01_M_Mobp1_kanban_0.geometry} material={materials.M_Mobp1_kanban} />
<mesh castShadow receiveShadow geometry={nodes.N_MansionObj_01_M_Mobp1_Textures01_0.geometry} material={materials.M_Mobp1_Textures01} />
<mesh castShadow receiveShadow geometry={nodes.N_MansionObj_02_M_Cmn_MainColor_Detail_0.geometry} material={materials.M_Cmn_MainColor_Detail} />
<mesh castShadow receiveShadow geometry={nodes.N_MansionObj_02_M_Mobp1_kanban_0.geometry} material={materials.M_Mobp1_kanban} />
<mesh castShadow receiveShadow geometry={nodes.N_MansionObj_02_M_Mobp1_Textures01_0.geometry} material={materials.M_Mobp1_Textures01} />
<mesh castShadow receiveShadow geometry={nodes.N_Obj_001_M_Cmn_MainColor_Detail_0.geometry} material={materials.M_Cmn_MainColor_Detail} />
<mesh castShadow receiveShadow geometry={nodes.N_Obj_001_M_Mobp1_kanban_0.geometry} material={materials.M_Mobp1_kanban} />
<mesh castShadow receiveShadow geometry={nodes.N_Obj_002_M_Cmn_MainColor_Detail_0.geometry} material={materials.M_Cmn_MainColor_Detail} />
<mesh castShadow receiveShadow geometry={nodes.N_Obj_002_M_Mobp1_kanban_0.geometry} material={materials.M_Mobp1_kanban} />
<mesh castShadow receiveShadow geometry={nodes.N_Obj_003_M_Cmn_MainColor_Detail_0.geometry} material={materials.M_Cmn_MainColor_Detail} />
<mesh castShadow receiveShadow geometry={nodes.N_Obj_003_M_Mobp1_kanban_0.geometry} material={materials.M_Mobp1_kanban} />
<mesh castShadow receiveShadow geometry={nodes.N_Obj_003_M_Mobp1_Window_0.geometry} material={materials.M_Mobp1_Window} />
<mesh castShadow receiveShadow geometry={nodes.N_Obj_004_M_Cmn_MainColor_Detail_0.geometry} material={materials.M_Cmn_MainColor_Detail} />
<mesh castShadow receiveShadow geometry={nodes.N_Obj_004_M_Mobp1_kanban_0.geometry} material={materials.M_Mobp1_kanban} />
<mesh castShadow receiveShadow geometry={nodes.N_Obj_005_M_Cmn_MainColor_Detail_0.geometry} material={materials.M_Cmn_MainColor_Detail} />
<mesh castShadow receiveShadow geometry={nodes.N_Obj_005_M_Mobp1_kanban_0.geometry} material={materials.M_Mobp1_kanban} />
<mesh castShadow receiveShadow geometry={nodes.N_Obj_005_M_Mobp1_Window_0.geometry} material={materials.M_Mobp1_Window} />
<mesh castShadow receiveShadow geometry={nodes.N_Obj_006_M_Cmn_MainColor_Detail_0.geometry} material={materials.M_Cmn_MainColor_Detail} />
<mesh castShadow receiveShadow geometry={nodes.N_Obj_006_M_Mobp1_kanban_0.geometry} material={materials.M_Mobp1_kanban} />
<mesh castShadow receiveShadow geometry={nodes.N_Obj_007_M_Cmn_MainColor_Detail_0.geometry} material={materials.M_Cmn_MainColor_Detail} />
<mesh castShadow receiveShadow geometry={nodes.N_Obj_007_M_Mobp1_kanban_0.geometry} material={materials.M_Mobp1_kanban} />
<mesh castShadow receiveShadow geometry={nodes.N_Obj_008_M_Cmn_MainColor_Detail_0.geometry} material={materials.M_Cmn_MainColor_Detail} />
<mesh castShadow receiveShadow geometry={nodes.N_Obj_008_M_Mobp1_kanban_0.geometry} material={materials.M_Mobp1_kanban} />
<mesh castShadow receiveShadow geometry={nodes.N_Obj_009_M_Cmn_MainColor_Detail_0.geometry} material={materials.M_Cmn_MainColor_Detail} />
<mesh castShadow receiveShadow geometry={nodes.N_Obj_009_M_Mobp1_kanban_0.geometry} material={materials.M_Mobp1_kanban} />
<mesh castShadow receiveShadow geometry={nodes.N_Obj_010_M_Cmn_MainColor_Detail_0.geometry} material={materials.M_Cmn_MainColor_Detail} />
<mesh castShadow receiveShadow geometry={nodes.N_Obj_010_M_Mobp1_kanban_0.geometry} material={materials.M_Mobp1_kanban} />
<mesh castShadow receiveShadow geometry={nodes.N_UniqueBuilding_Parts_M_Cmn_MainColor_Detail_0.geometry} material={materials.M_Cmn_MainColor_Detail} />
<mesh castShadow receiveShadow geometry={nodes.N_UniqueBuilding_Parts_M_Mobp1_kanban_0.geometry} material={materials.M_Mobp1_kanban} />
<mesh castShadow receiveShadow geometry={nodes.Rainbow_model_M_Mobp1_Rainbow_0.geometry} material={materials.M_Mobp1_Rainbow} position={[-16, 0.14, 0]} rotation={[0, -1.571, 0]} />
<mesh castShadow receiveShadow geometry={nodes.F_BlindBuilding_M_Cmn_MainColor_Detail_0.geometry} material={materials.M_Cmn_MainColor_Detail} />
<mesh castShadow receiveShadow geometry={nodes.F_BlindBuilding_M_Mobp1_Textures01_0.geometry} material={materials.M_Mobp1_Textures01} />
<mesh castShadow receiveShadow geometry={nodes.F_effel_M_Cmn_MainColor_Detail_0.geometry} material={materials.M_Cmn_MainColor_Detail} />
<mesh castShadow receiveShadow geometry={nodes.F_Ground_01_M_Cmn_MainColor_Detail_0.geometry} material={materials.M_Cmn_MainColor_Detail} />
<mesh castShadow receiveShadow geometry={nodes.F_Ground_01_M_Mobp1_Textures01_0.geometry} material={materials.M_Mobp1_Textures01} />
<mesh castShadow receiveShadow geometry={nodes.F_Ground_01_M_Mobp1_Water_0.geometry} material={materials.M_Mobp1_Water} />
<mesh castShadow receiveShadow geometry={nodes.F_Ground_01_M_Mobp1_Window_0.geometry} material={materials.M_Mobp1_Window} />
<mesh castShadow receiveShadow geometry={nodes.Gmob_Paris_VR_M_Mobp1_VR_0.geometry} material={materials.M_Mobp1_VR} position={[0, -451.06, 0]} />
<mesh castShadow receiveShadow geometry={nodes.M_Building_001_M_Cmn_MainColor_Detail_0.geometry} material={materials.M_Cmn_MainColor_Detail} />
<mesh castShadow receiveShadow geometry={nodes.M_Building_001_M_Mobp1_Textures01_0.geometry} material={materials.M_Mobp1_Textures01} />
<mesh castShadow receiveShadow geometry={nodes.M_Building_001_M_Mobp1_Window_0.geometry} material={materials.M_Mobp1_Window} />
<mesh castShadow receiveShadow geometry={nodes.N_Building_001_M_Cmn_MainColor_Detail_0.geometry} material={materials.M_Cmn_MainColor_Detail} />
<mesh castShadow receiveShadow geometry={nodes.N_Building_001_M_Mobp1_Textures01_0.geometry} material={materials.M_Mobp1_Textures01} />
<mesh castShadow receiveShadow geometry={nodes.N_Building_001_M_Mobp1_Window_0.geometry} material={materials.M_Mobp1_Window} />
<mesh castShadow receiveShadow geometry={nodes.N_Building_002_M_Cmn_MainColor_Detail_0.geometry} material={materials.M_Cmn_MainColor_Detail} />
<mesh castShadow receiveShadow geometry={nodes.N_Building_002_M_Mobp1_gaisenmon_tex_0.geometry} material={materials.M_Mobp1_gaisenmon_tex} />
<mesh castShadow receiveShadow geometry={nodes.N_Building_002_M_Mobp1_kanban_0.geometry} material={materials.M_Mobp1_kanban} />
<mesh castShadow receiveShadow geometry={nodes.N_Building_002_M_Mobp1_Textures01_0.geometry} material={materials.M_Mobp1_Textures01} />
<mesh castShadow receiveShadow geometry={nodes.N_Building_002_M_Mobp1_Window_0.geometry} material={materials.M_Mobp1_Window} />
<mesh castShadow receiveShadow geometry={nodes.N_Building_003_M_Cmn_MainColor_Detail_0.geometry} material={materials.M_Cmn_MainColor_Detail} />
<mesh castShadow receiveShadow geometry={nodes.N_Building_003_M_Mobp1_Textures01_0.geometry} material={materials.M_Mobp1_Textures01} />
<mesh castShadow receiveShadow geometry={nodes.N_Building_003_M_Mobp1_Window_0.geometry} material={materials.M_Mobp1_Window} />
<mesh castShadow receiveShadow geometry={nodes.N_Building_004_M_Cmn_MainColor_Detail_0.geometry} material={materials.M_Cmn_MainColor_Detail} />
<mesh castShadow receiveShadow geometry={nodes.N_Building_004_M_Mobp1_Textures01_0.geometry} material={materials.M_Mobp1_Textures01} />
<mesh castShadow receiveShadow geometry={nodes.N_Building_004_M_Mobp1_Window_0.geometry} material={materials.M_Mobp1_Window} />
<mesh castShadow receiveShadow geometry={nodes.N_effel_M_Cmn_MainColor_Detail_0.geometry} material={materials.M_Cmn_MainColor_Detail} />
<mesh castShadow receiveShadow geometry={nodes.N_effel_M_Mobp1_Window_0.geometry} material={materials.M_Mobp1_Window} />
<mesh castShadow receiveShadow geometry={nodes.N_Obj_000_M_Cmn_MainColor_Detail_0.geometry} material={materials.M_Cmn_MainColor_Detail} />
<mesh castShadow receiveShadow geometry={nodes.N_Obj_000_M_Mobp1_Textures01_0.geometry} material={materials.M_Mobp1_Textures01} />
<mesh castShadow receiveShadow geometry={nodes.N_Obj_000_M_Mobp1_Transparent_0.geometry} material={materials.M_Mobp1_Transparent} />
<mesh castShadow receiveShadow geometry={nodes.N_Obj_000_M_Mobp1_Window_0.geometry} material={materials.M_Mobp1_Window} />
<mesh castShadow receiveShadow geometry={nodes.N_UniqueBuilding_M_Cmn_MainColor_Detail_0.geometry} material={materials.M_Cmn_MainColor_Detail} />
<mesh castShadow receiveShadow geometry={nodes.N_UniqueBuilding_M_Mobp1_gaisenmon_tex_0.geometry} material={materials.M_Mobp1_gaisenmon_tex} />
<mesh castShadow receiveShadow geometry={nodes.N_UniqueBuilding_M_Mobp1_Textures01_0.geometry} material={materials.M_Mobp1_Textures01} />
<mesh castShadow receiveShadow geometry={nodes.N_UniqueBuilding_M_Mobp1_Window_0.geometry} material={materials.M_Mobp1_Window} />
<mesh castShadow receiveShadow geometry={nodes.BlindTree_M_Cmn_MainColor_Detail_0.geometry} material={materials.M_Cmn_MainColor_Detail} />
<mesh castShadow receiveShadow geometry={nodes.Low_Obj_M_Cmn_MainColor_Detail_0.geometry} material={materials.M_Cmn_MainColor_Detail} />
<mesh castShadow receiveShadow geometry={nodes.Low_Obj_M_Mobp1_kanban_0.geometry} material={materials.M_Mobp1_kanban} />
<mesh castShadow receiveShadow geometry={nodes.N_Road_Ground_M_Cmn_MainColor_Detail_0.geometry} material={materials.M_Cmn_MainColor_Detail} />
<mesh castShadow receiveShadow geometry={nodes.N_Road_Ground_M_Mobp1_Road_A_0.geometry} material={materials.M_Mobp1_Road_A} />
<mesh castShadow receiveShadow geometry={nodes.N_Road_Ground_M_Mobp1_Road_B_0.geometry} material={materials.M_Mobp1_Road_B} />
<mesh castShadow receiveShadow geometry={nodes.N_Road_Ground_M_Mobp1_RoadColor_0.geometry} material={materials.M_Mobp1_RoadColor} />
<mesh castShadow receiveShadow geometry={nodes.N_Road_Ground_M_Mobp1_Water_0.geometry} material={materials.M_Mobp1_Water} />
<mesh castShadow receiveShadow geometry={nodes.N_Road_Ground_M_Mobp1_Window_0.geometry} material={materials.M_Mobp1_Window} />
<mesh castShadow receiveShadow geometry={nodes.N_Trocadero_M_Cmn_MainColor_Detail_0.geometry} material={materials.M_Cmn_MainColor_Detail} />
<mesh castShadow receiveShadow geometry={nodes.N_Trocadero_M_Mobp1_RoadColor_0.geometry} material={materials.M_Mobp1_RoadColor} />
<mesh castShadow receiveShadow geometry={nodes.N_Trocadero_Water_M_Mobp1_Water_0.geometry} material={materials.M_Mobp1_Water} />
<RigidBody type="fixed" colliders="trimesh" name="terrain">
<mesh castShadow receiveShadow geometry={nodes.ShadowCollision_M_Cmn_ShadowCollision_0.geometry} material={materials.M_Cmn_ShadowCollision} position={[0, 0.244, 0]} />
</RigidBody>
</group>
</group>
)
}
useGLTF.preload('./models/tracks/paris-bis.glb')

Some files were not shown because too many files have changed in this diff Show More