Scene switching powered by Redux!
This commit is contained in:
parent
efb127dedd
commit
0b30af51c8
11 changed files with 58 additions and 46 deletions
|
@ -1,32 +1,16 @@
|
||||||
import React, { Fragment } from "react";
|
import React, { Fragment } from "react";
|
||||||
import useLoader from "~game/lib/Loader";
|
import { useSelector } from "react-redux";
|
||||||
import InGameSpaceBG from "./backgrounds/InGameSpaceBG";
|
import { SceneStore } from "~store/scene/reducer";
|
||||||
|
import { GameStore } from "~store/state";
|
||||||
// Resources, this will make TS go crazy!
|
import MapEditor from "~game/scenes/MapEditor";
|
||||||
|
|
||||||
//@ts-expect-error Image resource
|
|
||||||
import NoiseSpaceFine from "~/../assets/images/noise/space_fine.png";
|
|
||||||
//@ts-expect-error Image resource
|
|
||||||
import NoiseSpaceSparse from "~/../assets/images/noise/space_sparse.png";
|
|
||||||
|
|
||||||
export default function Game() {
|
export default function Game() {
|
||||||
const { loaded, resources } = useLoader({
|
const scene = useSelector<GameStore, SceneStore>((state) => state.scene);
|
||||||
bg_fine: NoiseSpaceFine,
|
switch (scene.type) {
|
||||||
bg_sparse: NoiseSpaceSparse,
|
case "MapEditor":
|
||||||
});
|
return <MapEditor />;
|
||||||
|
default:
|
||||||
if (!loaded) {
|
// Bad case, should have something to show just in case!
|
||||||
return <Fragment></Fragment>;
|
return <Fragment></Fragment>;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
|
||||||
<Fragment>
|
|
||||||
<InGameSpaceBG
|
|
||||||
textures={{
|
|
||||||
noise_fine: resources.bg_fine,
|
|
||||||
noise_sparse: resources.bg_sparse,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Fragment>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,11 @@ import NoiseSpaceSparse from "~/../assets/images/noise/space_sparse.png";
|
||||||
import LoadingScreen from "./LoadingScreen";
|
import LoadingScreen from "./LoadingScreen";
|
||||||
import useUILayer from "~ui/utils/useLayer";
|
import useUILayer from "~ui/utils/useLayer";
|
||||||
|
|
||||||
|
// Scene switcher entry
|
||||||
|
export interface MapEditorScene {
|
||||||
|
type: "MapEditor";
|
||||||
|
}
|
||||||
|
|
||||||
export default function MapEditor() {
|
export default function MapEditor() {
|
||||||
const { loaded, resources } = useLoader({
|
const { loaded, resources } = useLoader({
|
||||||
bg_fine: NoiseSpaceFine,
|
bg_fine: NoiseSpaceFine,
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { Stage } from "@inlet/react-pixi";
|
||||||
import { configureStore } from "@reduxjs/toolkit";
|
import { configureStore } from "@reduxjs/toolkit";
|
||||||
import UI from "~ui/UI";
|
import UI from "~ui/UI";
|
||||||
import reducer from "~store/reducer";
|
import reducer from "~store/reducer";
|
||||||
import MapEditor from "~game/scenes/MapEditor";
|
import Game from "~game/scenes/Game";
|
||||||
|
|
||||||
PIXI.settings.SCALE_MODE = PIXI.SCALE_MODES.NEAREST;
|
PIXI.settings.SCALE_MODE = PIXI.SCALE_MODES.NEAREST;
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ ReactDOM.render(
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<Stage options={{ resolution: 1, resizeTo: window }} onMount={mounted}>
|
<Stage options={{ resolution: 1, resizeTo: window }} onMount={mounted}>
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<MapEditor />
|
<Game />
|
||||||
</Provider>
|
</Provider>
|
||||||
</Stage>
|
</Stage>
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { combineReducers } from "@reduxjs/toolkit";
|
import { combineReducers } from "@reduxjs/toolkit";
|
||||||
import uiReducer from "./ui/reducer";
|
import uiReducer from "./ui/reducer";
|
||||||
|
import sceneReducer from "./scene/reducer";
|
||||||
|
|
||||||
const reducer = combineReducers({ ui: uiReducer });
|
const reducer = combineReducers({ ui: uiReducer, scene: sceneReducer });
|
||||||
|
|
||||||
export default reducer;
|
export default reducer;
|
||||||
|
|
17
src/store/scene/reducer.ts
Normal file
17
src/store/scene/reducer.ts
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
|
||||||
|
import { MapEditorScene } from "~game/scenes/MapEditor";
|
||||||
|
|
||||||
|
export type SceneStore = MapEditorScene;
|
||||||
|
|
||||||
|
const initialState: SceneStore = {
|
||||||
|
type: "MapEditor",
|
||||||
|
};
|
||||||
|
|
||||||
|
const sceneSlice = createSlice({
|
||||||
|
name: "scene",
|
||||||
|
initialState,
|
||||||
|
reducers: {},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const {} = sceneSlice.actions;
|
||||||
|
export default sceneSlice.reducer;
|
|
@ -1,5 +1,7 @@
|
||||||
|
import { SceneStore } from "./scene/reducer";
|
||||||
import UIStore from "./ui/state";
|
import UIStore from "./ui/state";
|
||||||
|
|
||||||
export interface GameStore {
|
export interface GameStore {
|
||||||
ui: UIStore;
|
ui: UIStore;
|
||||||
|
scene: SceneStore;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
|
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
|
||||||
import { UILayer } from "~ui/UI";
|
import UIStore, { UILayer } from "./state";
|
||||||
import UIStore from "./state";
|
|
||||||
|
|
||||||
const initialState: UIStore = {
|
const initialState: UIStore = {
|
||||||
layers: [],
|
layers: [],
|
||||||
|
@ -38,7 +37,8 @@ const uiSlice = createSlice({
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
state.layers[index].visible = true;
|
|
||||||
|
state.layers[index] = { ...state.layers[index], visible: true };
|
||||||
},
|
},
|
||||||
hideLayer(state, action: PayloadAction<LayerActionPayload>) {
|
hideLayer(state, action: PayloadAction<LayerActionPayload>) {
|
||||||
const index = state.layers.findIndex(
|
const index = state.layers.findIndex(
|
||||||
|
@ -47,7 +47,7 @@ const uiSlice = createSlice({
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
state.layers[index].visible = false;
|
state.layers[index] = { ...state.layers[index], visible: false };
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
import { LayerList } from "~ui/UI";
|
import { MapEditorLayer } from "~ui/MapEditor";
|
||||||
|
|
||||||
|
export type UILayer = MapEditorLayer;
|
||||||
|
|
||||||
|
export type LayerList = { id: string; data: UILayer; visible: boolean }[];
|
||||||
|
|
||||||
export default interface UIStore {
|
export default interface UIStore {
|
||||||
layers: LayerList;
|
layers: LayerList;
|
||||||
|
|
|
@ -4,7 +4,7 @@ export interface MapEditorLayer {
|
||||||
type: "MapEditor";
|
type: "MapEditor";
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function MapEditor() {
|
export default function MapEditorUI() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<p>HEY HEY</p>
|
<p>HEY HEY</p>
|
||||||
|
|
|
@ -1,16 +1,13 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useSelector } from "react-redux";
|
import { useSelector } from "react-redux";
|
||||||
import { GameStore } from "~store/state";
|
import { GameStore } from "~store/state";
|
||||||
import MapEditor, { MapEditorLayer } from "./MapEditor";
|
import { UILayer, LayerList } from "~store/ui/state";
|
||||||
|
import MapEditorUI from "./MapEditor";
|
||||||
export type UILayer = MapEditorLayer;
|
|
||||||
|
|
||||||
export type LayerList = { id: string; data: UILayer; visible: boolean }[];
|
|
||||||
|
|
||||||
function renderLayer(data: UILayer) {
|
function renderLayer(data: UILayer) {
|
||||||
switch (data.type) {
|
switch (data.type) {
|
||||||
case "MapEditor":
|
case "MapEditor":
|
||||||
return <MapEditor />;
|
return <MapEditorUI />;
|
||||||
default:
|
default:
|
||||||
throw new Error("unknown or invalid ui layer");
|
throw new Error("unknown or invalid ui layer");
|
||||||
}
|
}
|
||||||
|
@ -20,8 +17,10 @@ export default function UI() {
|
||||||
const layers = useSelector<GameStore, LayerList>((state) => state.ui.layers);
|
const layers = useSelector<GameStore, LayerList>((state) => state.ui.layers);
|
||||||
return (
|
return (
|
||||||
<div id="ui">
|
<div id="ui">
|
||||||
{layers.map(({ id, data }) => (
|
{layers.map(({ id, data, visible }) => (
|
||||||
<div key={id}>{renderLayer(data)}</div>
|
<div key={id} style={{ display: visible ? "" : "none" }}>
|
||||||
|
{renderLayer(data)}
|
||||||
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useDispatch } from "react-redux";
|
import { useDispatch } from "react-redux";
|
||||||
import { UILayer } from "~ui/UI";
|
|
||||||
import { addLayer, removeLayer, showLayer, hideLayer } from "~store/ui/reducer";
|
import { addLayer, removeLayer, showLayer, hideLayer } from "~store/ui/reducer";
|
||||||
|
import { UILayer } from "~store/ui/state";
|
||||||
|
|
||||||
export default function useUILayer(data: UILayer, show: boolean) {
|
export default function useUILayer(data: UILayer, show: boolean) {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const id = data.type + "-" + Math.random().toString(32).slice(2);
|
|
||||||
|
|
||||||
|
const [id] = useState(data.type + "-" + Math.random().toString(32).slice(2));
|
||||||
const [visible, setVisible] = useState(show);
|
const [visible, setVisible] = useState(show);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
Reference in a new issue