diff --git a/CHANGELOG.md b/CHANGELOG.md
index ffea9464..49457346 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -18,11 +18,13 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- Added `PointerWheel` event type for the `wheel` browser event, Excalibur now supports scroll wheel ([#808](https://github.com/excaliburjs/Excalibur/issues/808/))
### Changed
+- Camera zoom over time now returns a promise that resolves on completion ([#800](https://github.com/excaliburjs/Excalibur/issues/800))
- Edge builds have more descriptive versions now containing build number and Git commit hash (e.g. `0.10.0-alpha.105#commit`) ([#777](https://github.com/excaliburjs/Excalibur/issues/777))
### Deprecated
### Removed
### Fixed
+- Fixed camera zoom over time, before it did not work at all ([#800](https://github.com/excaliburjs/Excalibur/issues/800))
- Fixed semi-colon key not being detected on Firefox and Opera. ([#789](https://github.com/excaliburjs/Excalibur/issues/789))
diff --git a/sandbox/index.html b/sandbox/index.html
index 382a63e7..e410d663 100644
--- a/sandbox/index.html
+++ b/sandbox/index.html
@@ -21,6 +21,7 @@
DisplayMode Position
Camera Zoom
Camera Lerp
+ Camera Zoom over time
Groups
Audio
Audio: Long-running sound muting
diff --git a/sandbox/tests/camera/zoom.html b/sandbox/tests/camera/zoom.html
new file mode 100644
index 00000000..ff32bf95
--- /dev/null
+++ b/sandbox/tests/camera/zoom.html
@@ -0,0 +1,12 @@
+
+
+
+ Camera Zooom
+
+
+
+
+
+ Click to zoom in and out over time
+
+
\ No newline at end of file
diff --git a/sandbox/tests/camera/zoom.ts b/sandbox/tests/camera/zoom.ts
new file mode 100644
index 00000000..b9d6bb23
--- /dev/null
+++ b/sandbox/tests/camera/zoom.ts
@@ -0,0 +1,32 @@
+///
+
+var game = new ex.Engine({
+ width: 500,
+ height: 500
+});
+
+game.backgroundColor = ex.Color.Blue;
+
+
+var actor = new ex.Actor();
+
+actor.pos.x = 250;
+actor.setWidth(10);
+actor.pos.y = 250;
+actor.setHeight(10);
+actor.color = ex.Color.Red;
+
+game.add(actor);
+
+var zoomedIn = false;
+game.input.pointers.primary.on('down', (evt: ex.Input.PointerEvent) => {
+ if (!zoomedIn) {
+ zoomedIn = true;
+ game.currentScene.camera.zoom(5, 1000);
+ } else {
+ zoomedIn = false;
+ game.currentScene.camera.zoom(.2, 1000);
+ }
+});
+
+game.start();
\ No newline at end of file
diff --git a/src/engine/Camera.ts b/src/engine/Camera.ts
index 1ce65f62..f10026f9 100644
--- a/src/engine/Camera.ts
+++ b/src/engine/Camera.ts
@@ -50,9 +50,9 @@ export class BaseCamera {
private _yShake: number = 0;
protected _isZooming: boolean = false;
- private _currentZoomScale: number = 1;
private _maxZoomScale: number = 1;
private _zoomDuration: number = 0;
+ private _zoomPromise: Promise;
private _zoomIncrement: number = 0.01;
private _easing: EasingFunction = EasingFunctions.EaseInOutCubic;
@@ -158,27 +158,22 @@ export class BaseCamera {
* @param scale The scale of the zoom
* @param duration The duration of the zoom in milliseconds
*/
- public zoom(scale: number, duration: number = 0) {
- this._isZooming = true;
- this._maxZoomScale = scale;
- this._zoomDuration = duration;
+ public zoom(scale: number, duration: number = 0): Promise {
+ this._zoomPromise = new Promise();
+
if (duration) {
- this._zoomIncrement = Math.abs(this._maxZoomScale - this._currentZoomScale) / duration * 1000;
- }
-
- if (this._maxZoomScale < 1) {
- if (duration) {
- this._zoomIncrement = -1 * this._zoomIncrement;
- } else {
- this._isZooming = false;
- this._setCurrentZoomScale(this._maxZoomScale);
- }
+ this._isZooming = true;
+ this._maxZoomScale = scale;
+ this._zoomDuration = duration;
+ this._zoomIncrement = (scale - this.z) / duration;
} else {
- if (!duration) {
- this._isZooming = false;
- this._setCurrentZoomScale(this._maxZoomScale);
- }
+ this._isZooming = false;
+ this.z = scale;
+ this._zoomPromise.resolve(true);
+
}
+
+ return this._zoomPromise;
}
/**
@@ -188,10 +183,6 @@ export class BaseCamera {
return this.z;
}
- private _setCurrentZoomScale(zoomScale: number) {
- this.z = zoomScale;
- }
-
public update(_engine: Engine, delta: number) {
// Update placements based on linear algebra
this._x += this.dx * delta / 1000;
@@ -204,6 +195,25 @@ export class BaseCamera {
this.rotation += this.rx * delta / 1000;
+ if (this._isZooming) {
+ var newZoom = this.z + this._zoomIncrement * delta;
+ this.z = newZoom;
+ if (this._zoomIncrement > 0) {
+
+ if (newZoom >= this._maxZoomScale) {
+ this._isZooming = false;
+ this.z = this._maxZoomScale;
+ this._zoomPromise.resolve(true);
+ }
+ } else {
+ if (newZoom <= this._maxZoomScale) {
+ this._isZooming = false;
+ this.z = this._maxZoomScale;
+ this._zoomPromise.resolve(true);
+ }
+ }
+ }
+
if (this._cameraMoving) {
if (this._currentLerpTime < this._lerpDuration) {
diff --git a/src/spec/CameraSpec.ts b/src/spec/CameraSpec.ts
index c94c3075..bcb6df57 100644
--- a/src/spec/CameraSpec.ts
+++ b/src/spec/CameraSpec.ts
@@ -13,22 +13,36 @@ describe('A camera', () => {
var mock = new Mocks.Mocker();
beforeEach(() => {
+ jasmine.addMatchers(imagediff.jasmine);
actor = new ex.Actor();
// mock engine
- engine = mock.engine(500, 500);
+ engine = TestUtils.engine({
+ width: 500,
+ height: 500
+ });
+
+ engine.setAntialiasing(false);
+
+ engine.backgroundColor = ex.Color.Blue;
actor.pos.x = 250;
actor.setWidth(10);
actor.pos.y = 250;
actor.setHeight(10);
+ actor.color = ex.Color.Red;
scene = new ex.Scene(engine);
+ scene.add(actor);
engine.currentScene = scene;
sideCamera = new ex.SideCamera();
lockedCamera = new ex.LockedCamera();
baseCamera = new ex.BaseCamera();
});
+
+ afterEach(() => {
+ engine.stop();
+ });
it('can follow an actor if it is a lockedCamera', () => {
engine.currentScene.camera = lockedCamera;
@@ -147,4 +161,20 @@ describe('A camera', () => {
});
+ xit('can zoom in over time', (done) => {
+ engine.start().then(() => {
+ engine.currentScene.camera.zoom(5, 1000).then(() => {
+ imagediff.expectCanvasImageMatches('CameraSpec/zoomin.png', engine.canvas, done);
+ });
+ });
+ });
+
+ xit('can zoom out over time', (done) => {
+ engine.start().then(() => {
+ engine.currentScene.camera.zoom(.2, 1000).then(() => {
+ imagediff.expectCanvasImageMatches('CameraSpec/zoomout.png', engine.canvas, done);
+ });
+ });
+ });
+
});
diff --git a/src/spec/images/CameraSpec/zoomin.png b/src/spec/images/CameraSpec/zoomin.png
new file mode 100644
index 0000000000000000000000000000000000000000..a42a001761ac4693efd9688725598c48f8d34d20
GIT binary patch
literal 1751
zcmeAS@N?(olHy`uVBq!ia0y~yVEh8Y9Bd2>45zQ%?_ywJ;4JWnEM{QfI|9OtQ?>b|
z85r0)JzX3_DsH{Kaget`LB!?Y)d+6)-5b4jee^JnU{Ud!^YVdy`}7T}d)XNxZsjpC
z2$V25Twr8yWM^QJ1tA03z!+2_!u~>7!+QB5P}a8
zg7V=?8Wu1^g&^_@FOZCY2tnn^(86H_bqM)JkYOvTme~vgoib43$l(Gb3Llb08&>iO
zAK0C>ZpxOW`5Br!gKX6}tp0?1o}PJI;DA8c*nj?u!72)26%mz8$
zRp!hLYtBx$9{AWsO8hiU*~kF`P27;of|7p*K^8=IC^Y6E4jq`_85mnpA_eY!P;g)`
dp$x7wXL|F$G~~~m!oa}5;OXk;vd$@?2>_@Si#Y%Q
literal 0
HcmV?d00001
diff --git a/src/spec/images/CameraSpec/zoomout.png b/src/spec/images/CameraSpec/zoomout.png
new file mode 100644
index 0000000000000000000000000000000000000000..509be0c2ef31816b0659bd1401a6a8a069777806
GIT binary patch
literal 1736
zcmeAS@N?(olHy`uVBq!ia0y~yVEh8Y9Bd2>45zQ%?_ywJ;4JWnEM{QfI|9OtQ?>b|
z85r2AJY5_^DsH{K;V9T(Ai#2vk@4VupCpAF9xL)Vf6v^tJ8LaN!{WPY3=EF!3@ow?
z0woL%7Z@EbFe3O6At)cN1jMJA7J(9|LqN8$$RZpD;?vAlRKJ-sGH_TiD7;{3SisEC
z#0NrfK2!+8M=0U2qMeq81