From 68b7d22e0d55f414fe98c027b06c375fbdde3bf9 Mon Sep 17 00:00:00 2001 From: photonstorm Date: Fri, 31 Jan 2014 03:32:12 +0000 Subject: [PATCH] Fixed issue with the camera being slightly out of sync with 'fixedToCamera' sprites. Also fixed 'jitter' issue with camera targets. --- examples/wip/rabbit map.js | 31 ++++++------- src/core/Camera.js | 26 +++++++---- src/core/Game.js | 4 +- src/core/World.js | 67 +++++++++++++++++++++-------- src/physics/arcade/ArcadePhysics.js | 64 +++++++++++++-------------- src/physics/arcade/Body.js | 6 +-- src/tilemap/TilemapLayer.js | 3 ++ 7 files changed, 121 insertions(+), 80 deletions(-) diff --git a/examples/wip/rabbit map.js b/examples/wip/rabbit map.js index 78a88e3d..f721fddf 100644 --- a/examples/wip/rabbit map.js +++ b/examples/wip/rabbit map.js @@ -34,6 +34,9 @@ console.log(' --- state create start ---'); game.step(); }); + // game.stage.backgroundColor = '#124184'; + + marker = new Phaser.Line(256, 0, 256, 600); map = game.add.tilemap('map'); @@ -48,22 +51,21 @@ console.log(' --- state create start ---'); // layer.debug = true; - // layer.resizeWorld(); + layer.resizeWorld(); - game.physics.gravity.y = 200; + // game.physics.gravity.y = 200; sprite = game.add.sprite(100, 300, 'phaser'); // up test // sprite = game.add.sprite(200, 240, 'phaser'); // 3-block corner test - sprite.debug = true; - - game.stepping = true; + // sprite.debug = true; + // game.stepping = true; // sprite.body.velocity.y = -300; - sprite.body.velocity.y = 200; + // sprite.body.velocity.y = 200; // sprite.anchor.setTo(0.5, 0.5); @@ -79,7 +81,7 @@ console.log(' --- state create start ---'); // sprite.angle = 35; - // game.camera.follow(sprite); + game.camera.follow(sprite); // game.input.onDown.add(getIt, this); @@ -89,7 +91,7 @@ console.log(' --- state create start ---'); function update() { -console.log(' --- state update start ---'); +// console.log(' --- state update start ---'); /* if (cursors.left.isDown) @@ -114,8 +116,8 @@ console.log(' --- state update start ---'); // sprite.body.velocity.y = -300; - // sprite.body.velocity.x = 0; - // sprite.body.velocity.y = 0; + sprite.body.velocity.x = 0; + sprite.body.velocity.y = 0; // sprite.body.angularVelocity = 0; // sprite.body.acceleration.x = 0; @@ -157,8 +159,8 @@ console.log(' --- state update start ---'); if (cursors.up.isDown) { - console.log('cursor up'); - sprite.body.velocity.y = -300; + // console.log('cursor up'); + sprite.body.velocity.y = -200; } else if (cursors.down.isDown) { @@ -167,14 +169,13 @@ console.log(' --- state update start ---'); if (cursors.left.isDown) { - sprite.body.velocity.x = -100; + sprite.body.velocity.x = -200; } else if (cursors.right.isDown) { - sprite.body.velocity.x = 100; + sprite.body.velocity.x = 200; } - } function render() { diff --git a/src/core/Camera.js b/src/core/Camera.js index d7bb5a1f..951e4362 100644 --- a/src/core/Camera.js +++ b/src/core/Camera.js @@ -39,7 +39,7 @@ Phaser.Camera = function (game, id, x, y, width, height) { * Camera view. * The view into the world we wish to render (by default the game dimensions). * The x/y values are in world coordinates, not screen coordinates, the width/height is how many pixels to render. - * Objects outside of this view are not rendered (unless set to ignore the Camera, i.e. UI?). + * Objects outside of this view are not rendered if set to camera cull. * @property {Phaser.Rectangle} view */ this.view = new Phaser.Rectangle(x, y, width, height); @@ -86,6 +86,9 @@ Phaser.Camera = function (game, id, x, y, width, height) { */ this._edge = 0; + /** + * @property {PIXI.DisplayObject} displayObject - The display object to which all game objects are added. Set by World.boot + */ this.displayObject = null; }; @@ -203,11 +206,15 @@ Phaser.Camera.prototype = { }, + /** + * Internal method + * @method Phaser.Camera#updateTarget + * @private + */ updateTarget: function () { if (this.deadzone) { - // this._edge = this.target.bounds.x - this.deadzone.x; this._edge = this.target.x - this.deadzone.x; if (this.view.x > this._edge) @@ -215,7 +222,6 @@ Phaser.Camera.prototype = { this.view.x = this._edge; } - // this._edge = this.target.bounds.right - this.deadzone.x - this.deadzone.width; this._edge = this.target.x + this.target.width - this.deadzone.x - this.deadzone.width; if (this.view.x < this._edge) @@ -223,7 +229,6 @@ Phaser.Camera.prototype = { this.view.x = this._edge; } - // this._edge = this.target.bounds.y - this.deadzone.y; this._edge = this.target.y - this.deadzone.y; if (this.view.y > this._edge) @@ -231,7 +236,6 @@ Phaser.Camera.prototype = { this.view.y = this._edge; } - // this._edge = this.target.bounds.bottom - this.deadzone.y - this.deadzone.height; this._edge = this.target.y + this.target.height - this.deadzone.y - this.deadzone.height; if (this.view.y < this._edge) @@ -246,6 +250,10 @@ Phaser.Camera.prototype = { }, + /** + * Update the Camera bounds to match the game world. + * @method Phaser.Camera#setBoundsToWorld + */ setBoundsToWorld: function () { this.bounds.setTo(this.game.world.bounds.x, this.game.world.bounds.y, this.game.world.bounds.width, this.game.world.bounds.height); @@ -268,10 +276,10 @@ Phaser.Camera.prototype = { this.view.x = this.bounds.x; } - if (this.view.x > this.bounds.right - this.width) + if (this.view.right > this.bounds.right) { this.atLimit.x = true; - this.view.x = (this.bounds.right - this.width) + 1; + this.view.x = this.bounds.right - this.width; } if (this.view.y < this.bounds.top) @@ -280,10 +288,10 @@ Phaser.Camera.prototype = { this.view.y = this.bounds.top; } - if (this.view.y > this.bounds.bottom - this.height) + if (this.view.bottom > this.bounds.bottom) { this.atLimit.y = true; - this.view.y = (this.bounds.bottom - this.height) + 1; + this.view.y = this.bounds.bottom - this.height; } this.view.floor(); diff --git a/src/core/Game.js b/src/core/Game.js index d13b0a61..6e6aafd4 100644 --- a/src/core/Game.js +++ b/src/core/Game.js @@ -592,7 +592,7 @@ Phaser.Game.prototype = { } this.plugins.preUpdate(); - console.log('world preUpdate'); + // console.log('world preUpdate'); this.world.preUpdate(); this.stage.update(); @@ -606,7 +606,7 @@ Phaser.Game.prototype = { this.particles.update(); this.plugins.update(); - console.log('world postUpdate'); + // console.log('world postUpdate'); this.world.postUpdate(); this.plugins.postUpdate(); } diff --git a/src/core/World.js b/src/core/World.js index 6a33dae1..c1a6004d 100644 --- a/src/core/World.js +++ b/src/core/World.js @@ -61,7 +61,8 @@ Phaser.World.prototype.boot = function () { } /** -* This is called automatically every frame, and is where main logic happens. +* This is called automatically after the plugins preUpdate and before the State.update. +* Most objects have preUpdate methods and it's where initial movement, drawing and calculations are done. * * @method Phaser.World#update */ @@ -90,7 +91,8 @@ Phaser.World.prototype.preUpdate = function () { } /** -* This is called automatically every frame, and is where main logic happens. +* This is called automatically after the State.update, but before particles or plugins update. +* Most objects won't have an update method set unless explicitly given one. * * @method Phaser.World#update */ @@ -121,31 +123,58 @@ Phaser.World.prototype.update = function () { } /** -* This is called automatically every frame, and is where main logic happens. +* This is called automatically before the renderer runs and after the plugins have updated. +* In postUpdate this is where all the final physics calculatations and object positioning happens. +* The objects are processed in the order of the display list. +* The only exception to this is if the camera is following an object, in which case that is updated first. +* * @method Phaser.World#postUpdate */ Phaser.World.prototype.postUpdate = function () { - this.camera.update(); - - if (this.game.stage._stage.first._iNext) + if (this.camera.target && this.camera.target['postUpdate']) { - var currentNode = this.game.stage._stage.first._iNext; - - do + this.camera.target.postUpdate(); + + this.camera.update(); + + if (this.game.stage._stage.first._iNext) { - if (currentNode['postUpdate']) - { - currentNode.postUpdate(); - } + var currentNode = this.game.stage._stage.first._iNext; - currentNode = currentNode._iNext; + do + { + if (currentNode['postUpdate'] && currentNode !== this.camera.target) + { + currentNode.postUpdate(); + } + + currentNode = currentNode._iNext; + } + while (currentNode != this.game.stage._stage.last._iNext) + } + } + else + { + this.camera.update(); + + if (this.game.stage._stage.first._iNext) + { + var currentNode = this.game.stage._stage.first._iNext; + + do + { + if (currentNode['postUpdate']) + { + currentNode.postUpdate(); + } + + currentNode = currentNode._iNext; + } + while (currentNode != this.game.stage._stage.last._iNext) } - while (currentNode != this.game.stage._stage.last._iNext) } - this.camera.update(); - } /** @@ -154,8 +183,8 @@ Phaser.World.prototype.postUpdate = function () { * @method Phaser.World#setBounds * @param {number} x - Top left most corner of the world. * @param {number} y - Top left most corner of the world. -* @param {number} width - New width of the world. -* @param {number} height - New height of the world. +* @param {number} width - New width of the world. Can never be smaller than the Game.width. +* @param {number} height - New height of the world. Can never be smaller than the Game.height. */ Phaser.World.prototype.setBounds = function (x, y, width, height) { diff --git a/src/physics/arcade/ArcadePhysics.js b/src/physics/arcade/ArcadePhysics.js index b01824bd..57787580 100644 --- a/src/physics/arcade/ArcadePhysics.js +++ b/src/physics/arcade/ArcadePhysics.js @@ -117,6 +117,12 @@ Phaser.Physics.Arcade = function (game) { */ this._p = new Phaser.Point(0, 0); + /** + * @property {number} _intersection - Internal cache var. + * @private + */ + this._intersection = [0,0,0,0]; + /** * @property {number} _gravityX - Internal cache var. * @private @@ -715,10 +721,7 @@ Phaser.Physics.Arcade.prototype = { */ collideSpriteVsTilemapLayer: function (sprite, tilemapLayer, collideCallback, processCallback, callbackContext) { - // At this stage the body.left value is WRONG (it's the old value) - // console.log('collideSpriteVsTilemapLayer sx:', sprite.x, 'sy:', sprite.y, 'body left:', sprite.body.left, 'right:', sprite.body.right); - console.log('collideSpriteVsTilemapLayer x:', sprite.body.x, 'y:', sprite.body.y, 'body left:', sprite.body.left, 'right:', sprite.body.right); - + // console.log('collideSpriteVsTilemapLayer x:', sprite.body.x, 'y:', sprite.body.y, 'body left:', sprite.body.left, 'right:', sprite.body.right); this._mapData = tilemapLayer.getTiles(sprite.body.left, sprite.body.top, sprite.body.width, sprite.body.height, true); @@ -865,30 +868,27 @@ Phaser.Physics.Arcade.prototype = { if (body.width <= 0 || body.height <= 0 || tile.width <= 0 || tile.height <= 0) { - return null; + this._intersection[4] = 0; + return this._intersection; } - console.log('____ tileIntersects'); - console.log('body: ', body.left, body.top, body.right, body.bottom); - console.log('tile: ', tile.x, tile.y, tile.right, tile.bottom); - // console.log('intersect #1', body.right < tile.x, body.right, tile.x); - // console.log('intersect #2', body.bottom < tile.y, body.bottom, tile.y); - // console.log('intersect #3', body.left > tile.right, body.left, tile.right); - // console.log('intersect #4', body.top > tile.bottom, body.top, tile.bottom); + // console.log('____ tileIntersects'); + // console.log('body: ', body.left, body.top, body.right, body.bottom); + // console.log('tile: ', tile.x, tile.y, tile.right, tile.bottom); if (!(body.right < tile.x || body.bottom < tile.y || body.left > tile.right || body.top > tile.bottom)) { - var out = [0,0,0,0]; + this._intersection[0] = Math.max(body.left, tile.x); // x + this._intersection[1] = Math.max(body.top, tile.y); // y + this._intersection[2] = Math.min(body.right, tile.right) - this._intersection[0]; // width + this._intersection[3] = Math.min(body.bottom, tile.bottom) - this._intersection[1]; // height + this._intersection[4] = 1; - out[0]= Math.max(body.left, tile.x); // x - out[1] = Math.max(body.top, tile.y); // y - out[2] = Math.min(body.right, tile.right) - out[0]; // width - out[3] = Math.min(body.bottom, tile.bottom) - out[1]; // height - - return out; + return this._intersection; } - return null; + this._intersection[4] = 0; + return this._intersection; }, @@ -901,7 +901,7 @@ Phaser.Physics.Arcade.prototype = { */ separateTiles: function (body, tiles) { - console.log('!!! separateTiles', tiles); + // console.log('!!! separateTiles', tiles); var tile; var result = false; @@ -929,17 +929,17 @@ Phaser.Physics.Arcade.prototype = { */ separateTile: function (body, tile) { - var intersection = this.tileIntersects(body, tile); + this._intersection = this.tileIntersects(body, tile); // If the intersection area is either entirely null, or has a width/height of zero, we bail out now - if (intersection === null || intersection[2] === 0 || intersection[3] === 0) + if (this._intersection[4] === 0 || this._intersection[2] === 0 || this._intersection[3] === 0) { - console.log('Tile does not intersect body'); + // console.log('Tile does not intersect body'); return false; } - console.log('*** separateTile', tile); - console.log('intersection', intersection); + // console.log('*** separateTile', tile); + // console.log('intersection', this._intersection); tile.tile.debug = true; @@ -969,7 +969,7 @@ Phaser.Physics.Arcade.prototype = { // LEFT body.overlapX = body.left - tile.right; - console.log('ST left', body.overlapX, body.deltaX(), 'bt', body.left, tile.right); + // console.log('ST left', body.overlapX, body.deltaX(), 'bt', body.left, tile.right); if (body.overlapX < 0) { @@ -985,7 +985,7 @@ Phaser.Physics.Arcade.prototype = { // RIGHT body.overlapX = body.right - tile.x; - console.log('ST right', body.overlapX, body.deltaX(), 'bt', body.right, tile.x); + // console.log('ST right', body.overlapX, body.deltaX(), 'bt', body.right, tile.x); if (body.overlapX > 0) { @@ -1002,7 +1002,7 @@ Phaser.Physics.Arcade.prototype = { // UP body.overlapY = body.top - tile.bottom; - console.log('ST up', body.overlapY, body.deltaY(), 'bt', body.top, tile.bottom); + // console.log('ST up', body.overlapY, body.deltaY(), 'bt', body.top, tile.bottom); if (body.overlapY < 0) { @@ -1018,7 +1018,7 @@ Phaser.Physics.Arcade.prototype = { // DOWN body.overlapY = body.bottom - tile.y; - console.log('ST down', body.overlapY, body.deltaY(), 'bt', body.bottom, tile.y); + // console.log('ST down', body.overlapY, body.deltaY(), 'bt', body.bottom, tile.y); if (body.overlapY > 0) { @@ -1064,7 +1064,7 @@ Phaser.Physics.Arcade.prototype = { */ processTileSeparation: function (body) { - console.log('PRE processTileSeparation xy', body.x, body.y, 'left', body.left, 'right', body.right, 'up', body.up, 'down', body.down); + // console.log('PRE processTileSeparation xy', body.x, body.y, 'left', body.left, 'right', body.right, 'up', body.up, 'down', body.down); if (body.overlapX < 0) { @@ -1109,7 +1109,7 @@ Phaser.Physics.Arcade.prototype = { body.touching.none = false; } - console.log('POST processTileSeparation xy', body.x, body.y, 'left', body.left, 'right', body.right, 'up', body.up, 'down', body.down); + // console.log('POST processTileSeparation xy', body.x, body.y, 'left', body.left, 'right', body.right, 'up', body.up, 'down', body.down); return true; diff --git a/src/physics/arcade/Body.js b/src/physics/arcade/Body.js index 126988d2..590b113a 100644 --- a/src/physics/arcade/Body.js +++ b/src/physics/arcade/Body.js @@ -100,7 +100,7 @@ Phaser.Physics.Arcade.Body = function (sprite) { this.bounce = new Phaser.Point(); /** - * @property {Phaser.Point} minVelocity - When a body rebounds off another or a wall the minVelocity is checked. If the new velocity is lower than minVelocity the body is stopped. + * @property {Phaser.Point} minVelocity - When a body rebounds off another body or a wall the minVelocity is checked. If the new velocity is lower than minVelocity the body is stopped. * @default */ this.minVelocity = new Phaser.Point(5, 5); @@ -521,14 +521,14 @@ if (this.sprite.debug) if (this.blocked.left || this.blocked.right && (Math.floor(this.x) !== this.blocked.x || Math.floor(this.y) !== this.blocked.y)) { - console.log('resetBlocked unlocked left + right'); + // console.log('resetBlocked unlocked left + right'); this.blocked.left = false; this.blocked.right = false; } if (this.blocked.up || this.blocked.down && (this.x !== this.blocked.x || this.y !== this.blocked.y)) { - console.log('resetBlocked unlocked up + down'); + // console.log('resetBlocked unlocked up + down'); this.blocked.up = false; this.blocked.down = false; } diff --git a/src/tilemap/TilemapLayer.js b/src/tilemap/TilemapLayer.js index 0431afc7..7bde7633 100644 --- a/src/tilemap/TilemapLayer.js +++ b/src/tilemap/TilemapLayer.js @@ -734,6 +734,9 @@ Phaser.TilemapLayer.prototype.render = function () { this._ty = this._dy; this.context.clearRect(0, 0, this.canvas.width, this.canvas.height); + // this.context.fillStyle = '#ff00ff'; + // this.context.fillRect(0, 0, this.canvas.width, this.canvas.height); + this.context.fillStyle = this.tileColor; var tile;