melonjs 9.1.0 → 10.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/{LICENSE → LICENSE.md} +0 -0
  2. package/README.md +93 -57
  3. package/dist/melonjs.js +10334 -11179
  4. package/dist/melonjs.min.js +4 -10
  5. package/dist/melonjs.module.d.ts +13206 -0
  6. package/dist/melonjs.module.js +9913 -10872
  7. package/package.json +19 -14
  8. package/src/audio/audio.js +477 -553
  9. package/src/camera/camera2d.js +67 -65
  10. package/src/entity/draggable.js +26 -35
  11. package/src/entity/droptarget.js +17 -14
  12. package/src/entity/entity.js +59 -79
  13. package/src/game.js +194 -204
  14. package/src/index.js +12 -30
  15. package/src/input/gamepad.js +8 -19
  16. package/src/input/keyboard.js +4 -4
  17. package/src/input/pointer.js +14 -12
  18. package/src/input/pointerevent.js +15 -13
  19. package/src/lang/deprecated.js +2 -887
  20. package/src/level/level.js +3 -3
  21. package/src/level/tiled/TMXGroup.js +7 -11
  22. package/src/level/tiled/TMXLayer.js +33 -32
  23. package/src/level/tiled/TMXTileMap.js +15 -19
  24. package/src/level/tiled/TMXTileset.js +5 -5
  25. package/src/level/tiled/TMXUtils.js +3 -3
  26. package/src/level/tiled/renderer/TMXRenderer.js +4 -0
  27. package/src/loader/loader.js +8 -23
  28. package/src/loader/loadingscreen.js +51 -60
  29. package/src/math/matrix3.js +1 -1
  30. package/src/particles/emitter.js +36 -39
  31. package/src/particles/particle.js +27 -12
  32. package/src/particles/particlecontainer.js +17 -16
  33. package/src/physics/body.js +80 -118
  34. package/src/physics/collision.js +5 -235
  35. package/src/physics/detector.js +235 -0
  36. package/src/physics/quadtree.js +14 -14
  37. package/src/physics/world.js +84 -18
  38. package/src/plugin/plugin.js +26 -24
  39. package/src/polyfill/console.js +9 -14
  40. package/src/renderable/GUI.js +48 -62
  41. package/src/renderable/collectable.js +11 -4
  42. package/src/renderable/colorlayer.js +28 -26
  43. package/src/renderable/container.js +120 -96
  44. package/src/renderable/imagelayer.js +94 -93
  45. package/src/renderable/renderable.js +164 -138
  46. package/src/renderable/sprite.js +42 -44
  47. package/src/renderable/trigger.js +24 -17
  48. package/src/shapes/ellipse.js +27 -27
  49. package/src/shapes/line.js +12 -8
  50. package/src/shapes/poly.js +77 -49
  51. package/src/shapes/rectangle.js +193 -268
  52. package/src/state/stage.js +23 -25
  53. package/src/state/state.js +35 -86
  54. package/src/system/device.js +233 -285
  55. package/src/system/event.js +485 -432
  56. package/src/system/pooling.js +61 -54
  57. package/src/system/save.js +17 -16
  58. package/src/system/timer.js +34 -38
  59. package/src/text/bitmaptext.js +44 -46
  60. package/src/text/text.js +39 -34
  61. package/src/tweens/easing.js +0 -2
  62. package/src/tweens/interpolation.js +3 -8
  63. package/src/tweens/tween.js +332 -351
  64. package/src/utils/function.js +6 -8
  65. package/src/utils/utils.js +34 -30
  66. package/src/video/canvas/canvas_renderer.js +13 -8
  67. package/src/video/renderer.js +8 -7
  68. package/src/video/texture.js +8 -8
  69. package/src/video/texture_cache.js +5 -5
  70. package/src/video/video.js +373 -403
  71. package/src/video/webgl/glshader.js +2 -2
  72. package/src/video/webgl/webgl_compositor.js +14 -8
  73. package/src/video/webgl/webgl_renderer.js +21 -19
  74. package/plugins/debug/debugPanel.js +0 -770
  75. package/plugins/debug/font/PressStart2P.fnt +0 -100
  76. package/plugins/debug/font/PressStart2P.ltr +0 -1
  77. package/plugins/debug/font/PressStart2P.png +0 -0
  78. package/plugins/debug/particleDebugPanel.js +0 -303
