evidently-pixi
Version:
TypeScript powered set of modules to make it easier to make games in Pixi.js.
187 lines • 8.04 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const PIXI = require("pixi.js");
const AssetLoader_1 = require("../Various/AssetLoader");
const TextureStore_1 = require("../Various/TextureStore");
const SceneManager_1 = require("../Managers/SceneManager");
const PostProcessEffects_1 = require("../Managers/PostProcessEffects");
const GameStage_1 = require("../Stages/GameStage");
const KeyboardInput_1 = require("evidently-input/dist/KeyboardInput");
const MouseInput_1 = require("evidently-input/dist/MouseInput");
/**
* The bootstrap and entrypoint for a PIXI game. It does the following things in order:
* 1. Creates a Pixi instance inside the element specified in `config.gameContainerId`.
* 2. Register mouse and keyboard listeners to grab input.
* 3. Setups loading screen.
* 4. Calls a custom callback to allow you to queue all the assets you need for loading.
* 5. Loads all the queued assets.
* 6. Removes loading screen.
* 7. Initializes the first scene (like a screen of your game: main menu, game itself, game over, leaderboards, etc)
* 8. Connects to the ticker that updates the active scene.
* 9. Adds all other necessary listeners - changing game dimensions, updating input etc.
*
* ### Example configuration
*
* ```
* const game = new Game({
* // `document` and `window` are required to be passed to the configuration
* document,
* window,
*
* // ID of the element where the PIXI's canvas should be added
* gameContainerId: 'game',
*
* // optional PIXI configuration, at the very least you want to provide width and height
* pixiConfig: {
* width: 640,
* height: 360,
* backgroundColor: 0,
* antialias: false,
* },
*
* // Creates and configures a stage which scales the game pixel-perfect, snapping to full integers of scale,
* // ie. x1, x2, x3, for a crisp pixel look. It also handles all of the magic required for Pixi's
* // interactions to work and for `MouseInput` library to report proper position
* stageFactory: (game: Game) => new ScalingStage(
* game,
* 640,
* 360,
* PIXI.SCALE_MODES.NEAREST,
* Config.ScalingStageUpscaleMode,
* ),
*
* // Queue some assets to be loaded
* onQueueAssets: (game: Game): void {
* game.assetLoader.queuePixiAutoFont('topaz_0.png', FontTopaz8Image);
* game.assetLoader.queuePixiAutoFont('font-topaz', FontTopaz8);
* game.assetLoader.queueTexture(GfxConstants.InitialTileset, InitialTileset);
* game.assetLoader.queueTileset(GfxConstants.InitialTileset, {
* tileWidth: 16,
* tileHeight: 16,
* offsetX: 0,
* offsetY: 0,
* spacingX: 0,
* spacingY: 0,
* })
* },
*
* // Callback to create the starting scene
* initialSceneFactory: (game) => new IntroScene(game),
*
* // Called once everything has finished initializing
* onStartGame: () => {
* console.log("Game started");
* },
* );
*
* // Actually starts the initialization of the game
* game.start();
* ```
*/
class Game {
constructor(config) {
if (config.pixiConfig.sharedTicker === undefined) {
config.pixiConfig.sharedTicker = true;
}
this._config = config;
this.pixi = new PIXI.Application(config.pixiConfig);
this.document = config.document;
this.keyboard = new KeyboardInput_1.KeyboardInput();
this.mouse = new MouseInput_1.MouseInput();
this.gameStage = config.stageFactory(this);
this.textureStore = new TextureStore_1.TextureStore();
this.assetLoader = new AssetLoader_1.AssetLoader({ textureStore: this.textureStore });
this.sceneManager = new SceneManager_1.SceneManager();
this.postProcessManager = new PostProcessEffects_1.PostProcessEffects();
const gameElement = config.document.getElementById(config.gameContainerId);
if (!gameElement) {
throw new Error(`Failed to find element '${config.gameContainerId}'`);
}
gameElement.appendChild(this.pixi.view);
this.keyboard.registerListeners(this.document);
this.mouse.registerListeners(this.document);
}
/**
* Initializes and runs the game.
*/
start() {
Promise.resolve()
.then(() => (this._config.onSetupLoadingScreen || this.setupDefaultLoadingScreen).call(this, this))
.then(() => this._config.onQueueAssets(this))
.then(() => this.loadAssets())
.then(() => (this._config.onRemoveLoadingScreen || this.removeDefaultLoadingScreen).call(this, this))
.then(() => this.initializeScene())
.then(() => this.finalSetup(this))
.then(() => { var _a; return (_a = this._config) === null || _a === void 0 ? void 0 : _a.onStartGame(this); });
}
/**
* Cretes a new PIXI.Sprite on the specified layer. This new sprite will be attached to the
* [[GameStage]], and can be used to actually display something on the screen.
* See [[GameStageLayer]] for more information about the types of layers.
* @param {GameStageLayer} layer Layer on which to create the container.
* @return {PIXI.Sprite} The sprite created and attached to stage.
*/
createContainer(layer = GameStage_1.GameStageLayer.Normal) {
const sprite = new PIXI.Sprite();
this.gameStage.addChild(sprite, layer);
return sprite;
}
/**
* Removes a container previously created by the call to `createContainer` from the stage. Use
* it when it's no longer in use, typicall when switching from a [[Scene]].
* @param {PIXI.Sprite} container The contianer to remove
*/
removeContainer(container) {
this.gameStage.removeChild(container);
}
update() {
const delta = this.pixi.ticker.elapsedMS;
this.sceneManager.update(delta);
this.postProcessManager.update(delta);
this.gameStage.update(delta);
this.mouse.update();
this.keyboard.update();
}
setupDefaultLoadingScreen(game) {
const div = game.document.createElement('div');
div.id = "__default-loading-div";
div.style.position = "fixed";
div.style.left = "0";
div.style.right = "0";
div.style.top = "0";
div.style.bottom = "0";
div.style.background = "#444";
div.style.color = "white";
div.style.fontSize = "80px";
div.style.display = "flex";
div.style.justifyContent = "center";
div.style.alignContent = "center";
div.style.alignItems = "center";
div.textContent = "Loading";
this.document.getElementsByTagName('body')[0].appendChild(div);
}
removeDefaultLoadingScreen() {
var _a, _b;
const loadingDiv = this.document.getElementById('__default-loading-div');
(_b = (_a = loadingDiv) === null || _a === void 0 ? void 0 : _a.parentNode) === null || _b === void 0 ? void 0 : _b.removeChild(loadingDiv);
}
loadAssets() {
return this.assetLoader.load(this.pixi.loader);
}
initializeScene() {
this.sceneManager.changeScene(this._config.initialSceneFactory(this));
}
finalSetup(game) {
game._config.window.onresize = () => {
game.onWindowResize(game, game._config.window.innerWidth, game._config.window.innerHeight);
};
game.pixi.ticker.add(() => game.update());
game.onWindowResize(game, game._config.window.innerWidth, game._config.window.innerHeight);
}
onWindowResize(game, width, height) {
game.pixi.renderer.resize(width, height);
game.gameStage.setWindowDimensions(width, height);
}
}
exports.Game = Game;
//# sourceMappingURL=Game.js.map