melonjs 10.5.2 → 10.6.0

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 (46) hide show
  1. package/README.md +4 -6
  2. package/dist/melonjs.js +4314 -4177
  3. package/dist/melonjs.min.js +14 -14
  4. package/dist/melonjs.module.d.ts +242 -267
  5. package/dist/melonjs.module.js +4646 -4523
  6. package/package.json +10 -10
  7. package/src/camera/camera2d.js +11 -10
  8. package/src/geometries/ellipse.js +1 -1
  9. package/src/geometries/poly.js +1 -1
  10. package/src/index.js +1 -1
  11. package/src/input/pointerevent.js +1 -1
  12. package/src/level/tiled/TMXLayer.js +1 -1
  13. package/src/level/tiled/TMXTileMap.js +1 -1
  14. package/src/level/tiled/renderer/TMXHexagonalRenderer.js +1 -1
  15. package/src/level/tiled/renderer/TMXIsometricRenderer.js +1 -1
  16. package/src/level/tiled/renderer/TMXOrthogonalRenderer.js +1 -1
  17. package/src/level/tiled/renderer/TMXRenderer.js +1 -1
  18. package/src/level/tiled/renderer/TMXStaggeredRenderer.js +1 -1
  19. package/src/loader/loadingscreen.js +1 -1
  20. package/src/math/color.js +1 -1
  21. package/src/math/matrix2.js +2 -2
  22. package/src/math/matrix3.js +1 -1
  23. package/src/math/observable_vector2.js +1 -1
  24. package/src/math/observable_vector3.js +1 -1
  25. package/src/math/vector2.js +1 -1
  26. package/src/math/vector3.js +1 -1
  27. package/src/particles/emitter.js +1 -1
  28. package/src/physics/body.js +7 -7
  29. package/src/renderable/colorlayer.js +1 -1
  30. package/src/renderable/container.js +11 -1
  31. package/src/renderable/imagelayer.js +1 -1
  32. package/src/renderable/nineslicesprite.js +6 -3
  33. package/src/renderable/renderable.js +18 -1
  34. package/src/renderable/sprite.js +2 -2
  35. package/src/state/state.js +6 -6
  36. package/src/system/pooling.js +150 -155
  37. package/src/text/bitmaptext.js +30 -86
  38. package/src/text/text.js +82 -145
  39. package/src/text/textmetrics.js +168 -0
  40. package/src/text/textstyle.js +14 -0
  41. package/src/video/canvas/canvas_renderer.js +21 -5
  42. package/src/video/renderer.js +1 -3
  43. package/src/video/texture.js +1 -1
  44. package/src/video/webgl/buffer/vertex.js +0 -3
  45. package/src/video/webgl/glshader.js +0 -2
  46. package/src/video/webgl/webgl_renderer.js +46 -19
@@ -15,174 +15,169 @@ var instance_counter = 0;
15
15
  * @namespace pool
16
16
  */
17
17
 
