melonjs 13.0.0 → 13.2.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "melonjs",
3
- "version": "13.0.0",
3
+ "version": "13.2.0",
4
4
  "description": "melonJS Game Engine",
5
5
  "homepage": "http://www.melonjs.org/",
6
6
  "keywords": [
@@ -52,7 +52,7 @@
52
52
  ],
53
53
  "dependencies": {
54
54
  "@teppeis/multimaps": "^2.0.0",
55
- "core-js": "^3.23.5",
55
+ "core-js": "^3.24.1",
56
56
  "earcut": "2.2.4",
57
57
  "eventemitter3": "^4.0.7",
58
58
  "howler": "2.2.3"
@@ -60,22 +60,22 @@
60
60
  "devDependencies": {
61
61
  "@melonjs/webdoc-theme": "^1.1.1",
62
62
  "@rollup/plugin-buble": "^0.21.3",
63
- "@rollup/plugin-commonjs": "^22.0.1",
63
+ "@rollup/plugin-commonjs": "^22.0.2",
64
64
  "@rollup/plugin-image": "^2.1.1",
65
65
  "@rollup/plugin-node-resolve": "^13.3.0",
66
66
  "@rollup/plugin-replace": "^4.0.0",
67
67
  "@types/offscreencanvas": "^2019.7.0",
68
68
  "@webdoc/cli": "^2.0.0",
69
- "del-cli": "^4.0.1",
70
- "eslint": "^8.20.0",
71
- "jasmine-core": "^4.2.0",
69
+ "del-cli": "^5.0.0",
70
+ "eslint": "^8.22.0",
71
+ "jasmine-core": "^4.3.0",
72
72
  "karma": "^6.4.0",
73
73
  "karma-chrome-launcher": "^3.1.1",
74
74
  "karma-coverage": "^2.2.0",
75
75
  "karma-html-detailed-reporter": "^2.1.0",
76
76
  "karma-jasmine": "^5.1.0",
77
77
  "karma-nyan-reporter": "0.2.5",
78
- "rollup": "^2.77.0",
78
+ "rollup": "^2.78.1",
79
79
  "rollup-plugin-bundle-size": "^1.0.3",
80
80
  "rollup-plugin-string": "^3.0.0",
81
81
  "terser": "^5.14.2",
@@ -0,0 +1,80 @@
1
+ /**
2
+ * @classdesc
3
+ * represents a point in a 2d space
4
+ */
5
+ class Point {
6
+ constructor(x = 0, y = 0) {
7
+ /**
8
+ * the position of the point on the horizontal axis
9
+ * @public
10
+ * @type {Number}
11
+ * @default 0
12
+ */
13
+ this.x = x;
14
+
15
+ /**
16
+ * the position of the point on the vertical axis
17
+ * @public
18
+ * @type {Number}
19
+ * @default 0
20
+ */
21
+ this.y = y;
22
+ }
23
+
24
+ /** @ignore */
25
+ onResetEvent(x = 0, y = 0) {
26
+ this.set(x, y);
27
+ }
28
+
29
+ /**
30
+ * set the Point x and y properties to the given values
31
+ * @param {number} x
32
+ * @param {number} y
33
+ * @returns {Point} Reference to this object for method chaining
34
+ */
35
+ set(x = 0, y = 0) {
36
+ this.x = x;
37
+ this.y = y;
38
+ return this;
39
+ }
40
+
41
+ /**
42
+ * return true if the two points are the same
43
+ * @name equals
44
+ * @memberof Point
45
+ * @method
46
+ * @param {Point} point
47
+ * @returns {boolean}
48
+ */
49
+ /**
50
+ * return true if this point is equal to the given values
51
+ * @name equals
52
+ * @memberof Point
53
+ * @param {number} x
54
+ * @param {number} y
55
+ * @returns {boolean}
56
+ */
57
+ equals() {
58
+ var _x, _y;
59
+ if (arguments.length === 2) {
60
+ // x, y
61
+ _x = arguments[0];
62
+ _y = arguments[1];
63
+ } else {
64
+ // point
65
+ _x = arguments[0].x;
66
+ _y = arguments[0].y;
67
+ }
68
+ return ((this.x === _x) && (this.y === _y));
69
+ }
70
+
71
+ /**
72
+ * clone this Point
73
+ * @name clone
74
+ * @returns {Point} new Point
75
+ */
76
+ clone() {
77
+ return new Point(this.x, this.y);
78
+ }
79
+ }
80
+ export default Point;
package/src/index.js CHANGED
@@ -30,6 +30,7 @@ import Matrix3d from "./math/matrix3.js";
30
30
  import Polygon from "./geometries/poly.js";
31
31
  import Line from "./geometries/line.js";
32
32
  import Ellipse from "./geometries/ellipse.js";
33
+ import Point from "./geometries/point.js";
33
34
  import Rect from "./geometries/rectangle.js";
34
35
  import RoundRect from "./geometries/roundrect.js";
35
36
  import QuadTree from "./physics/quadtree.js";
@@ -119,6 +120,7 @@ export {
119
120
  Polygon,
120
121
  Line,
121
122
  Ellipse,
123
+ Point,
122
124
  Rect,
123
125
  RoundRect,
124
126
  Tween,
@@ -226,6 +228,7 @@ export function boot() {
226
228
  pool.register("me.RoundRect", RoundRect, true);
227
229
  pool.register("me.Polygon", Polygon, true);
228
230
  pool.register("me.Line", Line, true);
231
+ pool.register("me.Point", Point, true);
229
232
  pool.register("me.Ellipse", Ellipse, true);
230
233
  pool.register("me.Bounds", Bounds, true);
231
234
 
@@ -255,6 +258,7 @@ export function boot() {
255
258
  pool.register("RoundRect", RoundRect, true);
256
259
  pool.register("Polygon", Polygon, true);
257
260
  pool.register("Line", Line, true);
261
+ pool.register("Point", Point, true);
258
262
  pool.register("Ellipse", Ellipse, true);
259
263
  pool.register("Bounds", Bounds, true);
260
264
  pool.register("CanvasTexture", CanvasTexture, true);
@@ -125,7 +125,7 @@ function enablePointerEvent() {
125
125
 
126
126
  if (pointerEventTarget === null) {
127
127
  // default pointer event target
128
- pointerEventTarget = renderer.getScreenCanvas();
128
+ pointerEventTarget = renderer.getCanvas();
129
129
  }
130
130
 
131
131
  if (device.pointerEvent) {
@@ -556,7 +556,7 @@ export var throttlingInterval;
556
556
  */
557
557
  export function globalToLocal(x, y, v) {
558
558
  v = v || pool.pull("Vector2d");
559
- var rect = device.getElementBounds(renderer.getScreenCanvas());
559
+ var rect = device.getElementBounds(renderer.getCanvas());
560
560
  var pixelRatio = globalThis.devicePixelRatio || 1;
561
561
  x -= rect.left + (globalThis.pageXOffset || 0);
562
562
  y -= rect.top + (globalThis.pageYOffset || 0);
@@ -62,7 +62,6 @@ Object.defineProperty(Renderer.prototype, "Texture", {
62
62
  }
63
63
  });
64
64
 
65
-
66
65
  /**
67
66
  * @classdesc
68
67
  * Used to make a game entity draggable
@@ -100,3 +99,30 @@ export class DroptargetEntity extends DropTarget {
100
99
  super(x, y, settings.width, settings.height);
101
100
  }
102
101
  }
102
+
103
+ /**
104
+ * return a reference to the screen canvas
105
+ * @name getScreenCanvas
106
+ * @memberof Renderer
107
+ * @returns {HTMLCanvasElement}
108
+ * @deprecated since 13.1.0
109
+ * @see getCanvas();
110
+ */
111
+ Renderer.prototype.getScreenCanvas = function() {
112
+ warning("getScreenCanvas", "getCanvas", "13.1.0");
113
+ return this.getCanvas();
114
+ };
115
+
116
+ /**
117
+ * return a reference to the screen canvas corresponding 2d Context<br>
118
+ * (will return buffered context if double buffering is enabled, or a reference to the Screen Context)
119
+ * @name getScreenContext
120
+ * @memberof Renderer
121
+ * @returns {CanvasRenderingContext2D}
122
+ * @deprecated since 13.1.0
123
+ * @see getContext();
124
+ */
125
+ Renderer.prototype.getScreenContext = function() {
126
+ warning("getScreenContext", "getContext", "13.1.0");
127
+ return this.getContext();
128
+ };
@@ -49,6 +49,16 @@ export default class TMXGroup {
49
49
  */
50
50
  this.tintcolor = data.tintcolor;
51
51
 
52
+
53
+ /**
54
+ * the group class
55
+ * @public
56
+ * @type {string}
57
+ * @name class
58
+ * @memberof TMXGroup
59
+ */
60
+ this.class = data.class;
61
+
52
62
  /**
53
63
  * group z order
54
64
  * @public
@@ -138,6 +138,15 @@ class TMXLayer extends Renderable {
138
138
  */
139
139
  this.renderorder = data.renderorder || "right-down";
140
140
 
141
+ /**
142
+ * the layer class
143
+ * @public
144
+ * @type {string}
145
+ * @name class
146
+ * @name TMXLayer#class
147
+ */
148
+ this.class = data.class;
149
+
141
150
  // for displaying order
142
151
  this.pos.z = z;
143
152
 
@@ -99,20 +99,31 @@ export default class TMXObject {
99
99
  * object type
100
100
  * @public
101
101
  * @type {string}
102
+ * @deprecated since Tiled 1.9
103
+ * @see https://docs.mapeditor.org/en/stable/reference/tmx-changelog/#tiled-1-9
102
104
  * @name type
103
105
  * @memberof TMXObject
104
106
  */
105
107
  this.type = settings.type;
106
108
 
109
+ /**
110
+ * the object class
111
+ * @public
112
+ * @type {string}
113
+ * @name class
114
+ * @memberof TMXObject
115
+ */
116
+ this.class = typeof settings.class !== "undefined" ? settings.class : settings.type;
117
+
107
118
  /**
108
119
  * object text
109
120
  * @public
110
121
  * @type {object}
111
122
  * @see http://docs.mapeditor.org/en/stable/reference/tmx-map-format/#text
112
- * @name type
123
+ * @name text
113
124
  * @memberof TMXObject
114
125
  */
115
- this.type = settings.type;
126
+ this.text = undefined;
116
127
 
117
128
  /**
118
129
  * The rotation of the object in radians clockwise (defaults to 0)
@@ -159,6 +170,15 @@ export default class TMXObject {
159
170
  */
160
171
  this.isEllipse = false;
161
172
 
173
+ /**
174
+ * if true, the object is a Point
175
+ * @public
176
+ * @type {boolean}
177
+ * @name isPoint
178
+ * @memberof TMXObject
179
+ */
180
+ this.isPoint = false;
181
+
162
182
  /**
163
183
  * if true, the object is a Polygon
164
184
  * @public
@@ -182,12 +202,14 @@ export default class TMXObject {
182
202
  this.setTile(map.tilesets);
183
203
  }
184
204
  else {
185
- if (typeof(settings.ellipse) !== "undefined") {
205
+ if (typeof settings.ellipse !== "undefined") {
186
206
  this.isEllipse = true;
187
- } else if (typeof(settings.polygon) !== "undefined") {
207
+ } else if (typeof settings.point !== "undefined") {
208
+ this.isPoint = true;
209
+ } else if (typeof settings.polygon !== "undefined") {
188
210
  this.points = settings.polygon;
189
211
  this.isPolygon = true;
190
- } else if (typeof(settings.polyline) !== "undefined") {
212
+ } else if (typeof settings.polyline !== "undefined") {
191
213
  this.points = settings.polyline;
192
214
  this.isPolyLine = true;
193
215
  }
@@ -261,8 +283,9 @@ export default class TMXObject {
261
283
  this.width,
262
284
  this.height
263
285
  )).rotate(this.rotation));
286
+ } else if (this.isPoint === true) {
287
+ shapes.push(pool.pull("Point", this.x, this.y));
264
288
  } else {
265
-
266
289
  // add a polygon
267
290
  if (this.isPolygon === true) {
268
291
  var _polygon = pool.pull("Polygon", 0, 0, this.points);
@@ -271,10 +294,8 @@ export default class TMXObject {
271
294
  throw new Error("collision polygones in Tiled should be defined as Convex");
272
295
  }
273
296
  shapes.push(_polygon.rotate(this.rotation));
274
- }
275
297
 
276
- // add a polyline
277
- else if (this.isPolyLine === true) {
298
+ } else if (this.isPolyLine === true) {
278
299
  var p = this.points;
279
300
  var p1, p2;
280
301
  var segments = p.length - 1;
@@ -306,7 +327,9 @@ export default class TMXObject {
306
327
  // Apply isometric projection
307
328
  if (this.orientation === "isometric") {
308
329
  for (i = 0; i < shapes.length; i++) {
309
- shapes[i].toIso();
330
+ if (typeof shapes[i].toIso === "function") {
331
+ shapes[i].toIso();
332
+ }
310
333
  }
311
334
  }
312
335
 
@@ -204,6 +204,16 @@ class TMXTileMap {
204
204
  */
205
205
  this.tiledversion = data.tiledversion;
206
206
 
207
+
208
+ /**
209
+ * The map class.
210
+ * @public
211
+ * @type {string}
212
+ * @name TMXTileMap#class
213
+ */
214
+ this.class = data.class;
215
+
216
+
207
217
  // tilesets for this map
208
218
  this.tilesets = null;
209
219
 
@@ -545,6 +555,8 @@ class TMXTileMap {
545
555
  obj.anchorPoint.set(0, 0);
546
556
  obj.name = settings.name;
547
557
  obj.type = settings.type;
558
+ // for backward compatibility
559
+ obj.class = settings.class || settings.type;
548
560
  obj.id = settings.id;
549
561
  obj.body = new Body(obj, shape);
550
562
  obj.body.setStatic(true);
@@ -62,6 +62,14 @@ class TMXTileset {
62
62
  */
63
63
  this.isCollection = false;
64
64
 
65
+ /**
66
+ * the tileset class
67
+ * @public
68
+ * @type {boolean}
69
+ * @name TMXTileset#class
70
+ */
71
+ this.class = tileset.class;
72
+
65
73
  /**
66
74
  * Tileset animations
67
75
  * @private
package/src/math/color.js CHANGED
@@ -2,10 +2,19 @@ import { clamp, random } from "./math.js";
2
2
  import pool from "./../system/pooling.js";
3
3
 
4
4
  // convert a give color component to it hexadecimal value
5
- var toHex = function (component) {
5
+ function toHex(component) {
6
6
  return "0123456789ABCDEF".charAt((component - (component % 16)) >> 4) + "0123456789ABCDEF".charAt(component % 16);
7
7
  };
8
8
 
9
+ function hue2rgb(p, q, t) {
10
+ if (t < 0) t += 1;
11
+ if (t > 1) t -= 1;
12
+ if (t < 1/6) return p + (q - p) * 6 * t;
13
+ if (t < 1/2) return q;
14
+ if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
15
+ return p;
16
+ }
17
+
9
18
  const rgbaRx = /^rgba?\((\d+), ?(\d+), ?(\d+)(, ?([\d\.]+))?\)$/;
10
19
  const hex3Rx = /^#([\da-fA-F])([\da-fA-F])([\da-fA-F])$/;
11
20
  const hex4Rx = /^#([\da-fA-F])([\da-fA-F])([\da-fA-F])([\da-fA-F])$/;
@@ -199,7 +208,6 @@ class Color {
199
208
  /**
200
209
  * Color Red Component [0 .. 255]
201
210
  * @type {number}
202
- * @memberof Color
203
211
  */
204
212
  get r() {
205
213
  return ~~(this.glArray[0] * 255);
@@ -213,7 +221,6 @@ class Color {
213
221
  /**
214
222
  * Color Green Component [0 .. 255]
215
223
  * @type {number}
216
- * @memberof Color
217
224
  */
218
225
  get g() {
219
226
  return ~~(this.glArray[1] * 255);
@@ -227,7 +234,6 @@ class Color {
227
234
  /**
228
235
  * Color Blue Component [0 .. 255]
229
236
  * @type {number}
230
- * @memberof Color
231
237
  */
232
238
  get b() {
233
239
  return ~~(this.glArray[2] * 255);
@@ -239,7 +245,6 @@ class Color {
239
245
  /**
240
246
  * Color Alpha Component [0.0 .. 1.0]
241
247
  * @type {number}
242
- * @memberof Color
243
248
  */
244
249
  get alpha() {
245
250
  return this.glArray[3];
@@ -252,8 +257,6 @@ class Color {
252
257
 
253
258
  /**
254
259
  * Set this color to the specified value.
255
- * @name setColor
256
- * @memberof Color
257
260
  * @param {number} r red component [0 .. 255]
258
261
  * @param {number} g green component [0 .. 255]
259
262
  * @param {number} b blue component [0 .. 255]
@@ -268,10 +271,59 @@ class Color {
268
271
  return this;
269
272
  }
270
273
 
274
+ /**
275
+ * set this color to the specified HSV value
276
+ * @param {number} h hue (a value from 0 to 1)
277
+ * @param {number} s saturation (a value from 0 to 1)
278
+ * @param {number} v value (a value from 0 to 1)
279
+ * @returns {Color} Reference to this object for method chaining
280
+ */
281
+ setHSV(h, s, v) {
282
+ var r, g, b;
283
+
284
+ var i = Math.floor(h * 6);
285
+ var f = h * 6 - i;
286
+ var p = v * (1 - s);
287
+ var q = v * (1 - f * s);
288
+ var t = v * (1 - (1 - f) * s);
289
+
290
+ switch (i % 6) {
291
+ case 0: r = v, g = t, b = p; break;
292
+ case 1: r = q, g = v, b = p; break;
293
+ case 2: r = p, g = v, b = t; break;
294
+ case 3: r = p, g = q, b = v; break;
295
+ case 4: r = t, g = p, b = v; break;
296
+ case 5: r = v, g = p, b = q; break;
297
+ }
298
+ return this.setColor(r * 255, g * 255, b * 255);
299
+ }
300
+
301
+ /**
302
+ * set this color to the specified HSL value
303
+ * @param {number} h hue (a value from 0 to 1)
304
+ * @param {number} s saturation (a value from 0 to 1)
305
+ * @param {number} l lightness (a value from 0 to 1)
306
+ * @returns {Color} Reference to this object for method chaining
307
+ */
308
+ setHSL(h, s, l) {
309
+ var r, g, b;
310
+
311
+ if (s === 0) {
312
+ r = g = b = l; // achromatic
313
+ } else {
314
+ var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
315
+ var p = 2 * l - q;
316
+
317
+ r = hue2rgb(p, q, h + 1/3);
318
+ g = hue2rgb(p, q, h);
319
+ b = hue2rgb(p, q, h - 1/3);
320
+ }
321
+
322
+ return this.setColor(r * 255, g * 255, b * 255);
323
+ }
324
+
271
325
  /**
272
326
  * Create a new copy of this color object.
273
- * @name clone
274
- * @memberof Color
275
327
  * @returns {Color} Reference to the newly cloned object
276
328
  */
277
329
  clone() {
@@ -280,8 +332,6 @@ class Color {
280
332
 
281
333
  /**
282
334
  * Copy a color object or CSS color into this one.
283
- * @name copy
284
- * @memberof Color
285
335
  * @param {Color|string} color
286
336
  * @returns {Color} Reference to this object for method chaining
287
337
  */
@@ -296,8 +346,6 @@ class Color {
296
346
 
297
347
  /**
298
348
  * Blend this color with the given one using addition.
299
- * @name add
300
- * @memberof Color
301
349
  * @param {Color} color
302
350
  * @returns {Color} Reference to this object for method chaining
303
351
  */
@@ -312,8 +360,6 @@ class Color {
312
360
 
313
361
  /**
314
362
  * Darken this color value by 0..1
315
- * @name darken
316
- * @memberof Color
317
363
  * @param {number} scale
318
364
  * @returns {Color} Reference to this object for method chaining
319
365
  */
@@ -328,8 +374,6 @@ class Color {
328
374
 
329
375
  /**
330
376
  * Linearly interpolate between this color and the given one.
331
- * @name lerp
332
- * @memberof Color
333
377
  * @param {Color} color
334
378
  * @param {number} alpha with alpha = 0 being this color, and alpha = 1 being the given one.
335
379
  * @returns {Color} Reference to this object for method chaining
@@ -345,8 +389,6 @@ class Color {
345
389
 
346
390
  /**
347
391
  * Lighten this color value by 0..1
348
- * @name lighten
349
- * @memberof Color
350
392
  * @param {number} scale
351
393
  * @returns {Color} Reference to this object for method chaining
352
394
  */
@@ -361,8 +403,6 @@ class Color {
361
403
 
362
404
  /**
363
405
  * Generate random r,g,b values for this color object
364
- * @name random
365
- * @memberof Color
366
406
  * @param {number} [min=0] minimum value for the random range
367
407
  * @param {number} [max=255] maxmium value for the random range
368
408
  * @returns {Color} Reference to this object for method chaining
@@ -386,8 +426,6 @@ class Color {
386
426
  /**
387
427
  * Return true if the r,g,b,a values of this color are equal with the
388
428
  * given one.
389
- * @name equals
390
- * @memberof Color
391
429
  * @param {Color} color
392
430
  * @returns {boolean}
393
431
  */
@@ -403,8 +441,6 @@ class Color {
403
441
  /**
404
442
  * Parse a CSS color string and set this color to the corresponding
405
443
  * r,g,b values
406
- * @name parseCSS
407
- * @memberof Color
408
444
  * @param {string} cssColor
409
445
  * @returns {Color} Reference to this object for method chaining
410
446
  */
@@ -420,8 +456,6 @@ class Color {
420
456
 
421
457
  /**
422
458
  * Parse an RGB or RGBA CSS color string
423
- * @name parseRGB
424
- * @memberof Color
425
459
  * @param {string} rgbColor
426
460
  * @returns {Color} Reference to this object for method chaining
427
461
  */
@@ -439,8 +473,6 @@ class Color {
439
473
  /**
440
474
  * Parse a Hex color ("#RGB", "#RGBA" or "#RRGGBB", "#RRGGBBAA" format) and set this color to
441
475
  * the corresponding r,g,b,a values
442
- * @name parseHex
443
- * @memberof Color
444
476
  * @param {string} hexColor
445
477
  * @param {boolean} [argb = false] true if format is #ARGB, or #AARRGGBB (as opposed to #RGBA or #RGGBBAA)
446
478
  * @returns {Color} Reference to this object for method chaining
@@ -498,12 +530,10 @@ class Color {
498
530
 
499
531
  /**
500
532
  * Pack this color into a Uint32 ARGB representation
501
- * @name toUint32
502
- * @memberof Color
503
533
  * @param {number} [alpha=1.0] alpha value [0.0 .. 1.0]
504
534
  * @returns {number}
505
535
  */
506
- toUint32(alpha = this.alpha) {
536
+ toUint32(alpha = 1.0) {
507
537
  var ur = this.r & 0xff;
508
538
  var ug = this.g & 0xff;
509
539
  var ub = this.b & 0xff;
@@ -514,8 +544,6 @@ class Color {
514
544
 
515
545
  /**
516
546
  * return an array representation of this object
517
- * @name toArray
518
- * @memberof Color
519
547
  * @returns {Float32Array}
520
548
  */
521
549
  toArray() {
@@ -524,9 +552,7 @@ class Color {
524
552
 
525
553
 
526
554
  /**
527
- * Get the color in "#RRGGBB" format
528
- * @name toHex
529
- * @memberof Color
555
+ * return the color in "#RRGGBB" format
530
556
  * @returns {string}
531
557
  */
532
558
  toHex() {
@@ -538,8 +564,6 @@ class Color {
538
564
 
539
565
  /**
540
566
  * Get the color in "#RRGGBBAA" format
541
- * @name toHex8
542
- * @memberof Color
543
567
  * @returns {string}
544
568
  */
545
569
  toHex8(alpha = this.alpha) {
@@ -551,8 +575,6 @@ class Color {
551
575
 
552
576
  /**
553
577
  * Get the color in "rgb(R,G,B)" format
554
- * @name toRGB
555
- * @memberof Color
556
578
  * @returns {string}
557
579
  */
558
580
  toRGB() {
@@ -568,8 +590,6 @@ class Color {
568
590
 
569
591
  /**
570
592
  * Get the color in "rgba(R,G,B,A)" format
571
- * @name toRGBA
572
- * @memberof Color
573
593
  * @param {number} [alpha=1.0] alpha value [0.0 .. 1.0]
574
594
  * @returns {string}
575
595
  */
@@ -388,8 +388,32 @@ class ObservableVector2d extends Vector2d {
388
388
  * @returns {ObservableVector2d} Reference to this object for method chaining
389
389
  */
390
390
  lerp(v, alpha) {
391
- this._x += ( v.x - this._x ) * alpha;
392
- this._y += ( v.y - this._y ) * alpha;
391
+ return this._set(
392
+ this._x + ( v.x - this._x ) * alpha,
393
+ this._y + ( v.y - this._y ) * alpha
394
+ );
395
+ }
396
+
397
+ /**
398
+ * interpolate the position of this vector towards the given one while nsure that the distance never exceeds the given step.
399
+ * @name moveTowards
400
+ * @memberof ObservableVector2d
401
+ * @param {Vector2d|ObservableVector2d} target
402
+ * @param {number} step the maximum step per iteration (Negative values will push the vector away from the target)
403
+ * @returns {ObservableVector2d} Reference to this object for method chaining
404
+ */
405
+ moveTowards(target, step) {
406
+ var angle = Math.atan2(target.y - this._y, target.x - this._x);
407
+
408
+ var distance = this.distance(target);
409
+
410
+ if (distance === 0 || (step >= 0 && distance <= step * step)) {
411
+ return target;
412
+ }
413
+
414
+ this._x += Math.cos(angle) * step;
415
+ this._y += Math.sin(angle) * step;
416
+
393
417
  return this;
394
418
  }
395
419