melonjs 11.0.0 → 13.1.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 (58) hide show
  1. package/LICENSE.md +1 -1
  2. package/README.md +6 -6
  3. package/dist/melonjs.js +22854 -22604
  4. package/dist/melonjs.min.js +5 -6
  5. package/dist/melonjs.module.d.ts +289 -284
  6. package/dist/melonjs.module.js +22427 -22175
  7. package/package.json +16 -16
  8. package/src/application/application.js +231 -0
  9. package/src/audio/audio.js +13 -7
  10. package/src/camera/camera2d.js +6 -6
  11. package/src/game.js +9 -232
  12. package/src/index.js +3 -3
  13. package/src/input/keyboard.js +2 -2
  14. package/src/input/pointer.js +4 -5
  15. package/src/input/pointerevent.js +10 -10
  16. package/src/lang/deprecated.js +27 -30
  17. package/src/level/level.js +2 -2
  18. package/src/level/tiled/TMXGroup.js +10 -0
  19. package/src/level/tiled/TMXLayer.js +11 -2
  20. package/src/level/tiled/TMXObject.js +13 -2
  21. package/src/level/tiled/TMXTileMap.js +15 -3
  22. package/src/level/tiled/TMXTileset.js +8 -0
  23. package/src/loader/loader.js +64 -28
  24. package/src/loader/loadingscreen.js +28 -115
  25. package/src/loader/melonjs_logo.png +0 -0
  26. package/src/math/color.js +62 -42
  27. package/src/math/observable_vector2.js +26 -2
  28. package/src/math/observable_vector3.js +32 -4
  29. package/src/math/vector2.js +23 -0
  30. package/src/math/vector3.js +26 -0
  31. package/src/physics/body.js +27 -51
  32. package/src/physics/detector.js +3 -3
  33. package/src/physics/quadtree.js +58 -29
  34. package/src/physics/world.js +32 -3
  35. package/src/polyfill/index.js +4 -0
  36. package/src/renderable/container.js +2 -2
  37. package/src/renderable/imagelayer.js +8 -8
  38. package/src/renderable/nineslicesprite.js +27 -1
  39. package/src/renderable/trigger.js +4 -4
  40. package/src/state/stage.js +1 -1
  41. package/src/state/state.js +50 -3
  42. package/src/system/device.js +814 -981
  43. package/src/system/event.js +2 -1
  44. package/src/system/platform.js +32 -0
  45. package/src/system/save.js +23 -14
  46. package/src/system/timer.js +12 -35
  47. package/src/text/bitmaptext.js +1 -2
  48. package/src/text/text.js +10 -14
  49. package/src/text/textmetrics.js +1 -2
  50. package/src/tweens/tween.js +6 -6
  51. package/src/utils/string.js +13 -24
  52. package/src/video/canvas/canvas_renderer.js +30 -65
  53. package/src/video/renderer.js +23 -30
  54. package/src/video/texture/canvas_texture.js +39 -3
  55. package/src/video/video.js +27 -25
  56. package/src/video/webgl/glshader.js +1 -1
  57. package/src/video/webgl/webgl_compositor.js +2 -2
  58. package/src/video/webgl/webgl_renderer.js +8 -20
@@ -1,10 +1,11 @@
1
- import { world, viewport } from "./../game.js";
1
+ import game from "./../game.js";
2
2
  import { renderer } from "./../video/video.js";
3
3
  import * as event from "./../system/event.js";
4
- import {nextPowerOfTwo} from "./../math/math.js";
5
- import pool from "./../system/pooling.js";
4
+ import Sprite from "./../renderable/sprite.js";
6
5
  import Renderable from "./../renderable/renderable.js";
7
6
  import Stage from "./../state/stage.js";
7
+ import loader from "./loader.js";
8
+ import logo_url from "./melonjs_logo.png";
8
9
 
9
10
 
10
11
  // a basic progress bar object
