import App from "./app.js"; import SpriteRegistry from "./registry/sprite_registry.js"; import ControllerRegistry from "./registry/controller_registry.js"; import Vec2 from "./game/vector/vec2.js"; import SoundRegistry from "./registry/sound/sound_registry.js"; import SpaceManager from "./game/space/space_manager.js"; import TaskManager from "./util/task/task_manager.js"; import InputManager from "./input/input_manager.js"; import CookieManager from "./util/data/cookie_manager.js"; import PrefabRegistry from "./registry/prefab_registry.js"; /** * @module Engine * @fileoverview Contains Engine class. */ /** * @class * Global root object for the entire engine. */ class Engine { /** * Create a new Engine. * @constructor */ constructor() { this._loadCounter = 0; this._canvasID = ""; this._onLoadFunction = () => {}; /** App for holding game data */ this._app = null; /** Registry holder */ this._reg = { sprites: new SpriteRegistry(), sound: new SoundRegistry(), controller: new ControllerRegistry(), prefab: new PrefabRegistry() }; /** Global cookie manager */ this._cookies = new CookieManager(); /** Global task manager */ this._tasks = new TaskManager(); /** Global space manager */ this._spaces = new SpaceManager(); /** Global input manager */ this._input = new InputManager(); this._offscreenCanvas = new OffscreenCanvas(1024, 1024); this._offscreenContext = this._offscreenCanvas.getContext("2d"); this._offscreenContext.willReadFrequently = true; /** Width of the canvas being used. */ this.width = 0; /** Height of the canvas being used. */ this.height = 0; /** The current mouse position relative to the canvas. */ this.mousePos = new Vec2(0, 0); /** Fonts to be used throughout the engine in drawing on the canvas. */ this.fonts = { debug: "roboto" }; /** Colors to be used throughout the engine. */ this.colors = { debug: "rgb(255,92,75)", debug2: "rgb(243,198,71)", debug_collision: "rgb(130,234,167)", debug_body: "rgb(80,147,241)", debug_body_connection: "rgb(234,97,149)", debug_physics: "rgb(143,229,56)", debug_path: "rgb(255,118,171)", debug_path2: "rgba(255,118,171,0.69)", debug_path_complete: "rgba(162,135,149,0.54)" }; /** Global flags. */ this.flags = { chunks: { cache: true }, timeScale: 1, pauseOnBlur: true, fillScreen: true }; /** Global debugging flags. Can be enabled to display debugging information. */ this.debug = { actors: false, chunks: false, particles: false, physics: false, enableAll: function() { this.actors = true; this.chunks = true; this.particles = true; this.physics = true; }, disableAll: function() { this.actors = false; this.chunks = false; this.particles = false; this.physics = false; }, toggleAll: function() { let which = true; if (this.actors) which = false; if (this.chunks) which = false; if (this.particles) which = false; if (this.physics) which = false; if (which) this.enableAll(); else this.disableAll(); } }; } // // Initialization and Loading // /** * Initialize the engine. * @param {string} canvasID The ID of the canvas to draw on * @param {function} onload Function to call once all assets are loaded * @param {function} preload Function for loading assets */ init(canvasID, onload = () => {}, preload = () => {}) { this._onLoadFunction = onload; this._canvasID = canvasID; preload(); this._checkReady(); } /** * Increment the amount of assets loading. */ loadInc() { this._loadCounter++; } /** * Decrement the amount of assets loading, and start the * application if it reaches 0. */ loadDec() { this._loadCounter--; this._checkReady(); } /** * Try to start the engine if all assets are loaded. * @private */ _checkReady() { if (this._loadCounter === 0) { this._app = new App(this._canvasID, true); this._app.start(); this._onLoadFunction(this._app); } } // // Getters // /** * Get the root application. * @returns {App} Root application */ get app() { return this._app; } /** * Get the registries for holding assets and more. * @returns {{controller: ControllerRegistry, sound: SoundRegistry, sprites: SpriteRegistry, prefab: PrefabRegistry}} Global registries */ get reg() { return this._reg; } /** * Get the global cookie manager. * @returns {CookieManager} Global cookie manager */ get cookies() { return this._cookies; } /** * Get the global task manager. * @returns {TaskManager} Global task manager */ get tasks() { return this._tasks; } /** * Get the global space manager. * @returns {SpaceManager} Global space manager */ get spaces() { return this._spaces; } /** * Get the global input handler. * @returns {InputManager} Global input handler */ get input() { return this._input; } // // Miscellaneous // /** * Generate an image using a custom function on an offscreen canvas. * @param {function} func Function to run (passes in context) * @param {function} onDone Function to run when complete (passes in image) * @param {number} width Width of image (starts at x = 0) * @param {number} height Height of image (starts at y = 0) */ createImage(func = ctx => {}, onDone = image => {}, width, height) { this._offscreenContext.clearRect(0, 0, this._offscreenCanvas.width, this._offscreenCanvas.height); this._offscreenCanvas.width = width; this._offscreenCanvas.height = height; func(this._offscreenContext); this._offscreenCanvas.convertToBlob() .then(blob => createImageBitmap(blob)) .then(image => onDone(image)); } /** * Generate image data using a custom function on an offscreen canvas. * @param {function} func Function to run (passes in context) * @param {number} width Width of data (starts at x = 0) * @param {number} height Height of data (starts at y = 0) * @returns {ImageData} Generated image data */ createImageData(func = ctx => {}, width, height) { this._offscreenContext.clearRect(0, 0, this._offscreenCanvas.width, this._offscreenCanvas.height); this._offscreenCanvas.width = width; this._offscreenCanvas.height = height; func(this._offscreenContext); return this._offscreenContext.getImageData(0, 0, width, height); } } window.$$ = new Engine();