import { Font2D } from '../font/2d'; import { Font3D } from '../font/3d'; import { InputManager } from '../input'; import { Renderer } from '../renderer'; import { ShaderProgram } from '../shader/program'; import { State2D } from '../state/2d'; import { State3D } from '../state/3d'; import { System2D } from '../system/2d'; import { System3D } from '../system/3d'; import { UI2D } from '../ui/2d'; import { UI3D } from '../ui/3d'; import { World2D } from '../world/2d'; import { World3D } from '../world/3d'; import { GameConfig, GameConfigDefaults } from './game.config'; /** * Generic abstract Game object, setting out the fundamental properties and runtime behaviour of all Aura Games, and broken down into * concrete 2D and 3D variants in Game2D and Game3D * * Implements only the abstractable aspects of both flavours of Game, and enforces the implementation of 2D and 3D specific members and * behaviour for subclasses, providing type-safety where appropriate or desired throughout the system for 2D and 3D Game creation * * Games may be instantiated with or without configuration objects to tweak their behaviour and initial state * * Game execution begins when *start()* is called upon a Game instance */ export declare abstract class Game { /** Abstract 2D or 3D World, to be implemented and the type to be narrowed by the subclass */ abstract readonly world: World2D | World3D; /** Abstract 2D or 3D Font, to be implemented and the type to be narrowed by the subclass */ abstract readonly font: Font2D | Font3D; /** Abstract 2D or 3D UI, to be implemented and the type to be narrowed by the subclass */ abstract readonly ui: UI2D | UI3D; /** InputManager */ readonly input: InputManager; /** Renderer */ readonly renderer: Renderer; /** HTML Canvas */ canvas: HTMLCanvasElement | undefined; /** Abstract mapping of 2D or 3D States, to be implemented and managed and the type to be narrowed by the subclass */ protected abstract readonly states: Map; /** Abstract reference to the current State, to be implemented and managed and the type to be narrowed by the subclass */ protected abstract currentState: State2D | State3D | undefined; /** Abstract mapping of 2D or 3D Systems, to be implemented and managed and the type to be narrowed by the subclass */ protected abstract readonly systems: Map; /** Frame time step, calculated during run() */ protected frameDelta: number; /** Time of the last frame, set during run() */ protected lastFrameTime: number; /** Generic mapping of Game Data, useful for storing and retrieving arbitrary global data at Game runtime */ protected readonly data: Map; /** Debug Mode, as potentially set by the GameConfig */ protected debugMode: GameConfig['debugMode']; /** Internal-use DebugData for tracking certain game statistics while in Debug Mode */ protected readonly debugData: { frameCount: number; fps: string; }; /** * Default GameConfig fallback values for various configuration options */ protected readonly defaults: GameConfigDefaults; /** * Reference to the potential GameConfig init() method */ protected init: GameConfig['init']; /** * Flag for whether or not the Game is stopped and therefore should not request any animation frames */ private stopped; /** * Constructor. Take an optional GameConfig, and initialise all generic/abstractable aspects of the Game * * @param config the optional GameConfig */ constructor(config?: GameConfig); /** * Abstract single State addition routine, to be implemented by the subclass * * By not implementing generically, ensures for example that a Game2D may only be configured with 2D States * * @param state the State2D or State3D to add; the type will be narrowed by the subclass */ abstract addState(state: State2D | State3D): void; /** * Abstract multi State addition routine, to be implemented by the subclass * * By not implementing generically, ensures for example that a Game2D may only be configured with 2D States * * @param states the list of State2Ds or State3Ds to add; the type will be narrowed by the subclass */ abstract addStates(...states: Array): void; /** * Abstract State init routine, to be implemented by the subclass * * By not implementing generically, ensures for example that a State2D's lifecycle methods will receive a type-correct Game2D */ abstract initState(): void; /** * Abstract State end routine, to be implemented by the subclass * * By not implementing generically, ensures for example that a State2D's lifecycle methods will receive a type-correct Game2D */ abstract endState(): void; /** * Switch to the State given by name * * Calls the State lifecycle method *end()* on the current State, then calls the lifecycle method *init()* on the new State * * Throws an error if the desired State is not found for runtime safety * * @param name the name of the State to switch to */ switchToState(name: string): void; /** * Abstract single System addition routine, to be implemented by the subclass * * By not implementing generically, ensures for example that a Game2D may only be configured with 2D Systems * * @param system the System2D or System3D to add; the type will be narrowed by the subclass */ abstract addSystem(system: System2D | System3D): void; /** * Abstract multi System addition routine, to be implemented by the subclass * * By not implementing generically, ensures for example that a Game2D may only be configured with 2D Systems * * @param systems the list of System2Ds or System3Ds to add; the type will be narrowed by the subclass */ abstract addSystems(...systems: Array): void; /** * Remove a single System by name * * @param name the name of the System to remove */ removeSystem(name: string): void; /** * Remvove a list of Systems by name * * @param names the names of the Systems to remove */ removeSystems(...names: Array): void; /** * Set the value of some arbitrary generic Game Data * * @param key the key for the Data * @param value the value for the Data */ setData(key: string, value: T): void; /** * Retrieve the value of some arbitrary generic Game Data by name * * Type param is for consumer convenience and relative type safety * * Throws an error if the data is not retrievable by the key to avoid runtime issues * * @param key the key of the Data to retrieve * * @typeparam T the type of the Data being retrieved * * @returns the retrieved Data */ getData(key: string): T; /** * Delete some arbitrary generic Game Data by name * * @param key the name of the Data to delete */ deleteData(key: string): void; /** * Create a given ShaderProgram so as to make it available for use in Entity Shader Components * * All ShaderPrograms to be used by the application should be registered *before* execution is begun with *start()* * * @param shader the ShaderProgram to register */ registerShader(shader: ShaderProgram): void; /** * Begin game executon by first calling the optional init() provided in the GameConfig, and then switching to the named State * * @param state the name of the State to start with */ start(state: string): void; /** * End game execution by setting the stopped flag, signalling to other constructs to tear down, and then dereferencing things * * // TODO first-working-version; needs improvement (see TODO/general) */ destroy(): void; /** * Abstract frame update routine, to be implemented by the subclass and intended to be used for updating the concrete Game's Systems and * current State * * By not implementing generically, ensures for example that a State2D or System2D's tick() lifecycle method will receive a * type-correct Game2D */ protected abstract update(): void; /** * Main game execution routine, representing the production of a single frame * * Performs the following actions in order: * - calculates the frame delta * - executes the abstract update(), triggering the update of all Systems and the current State * - executes the World update() * - executes the UI update() * - executed the Font update() * - clears the screen * - renders the World * - renders the UI * - renders the Font * - handles debugData if appropriate */ private run; }