18
- var pool = {
19
-
20
- /**
21
- * register an object to the pool. <br>
22
- * Pooling must be set to true if more than one such objects will be created. <br>
23
- * (Note: for an object to be poolable, it must implements a `onResetEvent` method)
24
- * @function pool.register
25
- * @param {string} className as defined in the Name field of the Object Properties (in Tiled)
26
- * @param {object} classObj corresponding Class to be instantiated
27
- * @param {boolean} [recycling=false] enables object recycling for the specified class
28
- * @example
29
- * // implement CherryEntity
30
- * class CherryEntity extends Spritesheet {
31
- * onResetEvent() {
32
- * // reset object mutable properties
33
- * this.lifeBar = 100;
34
- * }
35
- * };
36
- * // add our users defined entities in the object pool and enable object recycling
37
- * me.pool.register("cherryentity", CherryEntity, true);
38
- */
39
- register(className, classObj, recycling = false) {
40
- if (typeof (classObj) !== "undefined") {
41
- objectClass[className] = {
42
- "class" : classObj,
43
- "pool" : (recycling ? [] : undefined)
44
- };
45
- } else {
46
- throw new Error("Cannot register object '" + className + "', invalid class");
47
- }
48
- },
18
+ /**
19
+ * register an object to the pool. <br>
20
+ * Pooling must be set to true if more than one such objects will be created. <br>
21
+ * (Note: for an object to be poolable, it must implements a `onResetEvent` method)
22
+ * @function pool.register
23
+ * @param {string} className as defined in the Name field of the Object Properties (in Tiled)
24
+ * @param {object} classObj corresponding Class to be instantiated
25
+ * @param {boolean} [recycling=false] enables object recycling for the specified class
26
+ * @example
27
+ * // implement CherryEntity
28
+ * class CherryEntity extends Spritesheet {
29
+ * onResetEvent() {
30
+ * // reset object mutable properties
31
+ * this.lifeBar = 100;
32
+ * }
33
+ * };
34
+ * // add our users defined entities in the object pool and enable object recycling
35
+ * me.pool.register("cherryentity", CherryEntity, true);
36
+ */
37
+ export function register(className, classObj, recycling = false) {
38
+ if (typeof (classObj) !== "undefined") {
39
+ objectClass[className] = {
40
+ "class" : classObj,
41
+ "pool" : (recycling ? [] : undefined)
42
+ };
43
+ } else {
44
+ throw new Error("Cannot register object '" + className + "', invalid class");
45
+ }
46
+ };
49
47
 
50
- /**
51
- * Pull a new instance of the requested object (if added into the object pool)
52
- * @function pool.pull
53
- * @param {string} name as used in {@link pool.register}
54
- * @param {object} [...arguments] arguments to be passed when instantiating/reinitializing the object
55
- * @returns {object} the instance of the requested object
56
- * @example
57
- * me.pool.register("bullet", BulletEntity, true);
58
- * me.pool.register("enemy", EnemyEntity, true);
59
- * // ...
60
- * // when we need to manually create a new bullet:
61
- * var bullet = me.pool.pull("bullet", x, y, direction);
62
- * // ...
63
- * // params aren't a fixed number
64
- * // when we need new enemy we can add more params, that the object construct requires:
65
- * var enemy = me.pool.pull("enemy", x, y, direction, speed, power, life);
66
- * // ...
67
- * // when we want to destroy existing object, the remove
68
- * // function will ensure the object can then be reallocated later
69
- * me.game.world.removeChild(enemy);
70
- * me.game.world.removeChild(bullet);
71
- */
72
- pull(name) {
73
- var args = new Array(arguments.length);
74
- for (var i = 0; i < arguments.length; i++) {
75
- args[i] = arguments[i];
76
- }
77
- var className = objectClass[name];
78
- if (className) {
79
- var proto = className["class"],
80
- poolArray = className.pool,
81
- obj;
48
+ /**
49
+ * Pull a new instance of the requested object (if added into the object pool)
50
+ * @function pool.pull
51
+ * @param {string} name as used in {@link pool.register}
52
+ * @param {object} [...arguments] arguments to be passed when instantiating/reinitializing the object
53
+ * @returns {object} the instance of the requested object
54
+ * @example
55
+ * me.pool.register("bullet", BulletEntity, true);
56
+ * me.pool.register("enemy", EnemyEntity, true);
57
+ * // ...
58
+ * // when we need to manually create a new bullet:
59
+ * var bullet = me.pool.pull("bullet", x, y, direction);
60
+ * // ...
61
+ * // params aren't a fixed number
62
+ * // when we need new enemy we can add more params, that the object construct requires:
63
+ * var enemy = me.pool.pull("enemy", x, y, direction, speed, power, life);
64
+ * // ...
65
+ * // when we want to destroy existing object, the remove
66
+ * // function will ensure the object can then be reallocated later
67
+ * me.game.world.removeChild(enemy);
68
+ * me.game.world.removeChild(bullet);
69
+ */
70
+ export function pull(name) {
71
+ var args = new Array(arguments.length);
72
+ for (var i = 0; i < arguments.length; i++) {
73
+ args[i] = arguments[i];
74
+ }
75
+ var className = objectClass[name];
76
+ if (className) {
77
+ var proto = className["class"],
78
+ poolArray = className.pool,
79
+ obj;
82
80
 
83
- if (poolArray && ((obj = poolArray.pop()))) {
84
- // pull an existing instance from the pool
85
- args.shift();
86
- // call the object onResetEvent function if defined
87
- if (typeof(obj.onResetEvent) === "function") {
88
- obj.onResetEvent.apply(obj, args);
89
- }
90
- instance_counter--;
91
- }
92
- else {
93
- // create a new instance
94
- args[0] = proto;
95
- obj = new (proto.bind.apply(proto, args))();
96
- if (poolArray) {
97
- obj.className = name;
98
- }
81
+ if (poolArray && ((obj = poolArray.pop()))) {
82
+ // pull an existing instance from the pool
83
+ args.shift();
84
+ // call the object onResetEvent function if defined
85
+ if (typeof(obj.onResetEvent) === "function") {
86
+ obj.onResetEvent.apply(obj, args);
99
87
  }
100
- return obj;
88
+ instance_counter--;
101
89
  }
102
- throw new Error("Cannot instantiate object of type '" + name + "'");
103
- },
104
-
105
- /**
106
- * purge the object pool from any inactive object <br>
107
- * Object pooling must be enabled for this function to work<br>
108
- * note: this will trigger the garbage collector
109
- * @function pool.purge
110
- */
111
- purge() {
112
- for (var className in objectClass) {
113
- if (objectClass[className]) {
114
- objectClass[className].pool = [];
90
+ else {
91
+ // create a new instance
92
+ args[0] = proto;
93
+ obj = new (proto.bind.apply(proto, args))();
94
+ if (poolArray) {
95
+ obj.className = name;
115
96
  }
116
97
  }
117
- instance_counter = 0;
118
- },
98
+ return obj;
99
+ }
100
+ throw new Error("Cannot instantiate object of type '" + name + "'");
101
+ };
119
102
 
120
- /**
121
- * Push back an object instance into the object pool <br>
122
- * Object pooling for the object class must be enabled,
123
- * and object must have been instantiated using {@link pool#pull},
124
- * otherwise this function won't work
125
- * @function pool.push
126
- * @throws will throw an error if the object cannot be recycled
127
- * @param {object} obj instance to be recycled
128
- * @param {boolean} [throwOnError=true] throw an exception if the object cannot be recycled
129
- * @returns {boolean} true if the object was successfully recycled in the object pool
130
- */
131
- push(obj, throwOnError = true) {
132
- if (!this.poolable(obj)) {
133
- if (throwOnError === true ) {
134
- throw new Error("me.pool: object " + obj + " cannot be recycled");
135
- } else {
136
- return false;
137
- }
103
+ /**
104
+ * purge the object pool from any inactive object <br>
105
+ * Object pooling must be enabled for this function to work<br>
106
+ * note: this will trigger the garbage collector
107
+ * @function pool.purge
108
+ */
109
+ export function purge() {
110
+ for (var className in objectClass) {
111
+ if (objectClass[className]) {
112
+ objectClass[className].pool = [];
138
113
  }
114
+ }
115
+ instance_counter = 0;
116
+ };
139
117
 
140
- // store back the object instance for later recycling
141
- objectClass[obj.className].pool.push(obj);
142
- instance_counter++;
118
+ /**
119
+ * Push back an object instance into the object pool <br>
120
+ * Object pooling for the object class must be enabled,
121
+ * and object must have been instantiated using {@link pool#pull},
122
+ * otherwise this function won't work
123
+ * @function pool.push
124
+ * @throws will throw an error if the object cannot be recycled
125
+ * @param {object} obj instance to be recycled
126
+ * @param {boolean} [throwOnError=true] throw an exception if the object cannot be recycled
127
+ * @returns {boolean} true if the object was successfully recycled in the object pool
128
+ */
129
+ export function push(obj, throwOnError = true) {
130
+ if (!poolable(obj)) {
131
+ if (throwOnError === true ) {
132
+ throw new Error("me.pool: object " + obj + " cannot be recycled");
133
+ } else {
134
+ return false;
135
+ }
136
+ }
143
137
 
144
- return true;
145
- },
138
+ // store back the object instance for later recycling
139
+ objectClass[obj.className].pool.push(obj);
140
+ instance_counter++;
146
141
 
147
- /**
148
- * Check if an object with the provided name is registered
149
- * @function pool.exists
150
- * @param {string} name of the registered object class
151
- * @returns {boolean} true if the classname is registered
152
- */
153
- exists(name) {
154
- return name in objectClass;
155
- },
142
+ return true;
143
+ };
156
144
 
157
- /**
158
- * Check if an object is poolable
159
- * (was properly registered with the recycling feature enable)
160
- * @function pool.poolable
161
- * @see pool.register
162
- * @param {object} obj object to be checked
163
- * @returns {boolean} true if the object is poolable
164
- * @example
165
- * if (!me.pool.poolable(myCherryEntity)) {
166
- * // object was not properly registered
167
- * }
168
- */
169
- poolable(obj) {
170
- var className = obj.className;
171
- return (typeof className !== "undefined") &&
172
- (typeof obj.onResetEvent === "function") &&
173
- (className in objectClass) &&
174
- (objectClass[className].pool !== "undefined");
145
+ /**
146
+ * Check if an object with the provided name is registered
147
+ * @function pool.exists
148
+ * @param {string} name of the registered object class
149
+ * @returns {boolean} true if the classname is registered
150
+ */
151
+ export function exists(name) {
152
+ return name in objectClass;
153
+ };
175
154
 
176
- },
155
+ /**
156
+ * Check if an object is poolable
157
+ * (was properly registered with the recycling feature enable)
158
+ * @function pool.poolable
159
+ * @see pool.register
160
+ * @param {object} obj object to be checked
161
+ * @returns {boolean} true if the object is poolable
162
+ * @example
163
+ * if (!me.pool.poolable(myCherryEntity)) {
164
+ * // object was not properly registered
165
+ * }
166
+ */
167
+ export function poolable(obj) {
168
+ var className = obj.className;
169
+ return (typeof className !== "undefined") &&
170
+ (typeof obj.onResetEvent === "function") &&
171
+ (className in objectClass) &&
172
+ (objectClass[className].pool !== "undefined");
177
173
 
178
- /**
179
- * returns the amount of object instance currently in the pool
180
- * @function pool.getInstanceCount
181
- * @returns {number} amount of object instance
182
- */
183
- getInstanceCount() {
184
- return instance_counter;
185
- }
186
174
  };
187
175
 
188
- export default pool;
176
+ /**
177
+ * returns the amount of object instance currently in the pool
178
+ * @function pool.getInstanceCount
179
+ * @returns {number} amount of object instance
180
+ */
181
+ export function getInstanceCount() {
182
+ return instance_counter;
183
+ };
@@ -1,35 +1,9 @@
1
1
  import Color from "./../math/color.js";
2
2
  import * as stringUtil from "./../utils/string.js";
3
- import pool from "./../system/pooling.js";
3
+ import * as pool from "./../system/pooling.js";
4
4
  import loader from "./../loader/loader.js";
5
5
  import Renderable from "./../renderable/renderable.js";
6
-
7
- /**
8
- * Measures the width of a single line of text, does not account for \n
9
- * @ignore
10
- */
11
- var measureTextWidth = function(font, text) {
12
- var characters = text.split("");
13
- var width = 0;
14
- var lastGlyph = null;
15
- for (var i = 0; i < characters.length; i++) {
16
- var ch = characters[i].charCodeAt(0);
17
- var glyph = font.fontData.glyphs[ch];
18
- var kerning = (lastGlyph && lastGlyph.kerning) ? lastGlyph.getKerning(ch) : 0;
19
- width += (glyph.xadvance + kerning) * font.fontScale.x;
20
- lastGlyph = glyph;
21
- }
22
-
23
- return width;
24
- };
25
-
26
- /**
27
- * Measures the height of a single line of text, does not account for \n
28
- * @ignore
29
- */
30
- var measureTextHeight = function(font) {
31
- return font.fontData.capHeight * font.lineHeight * font.fontScale.y;
32
- };
6
+ import TextMetrics from "./textmetrics.js";
33
7
 
34
8
  /**
35
9
  * @classdesc
@@ -50,6 +24,7 @@ class BitmapText extends Renderable {
50
24
  * @param {string} [settings.textBaseline="top"] the text baseline
51
25
  * @param {number} [settings.lineHeight=1.0] line spacing height
52
26
  * @param {Vector2d} [settings.anchorPoint={x:0.0, y:0.0}] anchor point to draw the text at
27
+ * @param {number} [settings.wordWrapWidth] the maximum length in CSS pixel for a single segment of text
53
28
  * @param {(string|string[])} [settings.text] a string, or an array of strings
54
29
  * @example
55
30
  * // Use me.loader.preload or me.loader.load to load assets
@@ -75,8 +50,6 @@ class BitmapText extends Renderable {
75
50
  * @public
76
51
  * @type {string}
77
52
  * @default "left"
78
- * @name textAlign
79
- * @memberof BitmapText
80
53
  */
81
54
  this.textAlign = settings.textAlign || "left";
82
55
 
@@ -86,8 +59,6 @@ class BitmapText extends Renderable {
86
59
  * @public
87
60
  * @type {string}
88
61
  * @default "top"
89
- * @name textBaseline
90
- * @memberof BitmapText
91
62
  */
92
63
  this.textBaseline = settings.textBaseline || "top";
93
64
 
@@ -97,11 +68,18 @@ class BitmapText extends Renderable {
97
68
  * @public
98
69
  * @type {number}
99
70
  * @default 1.0
100
- * @name lineHeight
101
- * @memberof BitmapText
102
71
  */
103
72
  this.lineHeight = settings.lineHeight || 1.0;
104
73
 
74
+ /**
75
+ * the maximum length in CSS pixel for a single segment of text.
76
+ * (use -1 to disable word wrapping)
77
+ * @public
78
+ * @type {number}
79
+ * @default -1
80
+ */
81
+ this.wordWrapWidth = settings.wordWrapWidth || -1;
82
+
105
83
  /**
106
84
  * the text to be displayed
107
85
  * @private
@@ -161,15 +139,15 @@ class BitmapText extends Renderable {
161
139
  this.anchorPoint.set(0, 0);
162
140
  }
163
141
 
142
+ // instance to text metrics functions
143
+ this.metrics = new TextMetrics(this);
144
+
164
145
  // set the text
165
146
  this.setText(settings.text);
166
147
  }
167
148
 
168
149
  /**
169
150
  * change the font settings
170
- * @name set
171
- * @memberof BitmapText.prototype
172
- * @function
173
151
  * @param {string} textAlign ("left", "center", "right")
174
152
  * @param {number} [scale]
175
153
  * @returns {BitmapText} this object for chaining
@@ -187,17 +165,10 @@ class BitmapText extends Renderable {
187
165
 
188
166
  /**
189
167
  * change the text to be displayed
190
- * @name setText
191
- * @memberof BitmapText.prototype
192
- * @function
193
168
  * @param {number|string|string[]} value a string, or an array of strings
194
169
  * @returns {BitmapText} this object for chaining
195
170
  */
196
- setText(value) {
197
- if (typeof value === "undefined") {
198
- value = "";
199
- }
200
-
171
+ setText(value = "") {
201
172
  if (this._text.toString() !== value.toString()) {
202
173
  if (!Array.isArray(value)) {
203
174
  this._text = ("" + value).split("\n");
@@ -207,6 +178,12 @@ class BitmapText extends Renderable {
207
178
  this.isDirty = true;
208
179
  }
209
180
 
181
+ if (this._text.length > 0 && this.wordWrapWidth > 0) {
182
+ this._text = this.metrics.wordWrap(this._text, this.wordWrapWidth);
183
+ }
184
+
185
+ this.getBounds().addBounds(this.metrics.measureText(this._text), true);
186
+
210
187
  return this;
211
188
  }
212
189
 
@@ -214,9 +191,7 @@ class BitmapText extends Renderable {
214
191
  * defines the color used to tint the bitmap text
215
192
  * @public
216
193
  * @type {Color}
217
- * @name fillStyle
218
194
  * @see Renderable#tint
219
- * @memberof BitmapText
220
195
  */
221
196
  get fillStyle() {
222
197
  return this.tint;
@@ -227,14 +202,14 @@ class BitmapText extends Renderable {
227
202
 
228
203
  /**
229
204
  * change the font display size
230
- * @name resize
231
- * @memberof BitmapText.prototype
232
- * @function
233
205
  * @param {number} scale ratio
234
206
  * @returns {BitmapText} this object for chaining
235
207
  */
236
208
  resize(scale) {
237
209
  this.fontScale.set(scale, scale);
210
+
211
+ this.getBounds().addBounds(this.metrics.measureText(this._text), true);
212
+
238
213
  // clear the cache text to recalculate bounds
239
214
  this.isDirty = true;
240
215
 
@@ -243,44 +218,15 @@ class BitmapText extends Renderable {
243
218
 
244
219
  /**
245
220
  * measure the given text size in pixels
246
- * @name measureText
247
- * @memberof BitmapText.prototype
248
- * @function
249
221
  * @param {string} [text]
250
- * @param {Rect} [ret] a object in which to store the text metrics
251
222
  * @returns {TextMetrics} a TextMetrics object with two properties: `width` and `height`, defining the output dimensions
252
223
  */
253
- measureText(text, ret) {
254
- text = text || this._text;
255
-
256
- var stringHeight = measureTextHeight(this);
257
- var textMetrics = ret || this.getBounds();
258
- var strings = typeof text === "string" ? ("" + (text)).split("\n") : text;
259
-
260
- textMetrics.height = textMetrics.width = 0;
261
-
262
- for (var i = 0; i < strings.length; i++) {
263
- textMetrics.width = Math.max(measureTextWidth(this, strings[i]), textMetrics.width);
264
- textMetrics.height += stringHeight;
265
- }
266
- return textMetrics;
267
- }
268
-
269
- /**
270
- * @ignore
271
- */
272
- update(/* dt */) {
273
- if (this.isDirty === true) {
274
- this.measureText();
275
- }
276
- return this.isDirty;
224
+ measureText(text = this._text) {
225
+ return this.metrics.measureText(text);
277
226
  }
278
227
 
279
228
  /**
280
229
  * draw the bitmap font
281
- * @name draw
282
- * @memberof BitmapText.prototype
283
- * @function
284
230
  * @param {CanvasRenderer|WebGLRenderer} renderer Reference to the destination renderer instance
285
231
  * @param {string} [text]
286
232
  * @param {number} [x]
@@ -295,8 +241,6 @@ class BitmapText extends Renderable {
295
241
  if (typeof this.ancestor === "undefined") {
296
242
  // update cache
297
243
  this.setText(text);
298
- // force update bounds
299
- this.update(0);
300
244
  renderer.setGlobalAlpha(_alpha * this.getOpacity());
301
245
  } else {
302
246
  // added directly to an object container
@@ -305,14 +249,14 @@ class BitmapText extends Renderable {
305
249
  }
306
250
 
307
251
  var lX = x;
308
- var stringHeight = measureTextHeight(this);
252
+ var stringHeight = this.metrics.lineHeight();
309
253
  var maxWidth = 0;
310
254
 
311
255
  for (var i = 0; i < this._text.length; i++) {
312
256
  x = lX;
313
257
  var string = stringUtil.trimRight(this._text[i]);
314
258
  // adjust x pos based on alignment value
315
- var stringWidth = measureTextWidth(this, string);
259
+ var stringWidth = this.metrics.lineWidth(string);
316
260
  switch (this.textAlign) {
317
261
  case "right":
318
262
  x -= stringWidth;
@@ -403,10 +347,10 @@ class BitmapText extends Renderable {
403
347
  pool.push(this.fontData);
404
348
  this.fontData = undefined;
405
349
  this._text.length = 0;
350
+ this.metrics = undefined;
406
351
  super.destroy();
407
352
  }
408
353
 
409
354
  };
410
355
 
411
-
412
356
  export default BitmapText;