diff --git a/README.md b/README.md index 2ba38146..355363d7 100644 --- a/README.md +++ b/README.md @@ -97,7 +97,14 @@ Version 1.0.7 (in progress in the dev branch) * Moved the Camera update checks to World.postUpdate, so all the sprites get the correct adjusted camera position. * Added Sprite.fixedToCamera boolean. A Sprite that is fixed to the camera doesn't move with the world, but has its x/y coordinates relative to the top-left of the camera. * Updated InputHandler to use Math.round rather than Math.floor when snapping an object during drag. - +* If you didn't provide the useNumericIndex parameter then AnimationManager.add will set the value by looking at the datatype of the first element in the frames array. +* Added Group.createMultiple - useful when you need to create a Group of identical sprites for pooling, such as bullets. +* Group.create now sets the visible and alive properties of the Sprite to the same value as the 'exists' parameter. +* Added Group.total. Same as Group.length, but more in line with the rest of the Group naming. +* Added Sprite.outOfBoundsKill boolean flag. Will automatically kill a sprite that leaves the game World bounds (off by default). +* ArcadePhysics.moveTowardsMouse changed to ArcadePhysics.moveTowardsPointer and now lets you specify which pointer to move towards (defaults to Input.activePointer). +* ArcadePhysics.angleBetweenMouse changed to ArcadePhysics.angleBetweenPointer and now lets you specify which pointer to get the angle to (defaults to Input.activePointer). +* ArcadePhysics.velocityFromAngle and ArcadePhysics.velocityFromRotation added with examples created. * TODO: look at Sprite.crop (http://www.html5gamedevs.com/topic/1617-error-in-spritecrop/) @@ -106,6 +113,7 @@ Version 1.0.7 (in progress in the dev branch) * TODO: addMarker hh:mm:ss:ms * TODO: swap state (non-destructive shift) * TODO: rotation offset +* TODO: check stage bgc on droid (http://www.html5gamedevs.com/topic/1629-stage-background-color-not-working-on-android-chrome/) Version 1.0.6 (September 24th 2013) diff --git a/examples/assets/games/gofish/Level 1.psd b/examples/assets/games/gofish/Level 1.psd new file mode 100644 index 00000000..1adcf53b Binary files /dev/null and b/examples/assets/games/gofish/Level 1.psd differ diff --git a/examples/assets/games/gofish/background.png b/examples/assets/games/gofish/background.png new file mode 100644 index 00000000..11268425 Binary files /dev/null and b/examples/assets/games/gofish/background.png differ diff --git a/examples/assets/games/gofish/fishie.png b/examples/assets/games/gofish/fishie.png new file mode 100644 index 00000000..0e406fbd Binary files /dev/null and b/examples/assets/games/gofish/fishie.png differ diff --git a/examples/assets/games/gofish/level1.png b/examples/assets/games/gofish/level1.png new file mode 100644 index 00000000..58f88735 Binary files /dev/null and b/examples/assets/games/gofish/level1.png differ diff --git a/examples/assets/games/znax/Mouse Command bits.psd b/examples/assets/games/znax/Mouse Command bits.psd new file mode 100644 index 00000000..f9062699 Binary files /dev/null and b/examples/assets/games/znax/Mouse Command bits.psd differ diff --git a/examples/assets/games/znax/znax.psd b/examples/assets/games/znax/znax.psd new file mode 100644 index 00000000..dc56891d Binary files /dev/null and b/examples/assets/games/znax/znax.psd differ diff --git a/examples/assets/sprites/longarrow.png b/examples/assets/sprites/longarrow.png new file mode 100644 index 00000000..41850f8f Binary files /dev/null and b/examples/assets/sprites/longarrow.png differ diff --git a/examples/input/multi touch.php b/examples/input/multi touch.php index a6db638a..a6bbc9bd 100644 --- a/examples/input/multi touch.php +++ b/examples/input/multi touch.php @@ -5,29 +5,38 @@ + + + + \ No newline at end of file diff --git a/examples/physics/angular velocity.php b/examples/physics/angular velocity.php index 076e70cd..5877517b 100644 --- a/examples/physics/angular velocity.php +++ b/examples/physics/angular velocity.php @@ -39,7 +39,7 @@ if (game.input.keyboard.isDown(Phaser.Keyboard.UP)) { - sprite.body.velocity.copyFrom(game.physics.velocityFromAngle(sprite.angle, 300)); + game.physics.velocityFromAngle(sprite.angle, 300, sprite.body.velocity); } } diff --git a/examples/physics/multi angle to pointer.php b/examples/physics/multi angle to pointer.php new file mode 100644 index 00000000..a78596db --- /dev/null +++ b/examples/physics/multi angle to pointer.php @@ -0,0 +1,59 @@ + + + + + \ No newline at end of file diff --git a/examples/physics/shoot the mouse.php b/examples/physics/shoot the mouse.php new file mode 100644 index 00000000..2348c73e --- /dev/null +++ b/examples/physics/shoot the mouse.php @@ -0,0 +1,76 @@ + + + + + \ No newline at end of file diff --git a/src/animation/AnimationManager.js b/src/animation/AnimationManager.js index 6d3043cb..3cf6920c 100644 --- a/src/animation/AnimationManager.js +++ b/src/animation/AnimationManager.js @@ -97,7 +97,19 @@ Phaser.AnimationManager.prototype = { frameRate = frameRate || 60; if (typeof loop === 'undefined') { loop = false; } - if (typeof useNumericIndex === 'undefined') { useNumericIndex = true; } + + // If they didn't set the useNumericIndex then let's at least try and guess it + if (typeof useNumericIndex === 'undefined') + { + if (frames[0] && typeof frames[0] === 'number') + { + useNumericIndex = true; + } + else + { + useNumericIndex = false; + } + } // Create the signals the AnimationManager will emit if (this.sprite.events.onAnimationStart == null) diff --git a/src/animation/FrameData.js b/src/animation/FrameData.js index 5b1c8662..d3275c84 100644 --- a/src/animation/FrameData.js +++ b/src/animation/FrameData.js @@ -209,7 +209,10 @@ Phaser.FrameData.prototype = { } else { - output.push(this.getFrameByName(frames[i]).index); + if (this.getFrameByName(frames[i])) + { + output.push(this.getFrameByName(frames[i]).index); + } } } } diff --git a/src/core/Group.js b/src/core/Group.js index a91a4697..eece453b 100644 --- a/src/core/Group.js +++ b/src/core/Group.js @@ -16,9 +16,12 @@ */ Phaser.Group = function (game, parent, name, useStage) { - parent = parent || null; + if (typeof parent === 'undefined') + { + parent = game.world; + } - if (typeof useStage == 'undefined') + if (typeof useStage === 'undefined') { useStage = false; } @@ -159,7 +162,7 @@ Phaser.Group.prototype = { * @param {number} y - The y coordinate to display the newly created Sprite at. The value is in relation to the Group.y point. * @param {string} key - The Game.cache key of the image that this Sprite will use. * @param {number|string} [frame] - If the Sprite image contains multiple frames you can specify which one to use here. - * @param {boolean} [exists] - The default exists state of the Sprite. + * @param {boolean} [exists=true] - The default exists state of the Sprite. * @return {Phaser.Sprite} The child that was created. */ create: function (x, y, key, frame, exists) { @@ -170,6 +173,8 @@ Phaser.Group.prototype = { child.group = this; child.exists = exists; + child.visible = exists; + child.alive = exists; if (child.events) { @@ -182,6 +187,40 @@ Phaser.Group.prototype = { }, + /** + * Automatically creates multiple Phaser.Sprite objects and adds them to the top of this Group. + * Useful if you need to quickly generate a pool of identical sprites, such as bullets. By default the sprites will be set to not exist + * and will be positioned at 0, 0 (relative to the Group.x/y) + * + * @method Phaser.Group#createMultiple + * @param {number} quantity - The number of Sprites to create. + * @param {string} key - The Game.cache key of the image that this Sprite will use. + * @param {number|string} [frame] - If the Sprite image contains multiple frames you can specify which one to use here. + * @param {boolean} [exists=false] - The default exists state of the Sprite. + */ + createMultiple: function (quantity, key, frame, exists) { + + if (typeof exists == 'undefined') { exists = false; } + + for (var i = 0; i < quantity; i++) + { + var child = new Phaser.Sprite(this.game, 0, 0, key, frame); + + child.group = this; + child.exists = exists; + child.visible = exists; + child.alive = exists; + + if (child.events) + { + child.events.onAddedToGroup.dispatch(child, this); + } + + this._container.addChild(child); + } + + }, + /** * Swaps the position of two children in this Group. * @@ -1067,6 +1106,19 @@ Phaser.Group.prototype = { }; +/** +* @name Phaser.Group#total +* @property {number} total - The total number of children in this Group, regardless of their alive state. +* @readonly +*/ +Object.defineProperty(Phaser.Group.prototype, "total", { + + get: function () { + return this._container.children.length; + } + +}); + /** * @name Phaser.Group#length * @property {number} length - The number of children in this Group. diff --git a/src/gameobjects/Sprite.js b/src/gameobjects/Sprite.js index bc27dc15..05389ccc 100644 --- a/src/gameobjects/Sprite.js +++ b/src/gameobjects/Sprite.js @@ -283,6 +283,12 @@ Phaser.Sprite = function (game, x, y, key, frame) { * @default */ this.inWorldThreshold = 0; + + /** + * @property {boolean} outOfBoundsKill - Kills this sprite as soon as it goes outside of the World bounds. + * @default + */ + this.outOfBoundsKill = false; /** * @property {boolean} _outOfBoundsFired - Description. @@ -528,6 +534,7 @@ Phaser.Sprite.prototype.reset = function(x, y) { this.alive = true; this.exists = true; this.visible = true; + this.renderable = true; this._outOfBoundsFired = false; this.body.reset(); @@ -581,6 +588,11 @@ Phaser.Sprite.prototype.updateBounds = function() { { this.events.onOutOfBounds.dispatch(this); this._outOfBoundsFired = true; + + if (this.outOfBoundsKill) + { + this.kill(); + } } } diff --git a/src/physics/arcade/ArcadePhysics.js b/src/physics/arcade/ArcadePhysics.js index c48cff67..6a683ee7 100644 --- a/src/physics/arcade/ArcadePhysics.js +++ b/src/physics/arcade/ArcadePhysics.js @@ -38,6 +38,7 @@ Phaser.Physics.Arcade = function (game) { this._mapData = []; this._result = false; this._total = 0; + this._angle = 0; }; @@ -981,57 +982,146 @@ Phaser.Physics.Arcade.prototype = { }, /** - * Given the angle and speed calculate the velocity and return it as a Point + * Move the given display object towards the pointer at a steady velocity. If no pointer is given it will use Phaser.Input.activePointer. + * If you specify a maxTime then it will adjust the speed (over-writing what you set) so it arrives at the destination in that number of seconds. + * Timings are approximate due to the way browser timers work. Allow for a variance of +- 50ms. + * Note: The display object doesn't stop moving once it reaches the destination coordinates. + * Note: Doesn't take into account acceleration, maxVelocity or drag (if you've set drag or acceleration too high this object may not move at all) * - * @param angle The angle (in degrees) calculated in clockwise positive direction (down = 90 degrees positive, right = 0 degrees positive, up = 90 degrees negative) - * @param speed The speed it will move, in pixels per second sq - * - * @return A Point where Point.x contains the velocity x value and Point.y contains the velocity y value + * @method Phaser.Physics.Arcade#moveTowardsObject + * @param {any} displayObject - The display object to move. + * @param {any} destination - The display object to move towards. Can be any object but must have visible x/y properties. + * @param {number} [speed=60] - The speed it will move, in pixels per second (default is 60 pixels/sec) + * @param {number} [maxTime=0] - Time given in milliseconds (1000 = 1 sec). If set the speed is adjusted so the object will arrive at destination in the given number of ms. + * @return {number} The angle (in radians) that the object should be visually set to in order to match its new velocity. */ - velocityFromAngle: function (angle, speed, point) { - - speed = speed || 0; - point = point || new Phaser.Point; - - var a = this.game.math.degToRad(angle); - - return point.setTo((Math.cos(a) * speed), (Math.sin(a) * speed)); - - }, - - /** - * Sets the source Sprite x/y velocity so it will move directly towards the destination Sprite at the speed given (in pixels per second)
- * If you specify a maxTime then it will adjust the speed (over-writing what you set) so it arrives at the destination in that number of seconds.
- * Timings are approximate due to the way Flash timers work, and irrespective of SWF frame rate. Allow for a variance of +- 50ms.
- * The source object doesn't stop moving automatically should it ever reach the destination coordinates.
- * If you need the object to accelerate, see accelerateTowardsObject() instead - * Note: Doesn't take into account acceleration, maxVelocity or drag (if you set drag or acceleration too high this object may not move at all) - * - * @param source The Sprite on which the velocity will be set - * @param dest The Sprite where the source object will move to - * @param speed The speed it will move, in pixels per second (default is 60 pixels/sec) - * @param maxTime Time given in milliseconds (1000 = 1 sec). If set the speed is adjusted so the source will arrive at destination in the given number of ms - */ - moveTowardsObject: function (source, dest, speed, maxTime) { + moveTowardsObject: function (displayObject, destination, speed, maxTime) { speed = speed || 60; maxTime = maxTime || 0; - var a = this.angleBetween(source, dest); + this._angle = Math.atan2(destination.y - displayObject.y, destination.x - displaxObject.x); if (maxTime > 0) { - var d = this.distanceBetween(source, dest); - // We know how many pixels we need to move, but how fast? - speed = d / (maxTime / 1000); + speed = this.distanceToMouse(displayObject) / (maxTime / 1000); } - source.body.velocity.x = Math.cos(a) * speed; - source.body.velocity.y = Math.sin(a) * speed; + displayObject.body.velocity.x = Math.cos(this._angle) * speed; + displayObject.body.velocity.y = Math.sin(this._angle) * speed; + + return this._angle; }, + /** + * Move the given display object towards the pointer at a steady velocity. If no pointer is given it will use Phaser.Input.activePointer. + * If you specify a maxTime then it will adjust the speed (over-writing what you set) so it arrives at the destination in that number of seconds. + * Timings are approximate due to the way browser timers work. Allow for a variance of +- 50ms. + * Note: The display object doesn't stop moving once it reaches the destination coordinates. + * + * @method Phaser.Physics.Arcade#moveTowardsPointer + * @param {any} displayObject - The display object to move. + * @param {number} [speed=60] - The speed it will move, in pixels per second (default is 60 pixels/sec) + * @param {Phaser.Pointer} [pointer] - The pointer to move towards. Defaults to Phaser.Input.activePointer. + * @param {number} [maxTime=0] - Time given in milliseconds (1000 = 1 sec). If set the speed is adjusted so the object will arrive at destination in the given number of ms. + * @return {number} The angle (in radians) that the object should be visually set to in order to match its new velocity. + */ + moveTowardsPointer: function (displayObject, speed, pointer, maxTime) { + + speed = speed || 60; + pointer = pointer || this.game.input.activePointer; + maxTime = maxTime || 0; + + this._angle = this.angleBetweenPointer(displayObject, pointer); + + if (maxTime > 0) + { + // We know how many pixels we need to move, but how fast? + speed = this.distanceToMouse(displayObject) / (maxTime / 1000); + } + + displayObject.body.velocity.x = Math.cos(this._angle) * speed; + displayObject.body.velocity.y = Math.sin(this._angle) * speed; + + return this._angle; + + }, + + /** + * Move the given display object towards the pointer at a steady velocity. If no pointer is given it will use Phaser.Input.activePointer. + * If you specify a maxTime then it will adjust the speed (over-writing what you set) so it arrives at the destination in that number of seconds. + * Timings are approximate due to the way browser timers work. Allow for a variance of +- 50ms. + * Note: The display object doesn't stop moving once it reaches the destination coordinates. + * Note: Doesn't take into account acceleration, maxVelocity or drag (if you've set drag or acceleration too high this object may not move at all) + * + * @method Phaser.Physics.Arcade#moveTowardsObject + * @param {any} displayObject - The display object to move. + * @param {any} destination - The display object to move towards. Can be any object but must have visible x/y properties. + * @param {number} [speed=60] - The speed it will move, in pixels per second (default is 60 pixels/sec) + * @param {number} [maxTime=0] - Time given in milliseconds (1000 = 1 sec). If set the speed is adjusted so the object will arrive at destination in the given number of ms. + * @return {number} The angle (in radians) that the object should be visually set to in order to match its new velocity. + */ + moveTowardsXY: function (displayObject, x, y, speed, maxTime) { + + speed = speed || 60; + maxTime = maxTime || 0; + + this._angle = this.angleBetweenPointer(displayObject, destination); + + if (maxTime > 0) + { + // We know how many pixels we need to move, but how fast? + speed = this.distanceToMouse(displayObject) / (maxTime / 1000); + } + + displayObject.body.velocity.x = Math.cos(this._angle) * speed; + displayObject.body.velocity.y = Math.sin(this._angle) * speed; + + return this._angle; + + }, + + /** + * Given the angle (in degrees) and speed calculate the velocity and return it as a Point object, or set it to the given point object. + * One way to use this is: velocityFromAngle(angle, 200, sprite.velocity) which will set the values directly to the sprites velocity and not create a new Point object. + * + * @method Phaser.Physics.Arcade#velocityFromAngle + * @param {number} angle - The angle in degrees calculated in clockwise positive direction (down = 90 degrees positive, right = 0 degrees positive, up = 90 degrees negative) + * @param {number} [speed=60] - The speed it will move, in pixels per second sq. + * @param {Phaser.Point|object} [point] - The Point object in which the x and y properties will be set to the calculated velocity. + * @return {Phaser.Point} - A Point where point.x contains the velocity x value and point.y contains the velocity y value. + */ + velocityFromAngle: function (angle, speed, point) { + + speed = speed || 60; + point = point || new Phaser.Point; + + return point.setTo((Math.cos(this.game.math.degToRad(angle)) * speed), (Math.sin(this.game.math.degToRad(angle)) * speed)); + + }, + + /** + * Given the rotation (in radians) and speed calculate the velocity and return it as a Point object, or set it to the given point object. + * One way to use this is: velocityFromRotation(rotation, 200, sprite.velocity) which will set the values directly to the sprites velocity and not create a new Point object. + * + * @method Phaser.Physics.Arcade#velocityFromRotation + * @param {number} rotation - The angle in radians. + * @param {number} [speed=60] - The speed it will move, in pixels per second sq. + * @param {Phaser.Point|object} [point] - The Point object in which the x and y properties will be set to the calculated velocity. + * @return {Phaser.Point} - A Point where point.x contains the velocity x value and point.y contains the velocity y value. + */ + velocityFromRotation: function (rotation, speed, point) { + + speed = speed || 60; + point = point || new Phaser.Point; + + return point.setTo((Math.cos(rotation) * speed), (Math.sin(rotation) * speed)); + + }, + + /** * Sets the x/y acceleration on the source Sprite so it will move towards the destination Sprite at the speed given (in pixels per second)
* You must give a maximum speed value, beyond which the Sprite won't go any faster.
@@ -1061,35 +1151,6 @@ Phaser.Physics.Arcade.prototype = { }, - /** - * Move the given Sprite towards the mouse pointer coordinates at a steady velocity - * If you specify a maxTime then it will adjust the speed (over-writing what you set) so it arrives at the destination in that number of seconds.
- * Timings are approximate due to the way Flash timers work, and irrespective of SWF frame rate. Allow for a variance of +- 50ms.
- * The source object doesn't stop moving automatically should it ever reach the destination coordinates.
- * - * @param source The Sprite to move - * @param speed The speed it will move, in pixels per second (default is 60 pixels/sec) - * @param maxTime Time given in milliseconds (1000 = 1 sec). If set the speed is adjusted so the source will arrive at destination in the given number of ms - */ - moveTowardsMouse: function (source, speed, maxTime) { - - speed = speed || 60; - maxTime = maxTime || 0; - - var a = this.angleBetweenMouse(source); - - if (maxTime > 0) - { - var d = this.distanceToMouse(source); - - // We know how many pixels we need to move, but how fast? - speed = d / (maxTime / 1000); - } - - source.body.velocity.x = Math.cos(a) * speed; - source.body.velocity.y = Math.sin(a) * speed; - - }, /** * Sets the x/y acceleration on the source Sprite so it will move towards the mouse coordinates at the speed given (in pixels per second)
@@ -1106,7 +1167,7 @@ Phaser.Physics.Arcade.prototype = { xSpeedMax = xSpeedMax || 1000; ySpeedMax = ySpeedMax || 1000; - var a = this.angleBetweenMouse(source); + var a = this.angleBetweenMouse(source, true); source.body.velocity.x = 0; source.body.velocity.y = 0; @@ -1119,36 +1180,6 @@ Phaser.Physics.Arcade.prototype = { }, - /** - * Sets the x/y velocity on the source Sprite so it will move towards the target coordinates at the speed given (in pixels per second)
- * If you specify a maxTime then it will adjust the speed (over-writing what you set) so it arrives at the destination in that number of seconds.
- * Timings are approximate due to the way Flash timers work, and irrespective of SWF frame rate. Allow for a variance of +- 50ms.
- * The source object doesn't stop moving automatically should it ever reach the destination coordinates.
- * - * @param source The Sprite to move - * @param target The Point coordinates to move the source Sprite towards - * @param speed The speed it will move, in pixels per second (default is 60 pixels/sec) - * @param maxTime Time given in milliseconds (1000 = 1 sec). If set the speed is adjusted so the source will arrive at destination in the given number of ms - */ - moveTowardsPoint: function (source, target, speed, maxTime) { - - speed = speed || 60; - maxTime = maxTime || 0; - - var a = this.angleBetweenPoint(source, target); - - if (maxTime > 0) - { - var d = this.distanceToPoint(source, target); - - // We know how many pixels we need to move, but how fast? - speed = d / (maxTime / 1000); - } - - source.body.velocity.x = Math.cos(a) * speed; - source.body.velocity.y = Math.sin(a) * speed; - - }, /** * Sets the x/y acceleration on the source Sprite so it will move towards the target coordinates at the speed given (in pixels per second)
@@ -1318,29 +1349,21 @@ Phaser.Physics.Arcade.prototype = { }, /** - * Find the angle (in radians) between an Sprite and the mouse, taking their x/y and origin into account. - * The angle is calculated in clockwise positive direction (down = 90 degrees positive, right = 0 degrees positive, up = 90 degrees negative) - * - * @param a The Object to test from - * @param asDegrees If you need the value in degrees instead of radians, set to true - * - * @return Number The angle (in radians unless asDegrees is true) - */ - angleBetweenMouse: function (a, asDegrees) { + * Find the angle in radians between a display object (like a Sprite) and a Pointer, taking their x/y and center into account. + * + * @param {any} displayObject - The Display Object to test from. + * @param {Phaser.Pointer} [pointer] - The Phaser.Pointer to test to. If none is given then Input.activePointer is used. + * @return {number} The angle in radians between displayObject.center.x/y to Pointer.x/y + */ + angleBetweenPointer: function (displayObject, pointer) { - asDegrees = asDegrees || false; + pointer = pointer || this.game.input.activePointer; - var dx = this.game.input.x - a.bounds.x; - var dy = this.game.input.y - a.bounds.y; + var dx = pointer.x - displayObject.x; + var dy = pointer.y - displayObject.y; - if (asDegrees) - { - return this.game.math.radToDeg(Math.atan2(dy, dx)); - } - else - { - return Math.atan2(dy, dx); - } + return Math.atan2(dy, dx); + } }; diff --git a/src/physics/arcade/Body.js b/src/physics/arcade/Body.js index ae94b6fb..1aa95208 100644 --- a/src/physics/arcade/Body.js +++ b/src/physics/arcade/Body.js @@ -221,6 +221,10 @@ Phaser.Physics.Arcade.Body.prototype = { this.angularVelocity = 0; this.angularAcceleration = 0; + this.preX = (this.sprite.worldTransform[2] - (this.sprite.anchor.x * this.width)) + this.offset.x; + this.preY = (this.sprite.worldTransform[5] - (this.sprite.anchor.y * this.height)) + this.offset.y; + this.preRotation = this.sprite.angle; + this.x = (this.sprite.worldTransform[2] - (this.sprite.anchor.x * this.width)) + this.offset.x; this.y = (this.sprite.worldTransform[5] - (this.sprite.anchor.y * this.height)) + this.offset.y; this.rotation = this.sprite.angle; diff --git a/src/utils/Debug.js b/src/utils/Debug.js index 69adbbbf..2e89e314 100644 --- a/src/utils/Debug.js +++ b/src/utils/Debug.js @@ -455,7 +455,7 @@ Phaser.Utils.Debug.prototype = { this.line('Sprite: ' + ' (' + sprite.width + ' x ' + sprite.height + ') anchor: ' + sprite.anchor.x + ' x ' + sprite.anchor.y); this.line('x: ' + sprite.x.toFixed(1) + ' y: ' + sprite.y.toFixed(1)); - this.line('angle: ' + sprite.angle + ' rotation: ' + sprite.rotation.toFixed(1)); + this.line('angle: ' + sprite.angle.toFixed(1) + ' rotation: ' + sprite.rotation.toFixed(1)); this.line('visible: ' + sprite.visible + ' in camera: ' + sprite.inCamera); this.line('body x: ' + sprite.body.x.toFixed(1) + ' y: ' + sprite.body.y.toFixed(1));