UNPKG

3.87 kBJavaScriptView Raw
1var clone = require("./clone");
2var components = require("./components");
3var ECS = require("entity-component-system").EntityComponentSystem;
4var EntityPool = require("entity-component-system").EntityPool;
5var registerComponents = require("./components/register");
6
7function Scene(name, globals) {
8 this.data = {};
9 this.entities = new EntityPool();
10 this.globals = globals;
11 this.name = name;
12 this.onEnter = function() {};
13 this.onExit = function() {};
14 this.renderer = new ECS();
15 this.state = "stopped";
16 this.speed = 1.0;
17 this.simulation = new ECS();
18 this.simulationStepTime = 5;
19
20 this.firstTime = true;
21 this.accumTime = 0;
22
23 var sceneData = globals.require("./data/scenes")[name];
24 if (typeof sceneData.onEnter === "string") {
25 this.onEnter = globals.require(sceneData.onEnter);
26 }
27 if (typeof sceneData.onExit === "string") {
28 this.onExit = globals.require(sceneData.onExit);
29 }
30}
31Scene.prototype.start = function(sceneArgs) {
32 if (this.state !== "stopped") {
33 return;
34 }
35 this.state = "starting";
36 this.tempArguments = sceneArgs;
37};
38Scene.prototype._initialize = function() {
39 this.entities = new EntityPool();
40 this.firstTime = true;
41 this.accumTime = 0;
42
43 this.data = {
44 animations: this.globals.animations,
45 arguments: this.tempArguments || {},
46 canvas: this.globals.canvas,
47 context: this.globals.context,
48 entities: this.entities,
49 images: this.globals.images,
50 inputs: this.globals.inputs,
51 prefabs: this.globals.prefabs,
52 require: this.globals.require,
53 scaleCanvasToCssSize: this.globals.scaleCanvasToCssSize,
54 scaleCanvasToFitRectangle: this.globals.scaleCanvasToFitRectangle,
55 scenes: this.globals.scenes,
56 sounds: this.globals.sounds,
57 switchScene: this.switchScene.bind(this)
58 };
59
60 this.simulation = new ECS();
61 this.renderer = new ECS();
62 this.simulation.add(function processInputUpdates() {
63 this.globals.inputs.processUpdates();
64 }.bind(this));
65
66 var systems = this.globals.require("./data/systems");
67 this.installSystems(systems.simulation, this.simulation, this.data);
68 this.installSystems(systems.renderer, this.renderer, this.data);
69
70 registerComponents(this.entities, components);
71 registerComponents(this.entities, this.globals.require("./data/components"));
72 var entities = this.globals.require("./data/entities");
73 this.entities.load(clone(entities[this.name]) || []);
74
75 this.onEnter(this.data);
76};
77Scene.prototype.stop = function() {
78 if (this.state === "stopped") {
79 return;
80 }
81 this.state = "stopped";
82 this.onExit(this.data);
83};
84Scene.prototype.switchScene = function(scene, sceneArgs) {
85 this.stop();
86 this.data.scenes[scene].start(sceneArgs);
87};
88Scene.prototype.installSystems = function(systems, ecs, data) {
89 for (var i = 0; i < systems.length; i++) {
90 var system = systems[i];
91
92 if (system.scenes.indexOf(this.name) === -1 && system.scenes !== "all") {
93 continue;
94 }
95 var script = this.globals.require(system.name);
96 if (script === undefined) {
97 console.error("failed to load script", system.name);
98 }
99 script(ecs, data);
100 }
101};
102Scene.prototype.simulate = function(elapsed) {
103 if (this.state === "stopped") {
104 return;
105 }
106 if (this.state === "starting") {
107 this._initialize();
108 this.state = "started";
109 }
110
111 if (this.firstTime) {
112 this.firstTime = false;
113 // run simulation the first time, because not enough time will have elapsed
114 this.simulation.run(this.entities, 0);
115 }
116
117 elapsed *= this.speed;
118
119 this.accumTime += elapsed;
120 while (this.accumTime >= this.simulationStepTime) {
121 this.accumTime -= this.simulationStepTime;
122 this.simulation.run(this.entities, this.simulationStepTime);
123 }
124};
125Scene.prototype.render = function(elapsed) {
126 if (this.state !== "started") {
127 return;
128 }
129 this.renderer.run(this.entities, elapsed);
130};
131
132module.exports = Scene;