1 | var AssetLoader = require("./assets/asset-loader");
|
2 | var loadImage = require("./assets/load-image");
|
3 | var Input = require("./input");
|
4 | var Prefabs = require("./prefabs");
|
5 | var Scene = require("./scene");
|
6 | var SoundManager = require("./sound-manager");
|
7 | var splitFilmStripAnimations = require("./split-filmstrip-animations");
|
8 |
|
9 | function Game(canvas, customRequire) {
|
10 | this.animations = customRequire("./data/animations");
|
11 | splitFilmStripAnimations(this.animations);
|
12 | this.canvas = canvas;
|
13 | this.context = canvas.getContext("2d");
|
14 | this.images = new AssetLoader(customRequire("./data/images"), loadImage);
|
15 | this.inputs = new Input(customRequire("./data/inputs"), canvas);
|
16 | this.require = customRequire;
|
17 | this.sounds = new SoundManager(customRequire("./data/sounds"));
|
18 | this.prefabs = new Prefabs(customRequire("./data/prefabs"));
|
19 | this.lastTime = -1;
|
20 | this.remainingDebugTime = undefined;
|
21 |
|
22 | this.scaleCanvasToCssSize();
|
23 | window.addEventListener("resize", this.onCanvasResize.bind(this));
|
24 |
|
25 | this.scenes = this.makeScenes(customRequire("./data/scenes"));
|
26 | this.run = this.run.bind(this);
|
27 | }
|
28 | Game.prototype.makeScenes = function(sceneList) {
|
29 | var names = Object.keys(sceneList);
|
30 | var scenes = {};
|
31 | for (var i = 0; i < names.length; i++) {
|
32 | var name = names[i];
|
33 | scenes[name] = new Scene(name, {
|
34 | animations: this.animations,
|
35 | canvas: this.canvas,
|
36 | context: this.context,
|
37 | images: this.images,
|
38 | inputs: this.inputs,
|
39 | prefabs: this.prefabs,
|
40 | require: this.require,
|
41 | scaleCanvasToCssSize: this.scaleCanvasToCssSize.bind(this),
|
42 | scaleCanvasToFitRectangle: this.scaleCanvasToFitRectangle.bind(this),
|
43 | scenes: scenes,
|
44 | sounds: this.sounds
|
45 | });
|
46 | if (sceneList[name].first) {
|
47 | scenes[name].start();
|
48 | }
|
49 | }
|
50 | return scenes;
|
51 | };
|
52 | Game.prototype.start = function() {
|
53 | if (this.running) {
|
54 | return;
|
55 | }
|
56 | this.running = true;
|
57 | this.lastTime = -1;
|
58 | window.requestAnimationFrame(this.run);
|
59 | };
|
60 | Game.prototype.stop = function() {
|
61 | this.running = false;
|
62 | };
|
63 | Game.prototype.run = function(time) {
|
64 | var scenes = Object.keys(this.scenes);
|
65 |
|
66 | if (this.lastTime === -1) {
|
67 | this.lastTime = time;
|
68 | }
|
69 | var elapsed = time - this.lastTime;
|
70 | this.lastTime = time;
|
71 |
|
72 | for (var i = 0; i < scenes.length; i++) {
|
73 | var name = scenes[i];
|
74 | var scene = this.scenes[name];
|
75 | scene.simulate(elapsed);
|
76 | }
|
77 | for (i = 0; i < scenes.length; i++) {
|
78 | name = scenes[i];
|
79 | scene = this.scenes[name];
|
80 | this.context.save();
|
81 | scene.render(elapsed);
|
82 | this.context.restore();
|
83 | }
|
84 |
|
85 | if (this.remainingDebugTime !== undefined) {
|
86 | this.remainingDebugTime -= elapsed;
|
87 | if (this.remainingDebugTime <= 0) {
|
88 | this.remainingDebugTime = undefined;
|
89 | this.logDebugTimes();
|
90 | }
|
91 | }
|
92 |
|
93 | if (this.running) {
|
94 | window.requestAnimationFrame(this.run);
|
95 | }
|
96 | };
|
97 | Game.prototype.timeSystems = function(total) {
|
98 | var scenes = Object.keys(this.scenes);
|
99 | for (var i = 0; i < scenes.length; i++) {
|
100 | var name = scenes[i];
|
101 | var scene = this.scenes[name];
|
102 | scene.simulation.resetTimings();
|
103 | scene.renderer.resetTimings();
|
104 | }
|
105 | this.remainingDebugTime = total;
|
106 | };
|
107 | Game.prototype.logDebugTimes = function() {
|
108 | var scenes = Object.keys(this.scenes);
|
109 | var timings = [];
|
110 | for (var i = 0; i < scenes.length; i++) {
|
111 | var name = scenes[i];
|
112 | var scene = this.scenes[name];
|
113 | timings = timings.concat(scene.simulation.timings());
|
114 | timings = timings.concat(scene.renderer.timings());
|
115 | }
|
116 | console.table(groupTimings(timings));
|
117 | };
|
118 | function groupTimings(timings) {
|
119 | var total = timings.map(function(timing) {
|
120 | return timing.time;
|
121 | }).reduce(function(a, b) {
|
122 | return a + b;
|
123 | });
|
124 | timings.sort(function(a, b) {
|
125 | return b.time - a.time;
|
126 | }).forEach(function(timing) {
|
127 | timing.percent = timing.time / total;
|
128 | });
|
129 | return timings;
|
130 | }
|
131 | Game.prototype.onCanvasResize = function() {
|
132 | this.resizer();
|
133 | };
|
134 | Game.prototype.scaleCanvasToCssSize = function() {
|
135 | this.resizer = function() {
|
136 | var canvasStyle = window.getComputedStyle(this.canvas);
|
137 | var width = parseInt(canvasStyle.width);
|
138 | var height = parseInt(canvasStyle.height);
|
139 | this.canvas.width = width;
|
140 | this.canvas.height = height;
|
141 | }.bind(this);
|
142 | this.resizer();
|
143 | };
|
144 | Game.prototype.scaleCanvasToFitRectangle = function(width, height) {
|
145 | this.resizer = function() {
|
146 | var canvasStyle = window.getComputedStyle(this.canvas);
|
147 | var cssWidth = parseInt(canvasStyle.width);
|
148 | var cssHeight = parseInt(canvasStyle.height);
|
149 | var cssAspectRatio = cssWidth / cssHeight;
|
150 |
|
151 | var desiredWidth = width;
|
152 | var desiredHeight = height;
|
153 | var desiredAspectRatio = width / height;
|
154 | if (desiredAspectRatio > cssAspectRatio) {
|
155 | desiredHeight = Math.floor(width / cssAspectRatio);
|
156 | } else if (desiredAspectRatio < cssAspectRatio) {
|
157 | desiredWidth = Math.floor(height * cssAspectRatio);
|
158 | }
|
159 |
|
160 | this.canvas.width = desiredWidth;
|
161 | this.canvas.height = desiredHeight;
|
162 | }.bind(this);
|
163 | this.resizer();
|
164 | };
|
165 |
|
166 | module.exports = Game;
|