|
4 | 4 | * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} |
5 | 5 | */ |
6 | 6 |
|
| 7 | +var Clamp = require('../../math/Clamp'); |
7 | 8 | var Class = require('../../utils/Class'); |
8 | 9 | var DegToRad = require('../../math/DegToRad'); |
9 | | -var EventEmitter = require('eventemitter3'); |
10 | 10 | var Effects = require('./effects'); |
| 11 | +var EventEmitter = require('eventemitter3'); |
| 12 | +var Linear = require('../../math/Linear'); |
11 | 13 | var Rectangle = require('../../geom/rectangle/Rectangle'); |
12 | 14 | var TransformMatrix = require('../../gameobjects/components/TransformMatrix'); |
13 | 15 | var ValueToColor = require('../../display/color/ValueToColor'); |
@@ -300,6 +302,22 @@ var Camera = new Class({ |
300 | 302 | */ |
301 | 303 | this.culledObjects = []; |
302 | 304 |
|
| 305 | + /** |
| 306 | + * The linear interpolation value to use when following a target. |
| 307 | + * |
| 308 | + * The default values of 1 means the camera will instantly snap to the target coordinates. |
| 309 | + * A lower value, such as 0.1 means the camera will more slowly track the target, giving |
| 310 | + * a smooth transition. You can set the horizontal and vertical values independently, and also |
| 311 | + * adjust this value in real-time during your game. |
| 312 | + * |
| 313 | + * Be sure to keep the value between 0 and 1. A value of zero will disable tracking on that axis. |
| 314 | + * |
| 315 | + * @name Phaser.Cameras.Scene2D.Camera#lerp |
| 316 | + * @type {Phaser.Math.Vector2} |
| 317 | + * @since 3.9.0 |
| 318 | + */ |
| 319 | + this.lerp = new Vector2(1, 1); |
| 320 | + |
303 | 321 | /** |
304 | 322 | * Internal follow target reference. |
305 | 323 | * |
@@ -683,13 +701,10 @@ var Camera = new Class({ |
683 | 701 | var originY = height / 2; |
684 | 702 | var follow = this._follow; |
685 | 703 |
|
686 | | - if (follow !== null) |
| 704 | + if (follow) |
687 | 705 | { |
688 | | - originX = follow.x; |
689 | | - originY = follow.y; |
690 | | - |
691 | | - this.scrollX = (originX - width * 0.5) / zoom; |
692 | | - this.scrollY = (originY - height * 0.5) / zoom; |
| 706 | + this.scrollX = Linear(this.scrollX, follow.x - originX, this.lerp.x) / zoom; |
| 707 | + this.scrollY = Linear(this.scrollY, follow.y - originY, this.lerp.y) / zoom; |
693 | 708 | } |
694 | 709 |
|
695 | 710 | if (this.useBounds) |
@@ -1034,22 +1049,47 @@ var Camera = new Class({ |
1034 | 1049 | * |
1035 | 1050 | * When enabled the Camera will automatically adjust its scroll position to keep the target Game Object |
1036 | 1051 | * in its center. |
| 1052 | + * |
| 1053 | + * You can set the linear interpolation value used in the follow code. |
| 1054 | + * Use low lerp values (such as 0.1) to automatically smooth the camera motion. |
| 1055 | + * |
| 1056 | + * If you find you're getting a slight "jitter" effect when following an object it's probably to do with sub-pixel |
| 1057 | + * rendering of the targets position. This can be rounded by setting the `roundPixels` argument to `true` to |
| 1058 | + * force full pixel rounding rendering. Note that this can still be broken if you have specified a non-integer zoom |
| 1059 | + * value on the camera. So be sure to keep the camera zoom to integers. |
1037 | 1060 | * |
1038 | 1061 | * @method Phaser.Cameras.Scene2D.Camera#startFollow |
1039 | 1062 | * @since 3.0.0 |
1040 | 1063 | * |
1041 | 1064 | * @param {(Phaser.GameObjects.GameObject|object)} target - The target for the Camera to follow. |
1042 | | - * @param {boolean} [roundPx=false] - Round the movement pixels to whole integers? |
| 1065 | + * @param {boolean} [roundPixels=false] - Round the camera position to whole integers to avoid sub-pixel rendering? |
| 1066 | + * @param {float} [lerpX=1] - A value between 0 and 1. This value specifies the amount of linear interpolation to use when horizontally tracking the target. The closer the value to 1, the faster the camera will track. |
| 1067 | + * @param {float} [lerpY=1] - A value between 0 and 1. This value specifies the amount of linear interpolation to use when vertically tracking the target. The closer the value to 1, the faster the camera will track. |
1043 | 1068 | * |
1044 | | - * @return {Phaser.Cameras.Scene2D.Camera} This Camera instance. |
| 1069 | + * @return {this} This Camera instance. |
1045 | 1070 | */ |
1046 | | - startFollow: function (target, roundPx) |
| 1071 | + startFollow: function (target, roundPixels, lerpX, lerpY) |
1047 | 1072 | { |
1048 | | - if (roundPx === undefined) { roundPx = false; } |
| 1073 | + if (roundPixels === undefined) { roundPixels = false; } |
| 1074 | + if (lerpX === undefined) { lerpX = 1; } |
| 1075 | + if (lerpY === undefined) { lerpY = lerpX; } |
1049 | 1076 |
|
1050 | 1077 | this._follow = target; |
1051 | 1078 |
|
1052 | | - this.roundPixels = roundPx; |
| 1079 | + this.roundPixels = roundPixels; |
| 1080 | + |
| 1081 | + lerpX = Clamp(lerpX, 0, 1); |
| 1082 | + lerpY = Clamp(lerpY, 0, 1); |
| 1083 | + |
| 1084 | + this.lerp.set(lerpX, lerpY); |
| 1085 | + |
| 1086 | + // Move the camera there immediately, to avoid a large lerp during preUpdate |
| 1087 | + var zoom = this.zoom; |
| 1088 | + var originX = this.width / 2; |
| 1089 | + var originY = this.height / 2; |
| 1090 | + |
| 1091 | + this.scrollX = (target.x - originX) / zoom; |
| 1092 | + this.scrollY = (target.y - originY) / zoom; |
1053 | 1093 |
|
1054 | 1094 | return this; |
1055 | 1095 | }, |
|
0 commit comments