import Serpentity from '@serpentity/serpentity'; /* global window document */ const internals = { kNoElementError: 'No element found. Cannot render.', // Handler for the window load event. Initializes and runs the app. onLoad() { const sumo = new internals.Sumo({ element: document.getElementById('sumo-app-entry-point') }); sumo.startLoop(); internals.exports.sumo = sumo; } }; /** * Sumo - main entry point. Attached to window->load * * @class Sumo * * @param {object} config the configuration to extend the object * * @property {HTMLElement} [element=null] the element in which to render. * Required, will throw if not provided * @property {Number} [fps=60] the fps target to maintain * @property {Number} [verticalResolution=224] how many pixels to render in the vertical * axis (gets scaled if the canvas is larger) * @property {Array} [aspectRatio=[2.76, 1]] the aspect ratio experssed as * an array of two numbers, where aspect ratio x:y is [x, y] (eg. [16, 9]) */ internals.Sumo = class Sumo { constructor(config) { this.fps = 60; this.aspectRatio = [2.76, 1]; this.verticalResolution = 224; Object.assign(this, config); if (!this.element) { throw new Error(internals.kNoElementError); } this._engine = new Serpentity(); this._previousTime = 0; this._looping = false; // Initialization functions this._initializeCanvas(); this._initializeSystems(); this._initializeEntities(); } /** * Starts the main loop. Resets the FPS (if you change it it won't go * live until after you stop and start the loop) * * @function startLoop * @instance * @memberof Sumo */ startLoop() { this._looping = true; this._frameDuration = 1000 / this.fps; window.requestAnimationFrame(this._loop.bind(this)); } /** * Pauses the loop * * @function pauseLoop * @instance * @memberof Sumo */ pauseLoop() { this._looping = false; } // The main loop used above. Runs the serpentity update process and // attempts to maintain FPS. The rest is handled by the engine. _loop(currentTime) { if (!this._looping) { return; } window.requestAnimationFrame(this._loop.bind(this)); const currentFrameDuration = currentTime - this._previousTime; if (currentFrameDuration > this._frameDuration) { // We're sending the currentTime since it gives better results for // this type of renderer, though usually we expect the delta this._engine.update(currentTime); this._previousTime = currentTime; } } // Creates a canvas for rendering _initializeCanvas() { this._canvas = document.createElement('canvas'); this.element.appendChild(this._canvas); this._resizeCanvas(); window.addEventListener('resize', this._resizeCanvas.bind(this)); } // Resizes the canvas to a square the size of the smallest magnitude // of the window. _resizeCanvas() { let width = window.innerWidth; let height = Math.round(width * this.aspectRatio[1] / this.aspectRatio[0]); if (window.innerHeight < height) { height = window.innerHeight; width = Math.round(height * this.aspectRatio[0] / this.aspectRatio[1]); } this._canvas.style.width = `${width}px`; this._canvas.style.height = `${height}px`; this._canvas.width = Math.round(this.verticalResolution * this.aspectRatio[0] / this.aspectRatio[1]); this._canvas.height = this.verticalResolution; } // Initializes the serpentity systems _initializeSystems() { } // Initializes the serpentity entities _initializeEntities() { } }; export default internals.exports = {}; // autorun.bat window.addEventListener('load', internals.onLoad);