@@ -40,7 +41,7 @@ class ProgressBar extends Renderable {
40
41
  * draw function
41
42
  * @ignore
42
43
  */
43
- draw (renderer) {
44
+ draw(renderer, viewport) {
44
45
  // draw the progress bar
45
46
  renderer.setColor("black");
46
47
  renderer.fillRect(this.pos.x, viewport.centerY, renderer.getWidth(), this.barHeight / 2);
@@ -61,71 +62,6 @@ class ProgressBar extends Renderable {
61
62
 
62
63
  };
63
64
 
64
- // the melonJS Logo
65
- class IconLogo extends Renderable {
66
- /**
67
- * @ignore
68
- */
69
- constructor(x, y) {
70
- super(x, y, 100, 85);
71
-
72
- this.iconTexture = pool.pull("CanvasTexture",
73
- renderer.WebGLVersion > 1 ? this.width : nextPowerOfTwo(this.width),
74
- renderer.WebGLVersion > 1 ? this.height : nextPowerOfTwo(this.height),
75
- { offscreenCanvas: true }
76
- );
77
-
78
- var context = this.iconTexture.context;
79
-
80
- context.beginPath();
81
- context.moveTo(0.7, 48.9);
82
- context.bezierCurveTo(10.8, 68.9, 38.4, 75.8, 62.2, 64.5);
83
- context.bezierCurveTo(86.1, 53.1, 97.2, 27.7, 87.0, 7.7);
84
- context.lineTo(87.0, 7.7);
85
- context.bezierCurveTo(89.9, 15.4, 73.9, 30.2, 50.5, 41.4);
86
- context.bezierCurveTo(27.1, 52.5, 5.2, 55.8, 0.7, 48.9);
87
- context.lineTo(0.7, 48.9);
88
- context.closePath();
89
- context.fillStyle = "rgb(255, 255, 255)";
90
- context.fill();
91
-
92
- context.beginPath();
93
- context.moveTo(84.0, 7.0);
94
- context.bezierCurveTo(87.6, 14.7, 72.5, 30.2, 50.2, 41.6);
95
- context.bezierCurveTo(27.9, 53.0, 6.9, 55.9, 3.2, 48.2);
96
- context.bezierCurveTo(-0.5, 40.4, 14.6, 24.9, 36.9, 13.5);
97
- context.bezierCurveTo(59.2, 2.2, 80.3, -0.8, 84.0, 7.0);
98
- context.lineTo(84.0, 7.0);
99
- context.closePath();
100
- context.lineWidth = 5.3;
101
- context.strokeStyle = "rgb(255, 255, 255)";
102
- context.lineJoin = "miter";
103
- context.miterLimit = 4.0;
104
- context.stroke();
105
-
106
- this.anchorPoint.set(0.5, 0.5);
107
- }
108
-
109
- /**
110
- * @ignore
111
- */
112
- draw(renderer) {
113
- renderer.drawImage(this.iconTexture.canvas, renderer.getWidth() / 2, this.pos.y);
114
- }
115
-
116
- /**
117
- * Destroy function
118
- * @ignore
119
- */
120
- destroy() {
121
- // call the parent destroy method
122
- super.destroy(arguments);
123
- pool.push(this.iconTexture);
124
- this.iconTexture = undefined;
125
- }
126
- };
127
-
128
-
129
65
  /**
130
66
  * a default loading screen
131
67
  * @ignore
@@ -139,60 +75,37 @@ class DefaultLoadingScreen extends Stage {
139
75
  var barHeight = 8;
140
76
 
141
77
  // set a background color
142
- world.backgroundColor.parseCSS("#202020");
78
+ game.world.backgroundColor.parseCSS("#202020");
143
79
 
144
80
  // progress bar
145
- world.addChild(new ProgressBar(
81
+ game.world.addChild(new ProgressBar(
146
82
  0,
147
83
  renderer.getHeight() / 2,
148
84
  renderer.getWidth(),
149
85
  barHeight
150
86
  ), 1);
151
87
 
152
- // melonJS logo
153
- world.addChild(new IconLogo(
154
- renderer.getWidth() / 2,
155
- (renderer.getHeight() / 2) - (barHeight * 2) - 35
156
-
157
- ), 2);
158
-
159
- var logo1 = pool.pull("Text",
160
- renderer.getWidth() / 2,
161
- (renderer.getHeight() / 2) + 16, {
162
- font: "century gothic",
163
- size: 32,
164
- fillStyle: "white",
165
- textAlign: "left",
166
- textBaseline : "top",
167
- text: "melon",
168
- offScreenCanvas: renderer.WebGLVersion >= 1
169
- }
170
- );
171
- logo1.anchorPoint.set(0, 0);
172
-
173
- var logo2 = pool.pull("Text",
174
- renderer.getWidth() / 2,
175
- (renderer.getHeight() / 2) + 16, {
176
- font: "century gothic",
177
- size: 32,
178
- fillStyle: "#55aa00",
179
- textAlign: "left",
180
- textBaseline : "top",
181
- bold: true,
182
- text: "JS",
183
- offScreenCanvas: renderer.WebGLVersion >= 1
184
- }
185
- );
186
- logo2.anchorPoint.set(0, 0);
187
-
188
- // adjust position of both text
189
- var text_width = logo1.getBounds().width + logo2.getBounds().width;
190
- logo1.pos.x = renderer.getWidth() / 2 - text_width / 2;
191
- logo2.pos.x = logo1.pos.x + logo1.getBounds().width;
192
-
193
- // melonJS text
194
- world.addChild(logo1, 2);
195
- world.addChild(logo2, 2);
88
+ // load the melonJS logo
89
+ loader.load({name: "melonjs_logo", type: "image", src: logo_url}, () => {
90
+ // melonJS logo
91
+ game.world.addChild(new Sprite(
92
+ renderer.getWidth() / 2,
93
+ renderer.getHeight() / 2, {
94
+ image : "melonjs_logo",
95
+ framewidth : 256,
96
+ frameheight : 256
97
+ }), 2
98
+ );
99
+ });
100
+ }
101
+
102
+ /**
103
+ * Called by engine before deleting the object
104
+ * @ignore
105
+ */
106
+ onDestroyEvent() {
107
+ // cancel the callback
108
+ loader.unload({name: "melonjs_logo", type:"image"});
196
109
  }
197
110
  };
198
111
 
Binary file
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,8 +530,6 @@ 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
  */
@@ -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
 
@@ -465,10 +465,38 @@ class ObservableVector3d extends Vector3d {
465
465
  * @returns {ObservableVector3d} Reference to this object for method chaining
466
466
  */
467
467
  lerp(v, alpha) {
468
- this._x += ( v.x - this._x ) * alpha;
469
- this._y += ( v.y - this._y ) * alpha;
470
- this._z += ( v.z - this._z ) * alpha;
471
- return this;
468
+ return this._set(
469
+ this._x + ( v.x - this._x ) * alpha,
470
+ this._y + ( v.y - this._y ) * alpha,
471
+ this._z + ( v.z - this._z ) * alpha
472
+ );
473
+ }
474
+
475
+ /**
476
+ * interpolate the position of this vector on the x and y axis towards the given one while ensure that the distance never exceeds the given step.
477
+ * @name moveTowards
478
+ * @memberof ObservableVector3d
479
+ * @param {Vector2d|ObservableVector2d|Vector3d|ObservableVector3d} target
480
+ * @param {number} step the maximum step per iteration (Negative values will push the vector away from the target)
481
+ * @returns {ObservableVector3d} Reference to this object for method chaining
482
+ */
483
+ moveTowards(target, step) {
484
+ var angle = Math.atan2(target.y - this._y, target.x - this._x);
485
+
486
+ var dx = this._x - target.x;
487
+ var dy = this._y - target.y;
488
+
489
+ var distance = Math.sqrt(dx * dx + dy * dy);
490
+
491
+ if (distance === 0 || (step >= 0 && distance <= step * step)) {
492
+ return target;
493
+ }
494
+
495
+ return this._set(
496
+ this._x + Math.cos(angle) * step,
497
+ this._y + Math.sin(angle) * step,
498
+ this._z
499
+ );
472
500
  }
473
501
 
474
502
  /**
@@ -426,6 +426,29 @@ class Vector2d {
426
426
  return this;
427
427
  }
428
428
 
429
+ /**
430
+ * interpolate the position of this vector towards the given one by the given maximum step.
431
+ * @name moveTowards
432
+ * @memberof Vector2d
433
+ * @param {Vector2d} target
434
+ * @param {number} step the maximum step per iteration (Negative values will push the vector away from the target)
435
+ * @returns {Vector2d} Reference to this object for method chaining
436
+ */
437
+ moveTowards(target, step) {
438
+ var angle = Math.atan2(target.y - this.y, target.x - this.x);
439
+
440
+ var distance = this.distance(target);
441
+
442
+ if (distance === 0 || (step >= 0 && distance <= step * step)) {
443
+ return target;
444
+ }
445
+
446
+ this.x += Math.cos(angle) * step;
447
+ this.y += Math.sin(angle) * step;
448
+
449
+ return this;
450
+ }
451
+
429
452
  /**
430
453
  * return the distance between this vector and the passed one
431
454
  * @name distance
@@ -460,6 +460,32 @@ class Vector3d {
460
460
  return this;
461
461
  }
462
462
 
463
+ /**
464
+ * interpolate the position of this vector on the x and y axis towards the given one by the given maximum step.
465
+ * @name moveTowards
466
+ * @memberof Vector3d
467
+ * @param {Vector2d|Vector3d} target
468
+ * @param {number} step the maximum step per iteration (Negative values will push the vector away from the target)
469
+ * @returns {Vector3d} Reference to this object for method chaining
470
+ */
471
+ moveTowards(target, step) {
472
+ var angle = Math.atan2(target.y - this.y, target.x - this.x);
473
+
474
+ var dx = this.x - target.x;
475
+ var dy = this.y - target.y;
476
+
477
+ var distance = Math.sqrt(dx * dx + dy * dy);
478
+
479
+ if (distance === 0 || (step >= 0 && distance <= step * step)) {
480
+ return target;
481
+ }
482
+
483
+ this.x += Math.cos(angle) * step;
484
+ this.y += Math.sin(angle) * step;
485
+
486
+ return this;
487
+ }
488
+
463
489
  /**
464
490
  * return the distance between this vector and the passed one
465
491
  * @name distance