@@ -28,17 +28,14 @@ import Polygon from "./../shapes/poly.js";
28
28
  * @param {Number} [settings.collisionMask] Mask collision detection for this object
29
29
  * @param {me.Rect[]|me.Polygon[]|me.Line[]|me.Ellipse[]} [settings.shapes] the initial list of collision shapes (usually populated through Tiled)
30
30
  */
31
- var Entity = Renderable.extend({
31
+
32
+ class Entity extends Renderable {
33
+
34
+
32
35
  /**
33
36
  * @ignore
34
37
  */
35
- init : function (x, y, settings) {
36
-
37
- /**
38
- * The array of renderable children of this entity.
39
- * @ignore
40
- */
41
- this.children = [];
38
+ constructor(x, y, settings) {
42
39
 
43
40
  // ensure mandatory properties are defined
44
41
  if ((typeof settings.width !== "number") || (typeof settings.height !== "number")) {
@@ -46,7 +43,13 @@ var Entity = Renderable.extend({
46
43
  }
47
44
 
48
45
  // call the super constructor
49
- this._super(Renderable, "init", [x, y, settings.width, settings.height]);
46
+ super(x, y, settings.width, settings.height);
47
+
48
+ /**
49
+ * The array of renderable children of this entity.
50
+ * @ignore
51
+ */
52
+ this.children = [];
50
53
 
51
54
  if (settings.image) {
52
55
  // set the frame size to the given entity size, if not defined in settings
@@ -104,7 +107,6 @@ var Entity = Renderable.extend({
104
107
  * @memberOf me.Entity
105
108
  */
106
109
  // initialize the default body
107
-
108
110
  if (typeof settings.shapes === "undefined") {
109
111
  settings.shapes = new Polygon(0, 0, [
110
112
  new Vector2d(0, 0),
@@ -113,13 +115,7 @@ var Entity = Renderable.extend({
113
115
  new Vector2d(0, this.height)
114
116
  ]);
115
117
  }
116
-
117
- if (typeof this.body !== "undefined") {
118
- this.body.init(this, settings.shapes, this.onBodyUpdate.bind(this));
119
- }
120
- else {
121
- this.body = new Body(this, settings.shapes, this.onBodyUpdate.bind(this));
122
- }
118
+ this.body = new Body(this, settings.shapes, this.onBodyUpdate.bind(this));
123
119
 
124
120
  // resize the entity if required
125
121
  if (this.width === 0 && this.height === 0) {
@@ -132,15 +128,42 @@ var Entity = Renderable.extend({
132
128
 
133
129
  // disable for entities
134
130
  this.autoTransform = false;
135
- },
131
+ }
132
+
133
+
134
+ /**
135
+ * The entity renderable component (can be any objects deriving from me.Renderable, like me.Sprite for example)
136
+ * @public
137
+ * @type me.Renderable
138
+ * @name renderable
139
+ * @memberOf me.Entity
140
+ */
141
+
142
+ /**
143
+ * @ignore
144
+ */
145
+ get renderable() {
146
+ return this.children[0];
147
+ }
148
+ /**
149
+ * @ignore
150
+ */
151
+ set renderable(value) {
152
+ if (value instanceof Renderable) {
153
+ this.children[0] = value;
154
+ this.children[0].ancestor = this;
155
+ } else {
156
+ throw new Error(value + "should extend me.Renderable");
157
+ }
158
+ }
136
159
 
137
160
  /** @ignore */
138
- update : function (dt) {
161
+ update(dt) {
139
162
  if (this.renderable) {
140
- return this.renderable.update(dt);
163
+ this.isDirty |= this.renderable.update(dt);
141
164
  }
142
- return this._super(Renderable, "update", [dt]);
143
- },
165
+ return super.update(dt);
166
+ }
144
167
 
145
168
  /**
146
169
  * update the bounds position when the body is modified
@@ -149,14 +172,14 @@ var Entity = Renderable.extend({
149
172
  * @memberOf me.Entity
150
173
  * @function
151
174
  */
152
- onBodyUpdate : function (body) {
175
+ onBodyUpdate(body) {
153
176
  // update the entity bounds to include the body bounds
154
177
  this.getBounds().addBounds(body.getBounds(), true);
155
178
  // update the bounds pos
156
179
  this.updateBoundsPos(this.pos.x, this.pos.y);
157
- },
180
+ }
158
181
 
159
- preDraw : function (renderer) {
182
+ preDraw(renderer) {
160
183
  renderer.save();
161
184
 
162
185
  // translate to the entity position
@@ -174,7 +197,7 @@ var Entity = Renderable.extend({
174
197
  this.anchorPoint.y * this.body.getBounds().height
175
198
  );
176
199
  }
177
- },
200
+ }
178
201
 
179
202
  /**
180
203
  * object draw<br>
@@ -187,7 +210,7 @@ var Entity = Renderable.extend({
187
210
  * @param {me.CanvasRenderer|me.WebGLRenderer} renderer a renderer object
188
211
  * @param {me.Rect} region to draw
189
212
  **/
190
- draw : function (renderer, rect) {
213
+ draw(renderer, rect) {
191
214
  var renderable = this.renderable;
192
215
  if (renderable instanceof Renderable) {
193
216
  // predraw (apply transforms)
@@ -199,13 +222,13 @@ var Entity = Renderable.extend({
199
222
  // postdraw (clean-up);
200
223
  renderable.postDraw(renderer);
201
224
  }
202
- },
225
+ }
203
226
 
204
227
  /**
205
228
  * Destroy function<br>
206
229
  * @ignore
207
230
  */
208
- destroy : function () {
231
+ destroy() {
209
232
  // free some property objects
210
233
  if (this.renderable) {
211
234
  this.renderable.destroy.apply(this.renderable, arguments);
@@ -213,8 +236,8 @@ var Entity = Renderable.extend({
213
236
  }
214
237
 
215
238
  // call the parent destroy method
216
- this._super(Renderable, "destroy", arguments);
217
- },
239
+ super.destroy(arguments);
240
+ }
218
241
 
219
242
  /**
220
243
  * onDeactivateEvent Notification function<br>
@@ -223,55 +246,12 @@ var Entity = Renderable.extend({
223
246
  * @memberOf me.Entity
224
247
  * @function
225
248
  */
226
- onDeactivateEvent : function () {
227
- if (this.renderable && this.renderable.onDeactivateEvent) {
228
- this.renderable.onDeactivateEvent();
229
- }
230
- },
231
-
232
- /**
233
- * onCollision callback<br>
234
- * triggered in case of collision, when this entity body is being "touched" by another one<br>
235
- * @name onCollision
236
- * @memberOf me.Entity
237
- * @function
238
- * @param {me.collision.ResponseObject} response the collision response object
239
- * @param {me.Entity} other the other entity touching this one (a reference to response.a or response.b)
240
- * @return {Boolean} true if the object should respond to the collision (its position and velocity will be corrected)
241
- */
242
- onCollision : function () {
243
- return false;
249
+ onDeactivateEvent() {
250
+ if (this.renderable && this.renderable.onDeactivateEvent) {
251
+ this.renderable.onDeactivateEvent();
252
+ }
244
253
  }
245
- });
246
-
247
254
 
248
- /**
249
- * The entity renderable component (can be any objects deriving from me.Renderable, like me.Sprite for example)
250
- * @public
251
- * @type me.Renderable
252
- * @name renderable
253
- * @memberOf me.Entity
254
- */
255
- Object.defineProperty(Entity.prototype, "renderable", {
256
- /* for backward compatiblity */
257
- /**
258
- * @ignore
259
- */
260
- get : function () {
261
- return this.children[0];
262
- },
263
- /**
264
- * @ignore
265
- */
266
- set : function (value) {
267
- if (value instanceof Renderable) {
268
- this.children[0] = value;
269
- this.children[0].ancestor = this;
270
- } else {
271
- throw new Error(value + "should extend me.Renderable");
272
- }
273
- },
274
- configurable : true
275
- });
255
+ };
276
256
 
277
257
  export default Entity;
package/src/game.js CHANGED
@@ -1,5 +1,5 @@
1
- import video from "./video/video.js";
2
- import event from "./system/event.js";
1
+ import { renderer } from "./video/video.js";
2
+ import * as event from "./system/event.js";
3
3
  import timer from "./system/timer.js";
4
4
  import state from "./state/state.js";
5
5
  import World from "./physics/world.js";
@@ -35,220 +35,210 @@ var lastUpdateStart = null;
35
35
  var updateAverageDelta = 0;
36
36
 
37
37
 
38
- var game = {
39
-
40
- /**
41
- * a reference to the current active stage "default" camera
42
- * @public
43
- * @type {me.Camera2d}
44
- * @name viewport
45
- * @memberOf me.game
46
- */
47
- viewport : undefined,
48
-
49
- /**
50
- * a reference to the game world, <br>
51
- * a world is a virtual environment containing all the game objects
52
- * @public
53
- * @type {me.World}
54
- * @name world
55
- * @memberOf me.game
56
- */
57
- world : null,
58
-
59
- /**
60
- * when true, all objects will be added under the root world container.<br>
61
- * When false, a `me.Container` object will be created for each corresponding groups
62
- * @public
63
- * @type {boolean}
64
- * @default true
65
- * @name mergeGroup
66
- * @memberOf me.game
67
- */
68
- mergeGroup : true,
69
-
70
- /**
71
- * Specify the property to be used when sorting entities.
72
- * Accepted values : "x", "y", "z"
73
- * @public
74
- * @type {string}
75
- * @default "z"
76
- * @name sortOn
77
- * @memberOf me.game
78
- */
79
- sortOn : "z",
80
-
81
- /**
82
- * Fired when a level is fully loaded and <br>
83
- * and all entities instantiated. <br>
84
- * Additionnaly the level id will also be passed
85
- * to the called function.
86
- * @public
87
- * @function
88
- * @name onLevelLoaded
89
- * @memberOf me.game
90
- * @example
91
- * // call myFunction () everytime a level is loaded
92
- * me.game.onLevelLoaded = this.myFunction.bind(this);
93
- */
94
- onLevelLoaded : function () {},
95
-
96
- /**
97
- * Initialize the game manager
98
- * @name init
99
- * @memberOf me.game
100
- * @ignore
101
- * @function
102
- */
103
- init : function () {
104
- // the root object of our world is an entity container
105
- this.world = new World();
106
-
107
- // publish init notification
108
- event.publish(event.GAME_INIT);
109
-
110
- // make display dirty by default
111
- isDirty = true;
112
- },
113
-
114
- /**
115
- * reset the game Object manager<br>
116
- * destroy all current objects
117
- * @name reset
118
- * @memberOf me.game
119
- * @public
120
- * @function
121
- */
122
- reset : function () {
123
- // point to the current active stage "default" camera
124
- var current = state.current();
125
- if (typeof current !== "undefined") {
126
- this.viewport = state.current().cameras.get("default");
127
- }
38
+ // initialize the game manager on system boot
39
+ event.on(event.BOOT, () => {
40
+ // the root object of our world is an entity container
41
+ world = new World();
42
+ // publish init notification
43
+ event.emit(event.GAME_INIT);
44
+ });
45
+
46
+
47
+ /**
48
+ * a reference to the current active stage "default" camera
49
+ * @public
50
+ * @type {me.Camera2d}
51
+ * @name viewport
52
+ * @memberOf me.game
53
+ */
54
+ export let viewport;
55
+
56
+ /**
57
+ * a reference to the game world, <br>
58
+ * a world is a virtual environment containing all the game objects
59
+ * @public
60
+ * @type {me.World}
61
+ * @name world
62
+ * @memberOf me.game
63
+ */
64
+ export let world;
128
65
 
129
- // publish reset notification
130
- event.publish(event.GAME_RESET);
131
-
132
- // Refresh internal variables for framerate limiting
133
- this.updateFrameRate();
134
- },
135
-
136
- /**
137
- * Update the renderer framerate using the system config variables.
138
- * @name updateFrameRate
139
- * @memberOf me.game
140
- * @public
141
- * @function
142
- * @see me.timer.maxfps
143
- * @see me.game.world.fps
144
- */
145
- updateFrameRate : function () {
66
+ /**
67
+ * when true, all objects will be added under the root world container.<br>
68
+ * When false, a `me.Container` object will be created for each corresponding groups
69
+ * @public
70
+ * @type {boolean}
71
+ * @default true
72
+ * @name mergeGroup
73
+ * @memberOf me.game
74
+ */
75
+ export let mergeGroup = true;
76
+
77
+ /**
78
+ * Specify the property to be used when sorting entities.
79
+ * Accepted values : "x", "y", "z"
80
+ * @public
81
+ * @type {string}
82
+ * @default "z"
83
+ * @name sortOn
84
+ * @memberOf me.game
85
+ */
86
+ export let sortOn = "z";
87
+
88
+ /**
89
+ * Last time the game update loop was executed. <br>
90
+ * Use this value to implement frame prediction in drawing events,
91
+ * for creating smooth motion while running game update logic at
92
+ * a lower fps.
93
+ * @public
94
+ * @type {DOMHighResTimeStamp}
95
+ * @name lastUpdate
96
+ * @memberOf me.game
97
+ */
98
+ export let lastUpdate = window.performance.now();
99
+
100
+ /**
101
+ * Fired when a level is fully loaded and all entities instantiated. <br>
102
+ * Additionnaly the level id will also be passed to the called function.
103
+ * @function me.game.onLevelLoaded
104
+ * @example
105
+ * // call myFunction () everytime a level is loaded
106
+ * me.game.onLevelLoaded = this.myFunction.bind(this);
107
+ */
108
+ export function onLevelLoaded() {};
109
+
110
+ /**
111
+ * reset the game Object manager<br>
112
+ * destroy all current objects
113
+ * @function me.game.reset
114
+ */
115
+ export function reset () {
116
+ // point to the current active stage "default" camera
117
+ var current = state.current();
118
+ if (typeof current !== "undefined") {
119
+ viewport = current.cameras.get("default");
120
+ }
121
+
122
+ // publish reset notification
123
+ event.emit(event.GAME_RESET);
124
+
125
+ // Refresh internal variables for framerate limiting
126
+ updateFrameRate();
127
+ }
128
+
129
+ /**
130
+ * Update the renderer framerate using the system config variables.
131
+ * @function me.game.updateFrameRate
132
+ * @see me.timer.maxfps
133
+ * @see me.game.world.fps
134
+ */
135
+ export function updateFrameRate() {
136
+ // reset the frame counter
137
+ frameCounter = 0;
138
+ frameRate = ~~(0.5 + 60 / timer.maxfps);
139
+
140
+ // set step size based on the updatesPerSecond
141
+ stepSize = (1000 / world.fps);
142
+ accumulator = 0.0;
143
+ accumulatorMax = stepSize * 10;
144
+
145
+ // display should always re-draw when update speed doesn't match fps
146
+ // this means the user intends to write position prediction drawing logic
147
+ isAlwaysDirty = (timer.maxfps > world.fps);
148
+ };
149
+
150
+ /**
151
+ * Returns the parent container of the specified Child in the game world
152
+ * @function me.game.getParentContainer
153
+ * @param {me.Renderable} child
154
+ * @return {me.Container}
155
+ */
156
+ export function getParentContainer(child) {
157
+ return child.ancestor;
158
+ };
159
+
160
+ /**
161
+ * force the redraw (not update) of all objects
162
+ * @function me.game.repaint
163
+ */
164
+ export function repaint() {
165
+ isDirty = true;
166
+ };
167
+
168
+
169
+ /**
170
+ * update all objects of the game manager
171
+ * @ignore
172
+ * @function me.game.update
173
+ * @param {Number} time current timestamp as provided by the RAF callback
174
+ * @param {me.Stage} stage the current stage
175
+ */
176
+ export function update(time, stage) {
177
+ // handle frame skipping if required
178
+ if ((++frameCounter % frameRate) === 0) {
146
179
  // reset the frame counter
147
180
  frameCounter = 0;
148
- frameRate = ~~(0.5 + 60 / timer.maxfps);
149
-
150
- // set step size based on the updatesPerSecond
151
- stepSize = (1000 / this.world.fps);
152
- accumulator = 0.0;
153
- accumulatorMax = stepSize * 10;
154
-
155
- // display should always re-draw when update speed doesn't match fps
156
- // this means the user intends to write position prediction drawing logic
157
- isAlwaysDirty = (timer.maxfps > this.world.fps);
158
- },
159
-
160
- /**
161
- * Returns the parent container of the specified Child in the game world
162
- * @name getParentContainer
163
- * @memberOf me.game
164
- * @function
165
- * @param {me.Renderable} child
166
- * @return {me.Container}
167
- */
168
- getParentContainer : function (child) {
169
- return child.ancestor;
170
- },
171
-
172
- /**
173
- * force the redraw (not update) of all objects
174
- * @name repaint
175
- * @memberOf me.game
176
- * @public
177
- * @function
178
- */
179
-
180
- repaint : function () {
181
- isDirty = true;
182
- },
183
-
184
-
185
- /**
186
- * update all objects of the game manager
187
- * @name update
188
- * @memberOf me.game
189
- * @ignore
190
- * @function
191
- * @param {Number} time current timestamp as provided by the RAF callback
192
- * @param {me.Stage} stage the current stage
193
- */
194
- update : function (time, stage) {
195
- // handle frame skipping if required
196
- if ((++frameCounter % frameRate) === 0) {
197
- // reset the frame counter
198
- frameCounter = 0;
199
181
 
200
- // game update event
201
- event.publish(event.GAME_UPDATE, [ time ]);
182
+ // publish notification
183
+ event.emit(event.GAME_BEFORE_UPDATE, time);
184
+
185
+ accumulator += timer.getDelta();
186
+ accumulator = Math.min(accumulator, accumulatorMax);
202
187
 
203
- accumulator += timer.getDelta();
204
- accumulator = Math.min(accumulator, accumulatorMax);
188
+ updateDelta = (timer.interpolation) ? timer.getDelta() : stepSize;
189
+ accumulatorUpdateDelta = (timer.interpolation) ? updateDelta : Math.max(updateDelta, updateAverageDelta);
205
190
 
206
- updateDelta = (timer.interpolation) ? timer.getDelta() : stepSize;
207
- accumulatorUpdateDelta = (timer.interpolation) ? updateDelta : Math.max(updateDelta, updateAverageDelta);
191
+ while (accumulator >= accumulatorUpdateDelta || timer.interpolation) {
192
+ lastUpdateStart = window.performance.now();
208
193
 
209
- while (accumulator >= accumulatorUpdateDelta || timer.interpolation) {
210
- lastUpdateStart = window.performance.now();
194
+ // game update event
195
+ if (state.isPaused() !== true) {
196
+ event.emit(event.GAME_UPDATE, time);
197
+ }
211
198
 
212
- // update all objects (and pass the elapsed time since last frame)
213
- isDirty = stage.update(updateDelta) || isDirty;
199
+ // update all objects (and pass the elapsed time since last frame)
200
+ isDirty = stage.update(updateDelta) || isDirty;
214
201
 
215
- timer.lastUpdate = window.performance.now();
216
- updateAverageDelta = timer.lastUpdate - lastUpdateStart;
202
+ lastUpdate = window.performance.now();
203
+ updateAverageDelta = lastUpdate - lastUpdateStart;
217
204
 
218
- accumulator -= accumulatorUpdateDelta;
219
- if (timer.interpolation) {
220
- accumulator = 0;
221
- break;
222
- }
205
+ accumulator -= accumulatorUpdateDelta;
206
+ if (timer.interpolation) {
207
+ accumulator = 0;
208
+ break;
223
209
  }
224
210
  }
225
- },
226
-
227
- /**
228
- * draw the current scene/stage
229
- * @name draw
230
- * @memberOf me.game
231
- * @ignore
232
- * @function
233
- * @param {me.Stage} stage the current stage
234
- */
235
- draw : function (stage) {
236
- var renderer = video.renderer;
237
-
238
- if (renderer.isContextValid === true && (isDirty || isAlwaysDirty)) {
239
- // prepare renderer to draw a new frame
240
- renderer.clear();
241
-
242
- // render the stage
243
- stage.draw(renderer);
244
-
245
- // set back to flag
246
- isDirty = false;
247
-
248
- // flush/render our frame
249
- renderer.flush();
250
- }
211
+
212
+ // publish notification
213
+ event.emit(event.GAME_AFTER_UPDATE, lastUpdate);
251
214
  }
252
215
  };
253
216
 
254
- export default game;
217
+ /**
218
+ * draw the current scene/stage
219
+ * @function me.game.draw
220
+ * @ignore
221
+ * @param {me.Stage} stage the current stage
222
+ */
223
+ export function draw(stage) {
224
+
225
+ if (renderer.isContextValid === true && (isDirty || isAlwaysDirty)) {
226
+ // publish notification
227
+ event.emit(event.GAME_BEFORE_DRAW, window.performance.now());
228
+
229
+ // prepare renderer to draw a new frame
230
+ renderer.clear();
231
+
232
+ // render the stage
233
+ stage.draw(renderer);
234
+
235
+ // set back to flag
236
+ isDirty = false;
237
+
238
+ // flush/render our frame
239
+ renderer.flush();
240
+
241
+ // publish notification
242
+ event.emit(event.GAME_AFTER_DRAW, window.performance.now());
243
+ }
244
+ };