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