UNPKG

splat-ecs

Version:
138 lines (124 loc) 4.14 kB
var clone = require("./clone"); var components = require("./components"); var ECS = require("entity-component-system").EntityComponentSystem; var EntityPool = require("entity-component-system").EntityPool; var registerComponents = require("./components/register"); function Scene(name, globals) { this.data = {}; this.entities = new EntityPool(); this.globals = globals; this.name = name; this.onEnter = function() {}; this.onExit = function() {}; this.renderer = new ECS(); this.state = "stopped"; this.speed = 1.0; this.simulation = new ECS(); this.simulationStepTime = 5; this.firstTime = true; this.accumTime = 0; this.sceneConfig = globals.require("./data/scenes")[name]; if (typeof this.sceneConfig.onEnter === "string") { this.onEnter = globals.require(this.sceneConfig.onEnter); } if (typeof this.sceneConfig.onExit === "string") { this.onExit = globals.require(this.sceneConfig.onExit); } } Scene.prototype.start = function(sceneArgs) { if (this.state !== "stopped") { return; } this.state = "starting"; this.tempArguments = sceneArgs; }; Scene.prototype._initialize = function() { this.entities = new EntityPool(); this.firstTime = true; this.accumTime = 0; this.data = { animations: this.globals.animations, arguments: this.tempArguments || {}, canvas: this.globals.canvas, context: this.globals.context, entities: this.entities, images: this.globals.images, inputs: this.globals.inputs, prefabs: this.globals.prefabs, require: this.globals.require, scaleCanvasToCssSize: this.globals.scaleCanvasToCssSize, scaleCanvasToFitRectangle: this.globals.scaleCanvasToFitRectangle, sceneConfig: this.sceneConfig, scenes: this.globals.scenes, sounds: this.globals.sounds, switchScene: this.switchScene.bind(this) }; this.simulation = new ECS(); this.renderer = new ECS(); this.simulation.add(function processInputUpdates() { this.globals.inputs.processUpdates(); }.bind(this)); var systems = this.globals.require("./data/systems"); this.installSystems(systems.simulation, this.simulation, this.data); this.installSystems(systems.renderer, this.renderer, this.data); registerComponents(this.entities, components); registerComponents(this.entities, this.globals.require("./data/components")); var entities = this.globals.require("./data/entities"); this.entities.load(clone(entities[this.name]) || []); this.onEnter(this.data); }; Scene.prototype.stop = function() { if (this.state === "stopped") { return; } this.state = "stopped"; this.onExit(this.data); }; Scene.prototype.switchScene = function(scene, sceneArgs) { this.stop(); this.data.scenes[scene].start(sceneArgs); }; Scene.prototype.installSystems = function(systems, ecs, data) { for (var i = 0; i < systems.length; i++) { var system = systems[i]; if (system.scenes.indexOf(this.name) === -1 && system.scenes !== "all") { continue; } var script = this.globals.require(system.name); if (script === undefined) { console.error("failed to load script", system.name); } script(ecs, data); } }; Scene.prototype.simulate = function(elapsed) { if (this.state === "stopped") { return; } if (this.state === "starting") { var start = window.performance.now(); this._initialize(); var end = window.performance.now(); this.accumTime = start - end; // negative so a long initialize doesn't make the first few frames slow this.state = "started"; } if (this.firstTime) { this.firstTime = false; // run simulation the first time, because not enough time will have elapsed this.simulation.run(this.entities, 0); elapsed = 0; } elapsed *= this.speed; this.accumTime += elapsed; while (this.accumTime >= this.simulationStepTime) { this.accumTime -= this.simulationStepTime; this.simulation.run(this.entities, this.simulationStepTime); } }; Scene.prototype.render = function(elapsed) { if (this.state !== "started") { return; } this.renderer.run(this.entities, elapsed); }; module.exports = Scene;