]> git.r.bdr.sh - rbdr/sumo/blob - lib/sumo.js
Render Sumo (#3)
[rbdr/sumo] / lib / sumo.js
1 import RenderSystem from './systems/render';
2 import SumoFactory from './factories/sumo';
3 import Serpentity from '@serpentity/serpentity';
4 import { Application } from 'pixi.js';
5
6 /* global window document */
7
8 const internals = {
9 kBackgroundColor: 0xd8c590,
10 kNoElementError: 'No element found. Cannot render.',
11
12 // Handler for the window load event. Initializes and runs the app.
13
14 onLoad() {
15
16 const sumo = new internals.Sumo({
17 element: document.getElementById('sumo-app-entry-point')
18 });
19
20 sumo.startLoop();
21
22 internals.exports.sumo = sumo;
23 }
24 };
25
26 /**
27 * Sumo - main entry point. Attached to window->load
28 *
29 * @class Sumo
30 *
31 * @param {object} config the configuration to extend the object
32 *
33 * @property {HTMLElement} [element=null] the element in which to render.
34 * Required, will throw if not provided
35 * @property {Number} [fps=60] the fps target to maintain
36 * @property {Number} [verticalResolution=224] how many pixels to render in the vertical
37 * axis (gets scaled if the canvas is larger)
38 * @property {Array<Number>} [aspectRatio=[2.76, 1]] the aspect ratio experssed as
39 * an array of two numbers, where aspect ratio x:y is [x, y] (eg. [16, 9])
40 */
41
42 internals.Sumo = class Sumo {
43
44 constructor(config) {
45
46 this.fps = 60;
47 this.aspectRatio = [2.76, 1];
48 this.verticalResolution = 224;
49
50 Object.assign(this, config);
51
52 if (!this.element) {
53 throw new Error(internals.kNoElementError);
54 }
55
56 this._engine = new Serpentity();
57
58 this._previousTime = 0;
59 this._looping = false;
60
61 // Initialization functions
62 this._initializeCanvas();
63 this._initializePixi();
64 this._initializeSystems();
65 this._initializeEntities();
66 }
67
68 /**
69 * Starts the main loop. Resets the FPS (if you change it it won't go
70 * live until after you stop and start the loop)
71 *
72 * @function startLoop
73 * @instance
74 * @memberof Sumo
75 */
76 startLoop() {
77
78 this._looping = true;
79 this._frameDuration = 1000 / this.fps;
80 window.requestAnimationFrame(this._loop.bind(this));
81 }
82
83 /**
84 * Pauses the loop
85 *
86 * @function pauseLoop
87 * @instance
88 * @memberof Sumo
89 */
90 pauseLoop() {
91
92 this._looping = false;
93 }
94
95 // The main loop used above. Runs the serpentity update process and
96 // attempts to maintain FPS. The rest is handled by the engine.
97
98 _loop(currentTime) {
99
100 if (!this._looping) {
101 return;
102 }
103
104 window.requestAnimationFrame(this._loop.bind(this));
105
106 const currentFrameDuration = currentTime - this._previousTime;
107
108 if (currentFrameDuration > this._frameDuration) {
109
110 // We're sending the currentTime since it gives better results for
111 // this type of renderer, though usually we expect the delta
112 this._engine.update(currentTime);
113 this._previousTime = currentTime;
114 }
115 }
116
117 // Creates a canvas for rendering
118
119 _initializeCanvas() {
120
121 this._canvas = document.createElement('canvas');
122 this.element.appendChild(this._canvas);
123 this._resizeCanvas();
124 window.addEventListener('resize', this._resizeCanvas.bind(this));
125 }
126
127 // Initialize Pixi
128
129 _initializePixi() {
130
131 this._pixi = new Application({
132 backgroundColor: internals.kBackgroundColor,
133 view: this._canvas,
134 width: this._canvas.width,
135 height: this._canvas.height
136 });
137 }
138
139 // Resizes the canvas to a square the size of the smallest magnitude
140 // of the window.
141
142 _resizeCanvas() {
143
144 let width = window.innerWidth;
145 let height = Math.round(width * this.aspectRatio[1] / this.aspectRatio[0]);
146
147 if (window.innerHeight < height) {
148 height = window.innerHeight;
149 width = Math.round(height * this.aspectRatio[0] / this.aspectRatio[1]);
150 }
151
152 this._canvas.style.width = `${width}px`;
153 this._canvas.style.height = `${height}px`;
154
155 this._canvas.width = Math.round(this.verticalResolution * this.aspectRatio[0] / this.aspectRatio[1]);
156 this._canvas.height = this.verticalResolution;
157 }
158
159 // Initializes the serpentity systems
160
161 _initializeSystems() {
162
163 this._engine.addSystem(new RenderSystem({
164 application: this._pixi
165 }));
166 }
167
168 // Initializes the serpentity entities
169
170 _initializeEntities() {
171
172 SumoFactory.createSumo(this._engine, {
173 position: {
174 x: 50,
175 y: 50
176 }
177 });
178
179 SumoFactory.createSumo(this._engine, {
180 position: {
181 x: 309,
182 y: 112
183 }
184 });
185 }
186 };
187
188 export default internals.exports = {};
189
190 // autorun.bat
191 window.addEventListener('load', internals.onLoad);