mirror of
https://github.com/Floriansylvain/generic-threejs-game.git
synced 2026-08-19 11:43:18 +02:00
feat: WIP chunk generation
This commit is contained in:
+20
-36
@@ -3,11 +3,12 @@ import "./App.css";
|
|||||||
import { Canvas } from "@react-three/fiber";
|
import { Canvas } from "@react-three/fiber";
|
||||||
import { KeyboardControls } from "@react-three/drei";
|
import { KeyboardControls } from "@react-three/drei";
|
||||||
import { useEffect, useRef, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import { PCFSoftShadowMap, Vector2, Vector3 } from "three";
|
import { PCFSoftShadowMap, Vector3 } from "three";
|
||||||
import { Player } from "./components/Player";
|
import { Player } from "./components/Player";
|
||||||
import { Bloom, EffectComposer, Vignette } from "@react-three/postprocessing";
|
import { Bloom, EffectComposer, Vignette } from "@react-three/postprocessing";
|
||||||
import { Cubes } from "./components/Cubes";
|
import { Cubes } from "./components/Cubes";
|
||||||
import { World } from "./components/World";
|
import { GameContext } from "./hooks/GameContext";
|
||||||
|
import { ChunkGenerator } from "./components/ChunkGenerator";
|
||||||
|
|
||||||
const CUBES_QT = 10;
|
const CUBES_QT = 10;
|
||||||
|
|
||||||
@@ -36,43 +37,26 @@ function App() {
|
|||||||
className="canvas"
|
className="canvas"
|
||||||
ref={container}
|
ref={container}
|
||||||
shadows={{ type: PCFSoftShadowMap }}
|
shadows={{ type: PCFSoftShadowMap }}
|
||||||
camera={{ fov: 50, frustumCulled: true, near: 0.1, far: 500 }}
|
camera={{ fov: 50, frustumCulled: true, near: 0.1, far: 129 }}
|
||||||
>
|
>
|
||||||
<Cubes cubesPosition={cubes}></Cubes>
|
<Cubes cubesPosition={cubes}></Cubes>
|
||||||
|
|
||||||
{/* <mesh
|
<GameContext.Provider value={{ playerPosition: new Vector3() }}>
|
||||||
rotation={[-Math.PI / 2, 0, 0]}
|
<KeyboardControls
|
||||||
position={[0, 0, 0]}
|
map={[
|
||||||
receiveShadow
|
{ keys: ["w", "ArrowUp"], name: "moveForward" },
|
||||||
castShadow
|
{ keys: ["s", "ArrowDown"], name: "moveBackward" },
|
||||||
>
|
{ keys: ["a", "ArrowLeft"], name: "moveLeft" },
|
||||||
<planeGeometry
|
{ keys: ["d", "ArrowRight"], name: "moveRight" },
|
||||||
attach={"geometry"}
|
]}
|
||||||
args={[5000, 5000]}
|
>
|
||||||
></planeGeometry>
|
<Player></Player>
|
||||||
<meshStandardMaterial
|
<ChunkGenerator></ChunkGenerator>
|
||||||
toneMapped={false}
|
{/* <Chunk position={new Vector2(0, 0)} seed={2234180}></Chunk>
|
||||||
color={"green"}
|
<Chunk position={new Vector2(100, 0)} seed={2234180}></Chunk>
|
||||||
></meshStandardMaterial>
|
<Chunk position={new Vector2(0, 100)} seed={2234180}></Chunk> */}
|
||||||
</mesh> */}
|
</KeyboardControls>
|
||||||
|
</GameContext.Provider>
|
||||||
<World position={new Vector2(0, 0)} seed={0.12354}></World>
|
|
||||||
<World position={new Vector2(100, 0)} seed={0.12354}></World>
|
|
||||||
<World position={new Vector2(100, 100)} seed={0.12354}></World>
|
|
||||||
<World position={new Vector2(0, 100)} seed={0.12354}></World>
|
|
||||||
|
|
||||||
<KeyboardControls
|
|
||||||
map={[
|
|
||||||
{ keys: ["w", "ArrowUp"], name: "moveForward" },
|
|
||||||
{ keys: ["s", "ArrowDown"], name: "moveBackward" },
|
|
||||||
{ keys: ["a", "ArrowLeft"], name: "moveLeft" },
|
|
||||||
{ keys: ["d", "ArrowRight"], name: "moveRight" },
|
|
||||||
{ keys: ["Space"], name: "jump" },
|
|
||||||
{ keys: ["ShiftLeft"], name: "sprint" },
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<Player></Player>
|
|
||||||
</KeyboardControls>
|
|
||||||
|
|
||||||
<ambientLight intensity={1} />
|
<ambientLight intensity={1} />
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import {
|
import {
|
||||||
ClampToEdgeWrapping,
|
ClampToEdgeWrapping,
|
||||||
|
FrontSide,
|
||||||
RepeatWrapping,
|
RepeatWrapping,
|
||||||
TextureLoader,
|
TextureLoader,
|
||||||
Vector2,
|
Vector2,
|
||||||
@@ -7,11 +8,15 @@ import {
|
|||||||
} from "three";
|
} from "three";
|
||||||
import { ImprovedNoise } from "three/examples/jsm/Addons.js";
|
import { ImprovedNoise } from "three/examples/jsm/Addons.js";
|
||||||
|
|
||||||
export function World(props: { position: Vector2; seed: number }): JSX.Element {
|
export function Chunk(props: { position: Vector2; seed: number }): JSX.Element {
|
||||||
const size = 100;
|
const size = 100;
|
||||||
const scale = 3;
|
const scale = 1.5;
|
||||||
const amplitude = 30;
|
const amplitude = 30;
|
||||||
const overlap = 0.5; // Amount of overlap between chunks
|
const overlap = 0.5;
|
||||||
|
const geometry = 50;
|
||||||
|
const chunkSize = 100;
|
||||||
|
|
||||||
|
const adjustedGeometry = geometry + overlap * 2;
|
||||||
|
|
||||||
const noise = (x: number, y: number): number => {
|
const noise = (x: number, y: number): number => {
|
||||||
const noise = new ImprovedNoise();
|
const noise = new ImprovedNoise();
|
||||||
@@ -66,7 +71,7 @@ export function World(props: { position: Vector2; seed: number }): JSX.Element {
|
|||||||
>
|
>
|
||||||
<planeGeometry
|
<planeGeometry
|
||||||
attach="geometry"
|
attach="geometry"
|
||||||
args={[100, 100, 100 + overlap * 2, 100 + overlap * 2]}
|
args={[chunkSize, chunkSize, adjustedGeometry, adjustedGeometry]}
|
||||||
></planeGeometry>
|
></planeGeometry>
|
||||||
<meshStandardMaterial
|
<meshStandardMaterial
|
||||||
toneMapped={false}
|
toneMapped={false}
|
||||||
@@ -74,6 +79,7 @@ export function World(props: { position: Vector2; seed: number }): JSX.Element {
|
|||||||
map={grassTexture}
|
map={grassTexture}
|
||||||
displacementMap={displacementMap}
|
displacementMap={displacementMap}
|
||||||
displacementScale={amplitude}
|
displacementScale={amplitude}
|
||||||
|
shadowSide={FrontSide}
|
||||||
/>
|
/>
|
||||||
</mesh>
|
</mesh>
|
||||||
</group>
|
</group>
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
import { useContext, useEffect, useState } from "react";
|
||||||
|
import { GameContext } from "../hooks/GameContext";
|
||||||
|
import { useFrame } from "@react-three/fiber";
|
||||||
|
import { Vector2 } from "three";
|
||||||
|
import { Chunk } from "./Chunk";
|
||||||
|
|
||||||
|
export function ChunkGenerator(): JSX.Element {
|
||||||
|
const { playerPosition } = useContext(GameContext);
|
||||||
|
const [chunks, setChunks] = useState([] as JSX.Element[]);
|
||||||
|
|
||||||
|
const [lastPlayerPosition] = useState(new Vector2(0, 0));
|
||||||
|
|
||||||
|
const chunkPosVec2 = new Vector2();
|
||||||
|
|
||||||
|
function generateChunk(x: number, y: number) {
|
||||||
|
setChunks([
|
||||||
|
<Chunk
|
||||||
|
key={`${x}-${y}`}
|
||||||
|
position={chunkPosVec2.set(x * 100, y * 100)}
|
||||||
|
seed={897624}
|
||||||
|
/>,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
generateChunk(0, 0);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useFrame(() => {
|
||||||
|
const playerX = Math.floor(playerPosition.x / 100 + 0.5);
|
||||||
|
const playerY = Math.floor(playerPosition.z / 100 + 0.5);
|
||||||
|
|
||||||
|
// generateChunk(playerX, playerY);
|
||||||
|
// console.log("player", playerX, playerY);
|
||||||
|
|
||||||
|
// // every time the player moves to a new chunk, generate 3x3 chunks around the player
|
||||||
|
// for (let x = -1; x <= 1; x++) {
|
||||||
|
// for (let y = -1; y <= 1; y++) {
|
||||||
|
// generateChunk(playerX + x, playerY + y);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
lastPlayerPosition.set(playerX, playerY);
|
||||||
|
});
|
||||||
|
|
||||||
|
return <>{chunks}</>;
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useAnimations, useGLTF, useKeyboardControls } from "@react-three/drei";
|
import { useAnimations, useGLTF, useKeyboardControls } from "@react-three/drei";
|
||||||
import { useFrame, useThree } from "@react-three/fiber";
|
import { useFrame, useThree } from "@react-three/fiber";
|
||||||
import { MutableRefObject, useEffect, useRef } from "react";
|
import { MutableRefObject, useContext, useEffect, useRef } from "react";
|
||||||
import {
|
import {
|
||||||
DirectionalLight,
|
DirectionalLight,
|
||||||
Euler,
|
Euler,
|
||||||
@@ -10,6 +10,7 @@ import {
|
|||||||
Vector3,
|
Vector3,
|
||||||
} from "three";
|
} from "three";
|
||||||
import { AnimationState } from "../models/Animations";
|
import { AnimationState } from "../models/Animations";
|
||||||
|
import { GameContext } from "../hooks/GameContext";
|
||||||
|
|
||||||
export interface KeyPressed {
|
export interface KeyPressed {
|
||||||
moveForward: boolean;
|
moveForward: boolean;
|
||||||
@@ -53,6 +54,8 @@ export function Player(): JSX.Element {
|
|||||||
];
|
];
|
||||||
const lastAnimState = {} as AnimationState;
|
const lastAnimState = {} as AnimationState;
|
||||||
|
|
||||||
|
const useGameContext = useContext(GameContext);
|
||||||
|
|
||||||
const setAnimState = (name: string, isPlaying: boolean): void => {
|
const setAnimState = (name: string, isPlaying: boolean): void => {
|
||||||
const anim = animsState.find((anim) => anim.name === name);
|
const anim = animsState.find((anim) => anim.name === name);
|
||||||
if (!anim) return;
|
if (!anim) return;
|
||||||
@@ -148,6 +151,7 @@ export function Player(): JSX.Element {
|
|||||||
rotateBackwards();
|
rotateBackwards();
|
||||||
}
|
}
|
||||||
interpolatePlayerQuaternionToTargetRotation();
|
interpolatePlayerQuaternionToTargetRotation();
|
||||||
|
useGameContext.playerPosition.copy(model.scene.position);
|
||||||
}
|
}
|
||||||
|
|
||||||
function setCameraPosition(): void {
|
function setCameraPosition(): void {
|
||||||
@@ -200,6 +204,9 @@ export function Player(): JSX.Element {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
model.scene.position.y = 10;
|
model.scene.position.y = 10;
|
||||||
|
if (dirLightRef.current) {
|
||||||
|
dirLightRef.current.shadow.bias = -0.0001;
|
||||||
|
}
|
||||||
window.addEventListener("mousemove", onMouseMove);
|
window.addEventListener("mousemove", onMouseMove);
|
||||||
return () => window.removeEventListener("mousemove", onMouseMove);
|
return () => window.removeEventListener("mousemove", onMouseMove);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import { createContext } from "react";
|
||||||
|
import { Vector3 } from "three";
|
||||||
|
|
||||||
|
export const GameContext = createContext({
|
||||||
|
playerPosition: new Vector3(),
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user