DHO4JCJIELKX4R42XXAMAHVQTTE6OWULLP2QF4BXO3UWC5UTMSMAC WTINQMZSNRT5MSAXLMMZVM6OU6TMD4AP4OEUYAXZUFNY5IWFLZSQC 2ZSVFRN4O7L6ARZNYSEIVECQTTSNPTHVMJU7TQDMEIYHOV36OG2QC 4CBMJ7C2376HBVEBEHGJGR3YZJSCHDVAD4Q6AEGBAZZFLLKD52SAC TQ57VE45BHV7MOZ6GKTYZEAMAOTXLPQ3ROCWJ2FUCITQWOYVMUIAC ZGS4FTTFBXTF2SHYTPAJJBWEUVWVYXPSJVEFI5NYJWTW273B4NHAC WO2ALETBVNH7N3NXJ6JKWCQ2YIZN6LBO7WEXPHAT3EQQJEUCJITQC 3EAR4KTTJ26IRF5QUGEDRMJVBR4X3VWSQ6OBIJCLDH3A4ZZ4O3ZAC ZHOSSPNKGFIKSFPDXCGLMSYMMX2J433VU2BUUWBKUH7TOLQUBSPQC // public async getAsync(): Promise<T> {// if (this._value !== undefined || this._wasConstructed === true) {// return Promise.resolve(this._value!);// } else {// return new Promise<T>((resolve, reject) => {// this._value = this._factory();// this._wasConstructed = true;// resolve(this._value);// });// }// }
// root containerpublic stage!: Pixi.Container;// Contains HUD, and other entities that don't move when game camera movespublic fixedCameraStage!: Pixi.Container;// Contains game entities that move when game camera pans/zooms. Highly encouraged to have further subdivions.public actionStage!: Pixi.Container;// Contains a few entities that doesn't move when game camera moves, but located behind action stage entities, e.g. static backgroundspublic backdropStage!: Pixi.Container;
export type BaseApplicationProps = DeepReadonly<{gameState: GameState,windowSize: Vector2,}>
constructor(config?: Partial<Config>) {assertOnlyCalledOnce("Application constructor");this.config = Object.assign({}, defaultConfig, config);
constructor(args: Partial<Config> = {}, props: BaseApplicationProps) {assertOnlyCalledOnce("Base application constructor");this.config = Object.assign({}, defaultConfig, args);
const appSize = BaseApplication.appSizeFromWindowSize(new Vector2(this.config.originalWindowWidth, this.config.originalWindowHeight));this.originalAppWidth = appSize.x;this.originalAppHeight = appSize.y;
this.state.appSize = BaseApplication.appSizeFromWindowSize(props.windowSize);this.originalAppWidth = this.state.appSize.x;this.originalAppHeight = this.state.appSize.y;
this.stage = this.app.stage;this.stage.sortableChildren = true;this.fixedCameraStage = new Pixi.Sprite();this.fixedCameraStage.zIndex = 1;this.fixedCameraStage.sortableChildren = true;this.stage.addChild(this.fixedCameraStage);this.actionStage = new Pixi.Sprite();this.actionStage.zIndex = 0;this.actionStage.sortableChildren = true;this.stage.addChild(this.actionStage);this.backdropStage = new Pixi.Sprite();this.backdropStage.zIndex = -1;this.backdropStage.sortableChildren = true;this.stage.addChild(this.backdropStage);this.keyboard = new KeyboardState();this.app.ticker.add(() => {this.keyboard.update();})this.fpsTracker = new FpsTracker();this.app.ticker.add((delta) => {// delta should be approximately equal to 1this.fpsTracker.tick(delta);})let pointNodeTexture = generatePointNodeTexture(this.app.renderer);
public rerender(props: {gameState: DeepReadonly<GameState>,pixiComponentState: PixiComponentState,}) {
updateState(delta: number, props: BaseApplicationProps) {this.state.appSize = BaseApplication.appSizeFromWindowSize(props.windowSize);}render(delta: number, props: BaseApplicationProps) {this.app.renderer.resize(this.state.appSize.x, this.state.appSize.y);}baseGameLoop(delta: number) {
* this.queuedEvents // used for onEvent listeners, to delay action until the next tick
* this.queuedEvents // used for onEvent listeners, to delay action until the next tick; perhaps this should interact with the global event queue?* globalEventQueue.push(eventAction: (delta, prevProps, prevState, updaters) => void)and then in the root component, every tick:globalEventQueue.map((eventAction) => eventAction(
* update(delta, props, updaters) { // edits this.state and sends parent state updates upwards. typically looks like:
* updateState(delta, props) { // component is given new props which should be stored; also edits this.state . typically looks like:
* TL;DR the flow is:* constructor, initialize state based on const args and initial props* immediately after the constructor, first render again with initial props* onX => enqueues event actions onto global event queue; event actions can modify state and parent state* ticker tick goes off* in root component, global event queue fires off callbacks, editing state everywhere* shouldUpdateState fires recursively, conditioning:* updateState fires recursively, causing state updates to flow down as props to children // should prevState/prevProps be kept here and in the previous method??* shouldRender fires recursively, conditioning:* render fires recursively, redrawing everything based on props & state. if new children are constructed, they get constructed, rendered, and then the parent continues its own rendering.* componentDidMount for newly created components. actions here are put onto global event queue and delayed until next tick.* componentDidUpdate fires recursively, all actions here are put onto global event queue and delayed until next tick* componentDidUnmount ??
import * as Pixi from "pixi.js";import { KeyboardState } from "../lib/pixi/keyboard";import { FpsTracker } from "../lib/util/fpsTracker";import { registerDraggable } from "../lib/pixi/DraggableHelper";import createBunnyExample from "./BunnyExample";import { Chunk, RenderedChunk } from "./Chunk";import { Vector2 } from "../lib/util/geometry/vector2";import { ZLevel } from "./ZLevel";import { RenderedZLevel } from "./RenderedZLevel";import { HashMap } from "../lib/util/data_structures/hash";import { GameState, PointNodeRef } from "../data/GameState";import { generatePointNodeTexture } from "./textures/PointNodeTexture";import { Reticle } from "./Reticle";import { ZLevelGenFactory } from "../dataFactory/WorldGenStateFactory";import { assertOnlyCalledOnce, DeepReadonly, Lazy } from "../lib/util/misc";type RootApplicationState = {}type RootApplicationProps = {}export class RootApplication {state!: RootApplicationState;props!: DeepReadonly<RootApplicationProps>;/* children */// Contains HUD, and other entities that don't move when game camera movespublic fixedCameraStage!: Pixi.Container;// Contains game entities that move when game camera pans/zooms. Highly encouraged to have further subdivions.public actionStage!: Pixi.Container;// Contains a few entities that doesn't move when game camera moves, but located behind action stage entities, e.g. static backgroundspublic backdropStage!: Pixi.Container;public keyboard!: KeyboardState;public fpsTracker!: FpsTracker;public static appSizeFromWindowSize(window: Vector2): Vector2 {return new Vector2({x: Math.min(1280, window.x),y: Math.min(720, window.y),});}/*** Need to provide config to set up the pixi canvas*/constructor(config?: Partial<Config>) {assertOnlyCalledOnce("Base application constructor");this.config = Object.assign({}, defaultConfig, config);const appSize = BaseApplication.appSizeFromWindowSize(new Vector2(this.config.originalWindowWidth, this.config.originalWindowHeight));this.originalAppWidth = appSize.x;this.originalAppHeight = appSize.y;this.app = new Pixi.Application({width: this.originalAppWidth, // both are ignored - see resize() belowheight: this.originalAppHeight,antialias: true, // both about the same FPS, i get around 30 fps on 1600 x 900transparent: true, // true -> better fps?? https://github.com/pixijs/pixi.js/issues/5580resolution: window.devicePixelRatio || 1, // lower -> more FPS but uglier// resolution: 0.5,// resolution: 2,autoDensity: true,powerPreference: "low-power", // the only valid one for webglbackgroundColor: 0xffffff, // immaterial - we recommend setting color in backdrop graphics});this.stage = this.app.stage;this.stage.sortableChildren = true;// this.fixedCameraStage = new Pixi.Sprite();// this.fixedCameraStage.zIndex = 1;// this.fixedCameraStage.sortableChildren = true;// this.stage.addChild(this.fixedCameraStage);// this.actionStage = new Pixi.Sprite();// this.actionStage.zIndex = 0;// this.actionStage.sortableChildren = true;// this.stage.addChild(this.actionStage);// this.backdropStage = new Pixi.Sprite();// this.backdropStage.zIndex = -1;// this.backdropStage.sortableChildren = true;// this.stage.addChild(this.backdropStage);// this.keyboard = new KeyboardState();// this.app.ticker.add(() => {// this.keyboard.update();// })// this.fpsTracker = new FpsTracker();// this.app.ticker.add((delta) => {// // delta should be approximately equal to 1// this.fpsTracker.tick(delta);// })let pointNodeTexture = new Lazy(() => generatePointNodeTexture(this.app.renderer));// test// createBunnyExample({ parent: this.actionStage, ticker: this.app.ticker, x: this.app.screen.width / 2, y: this.app.screen.height / 2 });this.app.ticker.add((delta) => this.baseGameLoop(delta));}/*** Please only call once!!* Usage: const container = useRef<HTMLDivElement>(null); useEffect(() => { application.register(container.current!); }, []);*/public register(curr: HTMLDivElement) {curr.appendChild(this.app.view);}// render(props: {// gameState: DeepReadonly<GameState>,// pixiComponentState: PixiComponentState,// }) { }baseGameLoop(delta: number) {}}