diff --git a/src/components/SceneEditorView.tsx b/src/components/SceneEditorView.tsx index 98e18c7..e1eb390 100644 --- a/src/components/SceneEditorView.tsx +++ b/src/components/SceneEditorView.tsx @@ -1,24 +1,12 @@ -import { useLayoutEffect, useRef } from 'react'; +import { useRef } from 'react'; import type React from 'react'; -import { useThree } from '@react-three/fiber'; import { Grid, OrbitControls } from '@react-three/drei'; import { observer } from 'mobx-react-lite'; import { state } from '../state'; import { SceneView } from './SceneView'; -import type { Pos3 } from '../types/3d'; import { type OrthographicCamera, type PerspectiveCamera } from 'three'; +import { CameraSync } from './tools/CameraSync'; -const CameraSync = observer(function ({ camera }: { camera: Pos3 }) { - const { camera: threeCamera } = useThree(); - - useLayoutEffect(() => { - threeCamera.position.set(camera.position[0], camera.position[1], camera.position[2]); - threeCamera.rotation.set(camera.look[0], camera.look[1], camera.look[2]); - threeCamera.updateProjectionMatrix(); - }); - - return null; -}); export const SceneEditorView = observer(function () { const controlsRef = useRef>(null); diff --git a/src/components/ThreeView.tsx b/src/components/ThreeView.tsx index de0293e..72f140d 100644 --- a/src/components/ThreeView.tsx +++ b/src/components/ThreeView.tsx @@ -49,14 +49,14 @@ export const ThreeView = observer(function () { { state.game ? <> - + { state.game!.isPaused ? : } - : + : } diff --git a/src/components/tools/CameraSync.tsx b/src/components/tools/CameraSync.tsx new file mode 100644 index 0000000..34781cd --- /dev/null +++ b/src/components/tools/CameraSync.tsx @@ -0,0 +1,16 @@ +import { useThree } from "@react-three/fiber"; +import type { Pos3 } from "../../types/3d"; +import { useLayoutEffect } from "react"; +import { observer } from "mobx-react-lite"; + +export const CameraSync = observer(function ({ camera }: { camera: Pos3 }) { + const { camera: threeCamera } = useThree(); + + useLayoutEffect(() => { + threeCamera.position.set(camera.position[0], camera.position[1], camera.position[2]); + threeCamera.rotation.set(camera.look[0], camera.look[1], camera.look[2]); + threeCamera.updateProjectionMatrix(); + }); + + return null; +}); \ No newline at end of file diff --git a/src/model/worldFactory.ts b/src/model/worldFactory.ts index 18a008e..715430f 100644 --- a/src/model/worldFactory.ts +++ b/src/model/worldFactory.ts @@ -14,9 +14,6 @@ export class WorldFactory { }, objects: {}, }, - state: { - playing: false, - }, gameRules: { gravity: true, }, diff --git a/src/state/gameState.ts b/src/state/gameState.ts index 73bc046..ed4cc0d 100644 --- a/src/state/gameState.ts +++ b/src/state/gameState.ts @@ -1,27 +1,33 @@ -import { makeAutoObservable } from "mobx"; +import { makeAutoObservable, toJS } from "mobx"; import type { WorldState } from "./worldState"; -import type { RunningGameState, Scene } from "../types"; +import type { Game, Scene } from "../types"; import type { Pos3 } from "../types/3d"; import type { CameraProps } from "@react-three/fiber"; +import { clone } from "../utils"; +import { state } from "./rootState"; export class GameState { private readonly world: WorldState; + public readonly data: Game; + constructor(world: WorldState) { this.world = world; + this.data = { + paused: false, + time: 0, + scene: clone(toJS(this.world.data.initialScene)), + }; + makeAutoObservable(this); } - public get state(): RunningGameState { - return this.world.data.state as RunningGameState; - } - public get isPaused(): boolean { - return this.state.paused; + return this.data.paused; } public get scene(): Scene { - return this.state.scene; + return this.data.scene; } public get camera(): Pos3 { @@ -38,18 +44,17 @@ export class GameState { } public resume(): void { - this.state.paused = false; + this.data.paused = false; } public pause(): void { - this.state.paused = true; + this.data.paused = true; } - public stop(): void { - this.world.data.state = { playing: false }; - } + public tick(deltaTime: number): void { + if (this.isPaused) + return; - public tick(_deltaTime: number): void { - //TODO + this.data.time += deltaTime; } } \ No newline at end of file diff --git a/src/state/rootState.ts b/src/state/rootState.ts index 19ccfba..31d6207 100644 --- a/src/state/rootState.ts +++ b/src/state/rootState.ts @@ -6,6 +6,7 @@ import { GameState } from "./gameState"; export class RootState { public readonly world = new WorldState(); public readonly worldEditor: WorldEditorState; + public game: GameState | undefined; constructor() { this.worldEditor = new WorldEditorState(this.world); @@ -19,12 +20,22 @@ export class RootState { } public get isGamePlaying(): boolean { - return this.world.data.state.playing; + return this.game !== undefined; } - public get game(): GameState | undefined { - if (this.isGamePlaying) - return new GameState(this.world); + public startGame(): void { + if (this.game) + this.stopGame(); + this.game = new GameState(this.world), + state.worldEditor.resetSelectedObject(); + } + + public stopGame(): void { + if (!this.game) + return; + + this.game.pause(); + this.game = undefined; } } diff --git a/src/state/worldState.ts b/src/state/worldState.ts index 7995dc8..703d3b8 100644 --- a/src/state/worldState.ts +++ b/src/state/worldState.ts @@ -74,9 +74,6 @@ export class WorldState { gameRules: { gravity: true, }, - state: { - playing: false, - }, }; console.log(objects); state.worldEditor.resetSelectedObject(); @@ -109,18 +106,4 @@ export class WorldState { public getVoxelTypeById(id: string): VoxelType | undefined { return this.data.voxelTypes[id]; } - - public play(): void { - if (state.game) - state.game.resume(); - else { - this.data.state = { - playing: true, - paused: false, - time: 0, - scene: clone(this.data.initialScene), - } - state.worldEditor.resetSelectedObject(); - } - } } diff --git a/src/types/game.ts b/src/types/game.ts new file mode 100644 index 0000000..5877dee --- /dev/null +++ b/src/types/game.ts @@ -0,0 +1,7 @@ +import type { Scene } from "./scene"; + +export type Game = { + paused: boolean; + time: number; + scene: Scene; +} diff --git a/src/types/gameState.ts b/src/types/gameState.ts deleted file mode 100644 index e8d695e..0000000 --- a/src/types/gameState.ts +++ /dev/null @@ -1,14 +0,0 @@ -import type { Scene } from "./scene"; - -export type StoppedGameState = { - playing: false; -} - -export type RunningGameState = { - playing: true; - paused: boolean; - time: number; - scene: Scene; -} - -export type GameState = StoppedGameState | RunningGameState; diff --git a/src/types/index.ts b/src/types/index.ts index 005ebad..098f42a 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -2,7 +2,7 @@ export * from './object'; export * from './scene'; export * from './world'; export * from './gameRules'; -export * from './gameState'; +export * from './game'; export * from './character'; diff --git a/src/types/world.ts b/src/types/world.ts index df77431..c3736a9 100644 --- a/src/types/world.ts +++ b/src/types/world.ts @@ -1,5 +1,4 @@ import type { GameRules } from "./gameRules"; -import type { GameState } from "./gameState"; import type { ObjectType } from "./object"; import type { Scene } from "./scene"; import type { Pos3 } from "./3d"; @@ -11,5 +10,4 @@ export type World = { editorCamera: Pos3; initialScene: Scene; gameRules: GameRules; - state: GameState; }