From 2fe8a3a0a7ccff70938c67ec1494e2caaeeee9c9 Mon Sep 17 00:00:00 2001 From: Richard Davey Date: Tue, 3 Sep 2013 17:07:05 +0100 Subject: [PATCH] Physics integration and a fix to Tween that stopped the repeat/yoyo from working. --- examples/body1.php | 47 +++------ examples/body2.php | 63 ++++++++++++ examples/body3.php | 53 ++++++++++ src/core/Game.js | 19 ++-- src/gameobjects/Sprite.js | 36 +++---- src/loader/Cache.js | 20 +++- src/physics/arcade/ArcadePhysics.js | 14 +-- src/physics/arcade/Body.js | 147 ++++++++++++++++++++++++++-- src/tween/Tween.js | 21 ++-- 9 files changed, 330 insertions(+), 90 deletions(-) create mode 100644 examples/body2.php create mode 100644 examples/body3.php diff --git a/examples/body1.php b/examples/body1.php index ff276dc3..07cf8781 100644 --- a/examples/body1.php +++ b/examples/body1.php @@ -16,56 +16,41 @@ function preload() { game.load.atlasJSONHash('bot', 'assets/sprites/running_bot.png', 'assets/sprites/running_bot.json'); + game.load.image('bunny', 'assets/sprites/bunny.png'); } - var s; + var bunny; + var bot; function create() { game.world._stage.backgroundColorString = '#182d3b'; - s = game.add.sprite(game.world.centerX, game.world.centerY, 'bot'); - // s.anchor.setTo(0.5, 0.5); + bunny = game.add.sprite(500, game.world.centerY, 'bunny'); + bunny.anchor.setTo(0.5, 0.5); - // s.body.offset.setTo(0, 0); + bot = game.add.sprite(150, game.world.centerY, 'bot'); + bot.anchor.setTo(0.5, 0.5); + bot.animations.add('run'); + bot.animations.play('run', 10, true); - - // s.scale.setTo(2, 2); - - s.animations.add('run'); - s.animations.play('run', 10, true); + game.add.tween(bot.scale).to({ x: 3, y: 3 }, 2000, Phaser.Easing.Linear.None, true, 0, 1000, true); } function update() { - s.rotation += 0.01; - - if (game.input.keyboard.isDown(Phaser.Keyboard.LEFT)) - { - s.x -= 4; - } - else if (game.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) - { - s.x += 4; - } - - if (game.input.keyboard.isDown(Phaser.Keyboard.UP)) - { - s.y -= 4; - } - else if (game.input.keyboard.isDown(Phaser.Keyboard.DOWN)) - { - s.y += 4; - } + bunny.angle += 1; + bot.angle += 1; } function render() { - game.debug.renderSpriteCorners(s, true, true); - // game.debug.renderRectangle(s.body.bounds, 'rgba(255,0,0,0.3)'); - game.debug.renderSpriteInfo(s, 20, 32); + game.debug.renderSpriteCorners(bunny, true, true); + game.debug.renderSpriteCorners(bot, true, true); + game.debug.renderSpriteInfo(bunny, 20, 32); + game.debug.renderSpriteInfo(bot, 20, 132); } diff --git a/examples/body2.php b/examples/body2.php new file mode 100644 index 00000000..c6272e94 --- /dev/null +++ b/examples/body2.php @@ -0,0 +1,63 @@ + + + + phaser.js - a new beginning + + + + + + + + \ No newline at end of file diff --git a/examples/body3.php b/examples/body3.php new file mode 100644 index 00000000..4fd01d89 --- /dev/null +++ b/examples/body3.php @@ -0,0 +1,53 @@ + + + + phaser.js - a new beginning + + + + + + + + \ No newline at end of file diff --git a/src/core/Game.js b/src/core/Game.js index 1f08c8e7..b3b2f867 100644 --- a/src/core/Game.js +++ b/src/core/Game.js @@ -26,13 +26,13 @@ */ Phaser.Game = function (width, height, renderer, parent, state, transparent, antialias) { - if (typeof width === "undefined") { width = 800; } - if (typeof height === "undefined") { height = 600; } - if (typeof renderer === "undefined") { renderer = Phaser.AUTO; } - if (typeof parent === "undefined") { parent = ''; } - if (typeof state === "undefined") { state = null; } - if (typeof transparent === "undefined") { transparent = false; } - if (typeof antialias === "undefined") { antialias = true; } + width = width || 800; + height = height || 600; + renderer = renderer || Phaser.AUTO; + parent = parent || ''; + state = state || null; + transparent = transparent || false; + antialias = antialias || true; this.id = Phaser.GAMES.push(this) - 1; this.parent = parent; @@ -263,7 +263,8 @@ Phaser.Game.prototype = { */ boot: function () { - if (this.isBooted) { + if (this.isBooted) + { return; } @@ -296,7 +297,7 @@ Phaser.Game.prototype = { this.tweens = new Phaser.TweenManager(this); this.input = new Phaser.Input(this); this.sound = new Phaser.SoundManager(this); - // this.physics = new Phaser.Physics.PhysicsManager(this); + this.physics = new Phaser.Physics.Arcade(this); this.plugins = new Phaser.PluginManager(this, this); this.net = new Phaser.Net(this); this.debug = new Phaser.Utils.Debug(this); diff --git a/src/gameobjects/Sprite.js b/src/gameobjects/Sprite.js index f77fd1bc..59ee393e 100644 --- a/src/gameobjects/Sprite.js +++ b/src/gameobjects/Sprite.js @@ -2,8 +2,7 @@ Phaser.Sprite = function (game, x, y, key, frame) { x = x || 0; y = y || 0; - // if null we ought to set to the phaser logo or something :) - key = key || null; + key = key || null; // if null we ought to set to the phaser logo or something :) frame = frame || null; this.game = game; @@ -14,7 +13,6 @@ Phaser.Sprite = function (game, x, y, key, frame) { this.alive = true; this.group = null; - this.name = ''; if (key) @@ -53,7 +51,7 @@ Phaser.Sprite = function (game, x, y, key, frame) { } else { - this.currentFrame = new Phaser.Animation.Frame(x, y, width, height, '', ''); + this.currentFrame = this.game.cache.getFrame(key); } /** @@ -111,13 +109,7 @@ Phaser.Sprite = function (game, x, y, key, frame) { width: this.currentFrame.sourceSizeW, height: this.currentFrame.sourceSizeH, // The actual width/height of the image if from a trimmed atlas, multiplied by the final calculated scale size - // actualWidth: 0, actualHeight: 0, - - // The actual width/height of the image if from a trimmed atlas, multiplied by the final calculated scale size - halfWidth: Math.floor(this.currentFrame.sourceSizeW), halfHeight: Math.floor(this.currentFrame.sourceSizeH), - - // The actual width/height of the image if from a trimmed atlas, multiplied by the final calculated scale size - // centerX: 0, centerY: 0, + halfWidth: Math.floor(this.currentFrame.sourceSizeW / 2), halfHeight: Math.floor(this.currentFrame.sourceSizeH / 2), // The current frame details frameID: this.currentFrame.uuid, frameWidth: this.currentFrame.width, frameHeight: this.currentFrame.height, @@ -131,7 +123,7 @@ Phaser.Sprite = function (game, x, y, key, frame) { // Corner point defaults this.offset = new Phaser.Point; - this.center = new Phaser.Point(Math.floor(this._cache.width / 2), Math.floor(this._cache.height / 2)); + this.center = new Phaser.Point(x + Math.floor(this._cache.width / 2), y + Math.floor(this._cache.height / 2)); this.topLeft = new Phaser.Point(x, y); this.topRight = new Phaser.Point(x + this._cache.width, y); this.bottomRight = new Phaser.Point(x + this._cache.width, y + this._cache.height); @@ -182,7 +174,7 @@ Phaser.Sprite.prototype.update = function() { { this._cache.a00 = this.worldTransform[0]; // scaleX a this._cache.a01 = this.worldTransform[1]; // skewY c - this._cache.scaleX = Math.sqrt((this._cache.a00 * this._cache.a00) + (this._cache.a01 * this._cache.a01)); + this._cache.scaleX = Math.sqrt((this._cache.a00 * this._cache.a00) + (this._cache.a01 * this._cache.a01)); // round this off a bit? this._cache.a01 *= -1; this._cache.dirty = true; } @@ -192,7 +184,7 @@ Phaser.Sprite.prototype.update = function() { { this._cache.a10 = this.worldTransform[3]; // skewX b this._cache.a11 = this.worldTransform[4]; // scaleY d - this._cache.scaleY = Math.sqrt((this._cache.a10 * this._cache.a10) + (this._cache.a11 * this._cache.a11)); + this._cache.scaleY = Math.sqrt((this._cache.a10 * this._cache.a10) + (this._cache.a11 * this._cache.a11)); // round this off a bit? this._cache.a10 *= -1; this._cache.dirty = true; } @@ -209,14 +201,16 @@ Phaser.Sprite.prototype.update = function() { { this._cache.frameWidth = this.texture.frame.width; this._cache.frameHeight = this.texture.frame.height; + this._cache.frameID = this.currentFrame.uuid; + this._cache.dirty = true; } if (this._cache.dirty) { - this._cache.width = this.currentFrame.sourceSizeW * this._cache.scaleX; - this._cache.height = this.currentFrame.sourceSizeH * this._cache.scaleY; - - // this.getLocalPosition(this.center, this.x - (this.anchor.x * this._cache.width), this.y - (this.anchor.y * this._cache.height)); + this._cache.width = Math.floor(this.currentFrame.sourceSizeW * this._cache.scaleX); + this._cache.height = Math.floor(this.currentFrame.sourceSizeH * this._cache.scaleY); + this._cache.halfWidth = Math.floor(this._cache.width / 2); + this._cache.halfHeight = Math.floor(this._cache.height / 2); this._cache.id = 1 / (this._cache.a00 * this._cache.a11 + this._cache.a01 * -this._cache.a10); @@ -249,10 +243,10 @@ Phaser.Sprite.prototype.update = function() { } // Update our physics bounds - this.body.update(); + this.body.update(this.center.x, this.center.y, this._cache.scaleX, this._cache.scaleY); } - // Check our bounds + this.body.updateMotion(); } @@ -262,8 +256,6 @@ Phaser.Sprite.prototype.updateBounds = function() { this.offset.setTo(this._cache.a02 - (this.anchor.x * this._cache.width), this._cache.a12 - (this.anchor.y * this._cache.height)); - // this.getLocalPosition(this.center, this.x - (this.anchor.x * this._cache.width), this.y - (this.anchor.y * this._cache.height)); - this.getLocalPosition(this.center, this.offset.x + this._cache.halfWidth, this.offset.y + this._cache.halfHeight); this.getLocalPosition(this.topLeft, this.offset.x, this.offset.y); this.getLocalPosition(this.topRight, this.offset.x + this._cache.width, this.offset.y); diff --git a/src/loader/Cache.js b/src/loader/Cache.js index 6e6d2d6d..2bca632c 100644 --- a/src/loader/Cache.js +++ b/src/loader/Cache.js @@ -115,6 +115,7 @@ Phaser.Cache.prototype = { addImage: function (key, url, data) { this._images[key] = { url: url, data: data, spriteSheet: false }; + this._images[key].frame = new Phaser.Animation.Frame(0, 0, data.width, data.height, '', ''); PIXI.BaseTextureCache[key] = new PIXI.BaseTexture(data); PIXI.TextureCache[key] = new PIXI.Texture(PIXI.BaseTextureCache[key]); @@ -129,8 +130,8 @@ Phaser.Cache.prototype = { */ addSound: function (key, url, data, webAudio, audioTag) { - if (typeof webAudio === "undefined") { webAudio = true; } - if (typeof audioTag === "undefined") { audioTag = false; } + webAudio = webAudio || true; + audioTag = audioTag || false; var locked = this.game.sound.touchLocked; var decoded = false; @@ -246,6 +247,21 @@ Phaser.Cache.prototype = { return null; }, + /** + * Get a single frame by key. You'd only do this to get the default Frame created for a non-atlas/spritesheet image. + * @param key Asset key of the frame data you want. + * @return {object} The frame data you want. + */ + getFrame: function (key) { + + if (this._images[key] && this._images[key].spriteSheet == false) + { + return this._images[key].frame; + } + + return null; + }, + /** * Get sound by key. * @param key Asset key of the sound you want. diff --git a/src/physics/arcade/ArcadePhysics.js b/src/physics/arcade/ArcadePhysics.js index 3b9f6e42..89eae036 100644 --- a/src/physics/arcade/ArcadePhysics.js +++ b/src/physics/arcade/ArcadePhysics.js @@ -27,20 +27,20 @@ Phaser.Physics.Arcade.prototype = { this._velocityDelta = (this.computeVelocity(body.angularVelocity, body.gravity.x, body.angularAcceleration, body.angularDrag, body.maxAngular) - body.angularVelocity) / 2; body.angularVelocity += this._velocityDelta; - body.sprite.rotation += body.angularVelocity * this.game.time.elapsed; + body.sprite.rotation += body.angularVelocity * this.game.time.physicsElapsed; body.angularVelocity += this._velocityDelta; this._velocityDelta = (this.computeVelocity(body.velocity.x, body.gravity.x, body.acceleration.x, body.drag.x) - body.velocity.x) / 2; body.velocity.x += this._velocityDelta; - this._delta = body.velocity.x * this.game.time.elapsed; + this._delta = body.velocity.x * this.game.time.physicsElapsed; body.velocity.x += this._velocityDelta; - body.sprite.x += this._delta; + body._x += this._delta; this._velocityDelta = (this.computeVelocity(body.velocity.y, body.gravity.y, body.acceleration.y, body.drag.y) - body.velocity.y) / 2; body.velocity.y += this._velocityDelta; - this._delta = body.velocity.y * this.game.time.elapsed; + this._delta = body.velocity.y * this.game.time.physicsElapsed; body.velocity.y += this._velocityDelta; - body.sprite.y += this._delta; + body._y += this._delta; }, @@ -63,11 +63,11 @@ Phaser.Physics.Arcade.prototype = { if (acceleration !== 0) { - velocity += (acceleration + gravity) * this.game.time.elapsed; + velocity += (acceleration + gravity) * this.game.time.physicsElapsed; } else if (drag !== 0) { - this._drag = drag * this.game.time.elapsed; + this._drag = drag * this.game.time.physicsElapsed; if (velocity - this._drag > 0) { diff --git a/src/physics/arcade/Body.js b/src/physics/arcade/Body.js index ceadb1dc..5778616d 100644 --- a/src/physics/arcade/Body.js +++ b/src/physics/arcade/Body.js @@ -2,12 +2,36 @@ Phaser.Physics.Arcade.Body = function (sprite) { this.sprite = sprite; this.game = sprite.game; - this.bounds = new Phaser.Rectangle(sprite.x, sprite.y, sprite.currentFrame.sourceSizeW, sprite.currentFrame.sourceSizeH); + this.hitArea = new Phaser.Rectangle(sprite.x, sprite.y, sprite.currentFrame.sourceSizeW, sprite.currentFrame.sourceSizeH); this.offset = new Phaser.Point; - this._w = sprite.width; - this._h = sprite.height; + this.width = this.hitArea.width; + this.height = this.hitArea.height; + this._sx = sprite.scale.x; + this._sy = sprite.scale.y; + + this.velocity = new Phaser.Point; + this.acceleration = new Phaser.Point; + this.drag = new Phaser.Point; + this.gravity = new Phaser.Point; + this.bounce = new Phaser.Point; + this.maxVelocity = new Phaser.Point(10000, 10000); + + this.angularVelocity = 0; + this.angularAcceleration = 0; + this.angularDrag = 0; + this.maxAngular = 1000; + this.mass = 1; + + this.touching = 0; + this.wasTouching = 0; + this.allowCollisions = 1; + + this._x = sprite.x; + this._y = sprite.y; + this._ox = sprite.x; + this._oy = sprite.y; }; @@ -15,15 +39,120 @@ Phaser.Physics.Arcade.Body.prototype = { sprite: null, game: null, - bounds: null, + hitArea: null, - update: function () { + update: function (x, y, scaleX, scaleY) { - this.bounds.x = this.sprite.x - (this.sprite.anchor.x * (this.offset.x * this.sprite.scale.x)); - this.bounds.y = this.sprite.y - (this.sprite.anchor.y * (this.offset.y * this.sprite.scale.y)); - this.bounds.width = this._w * this.sprite.scale.x; - this.bounds.height = this._h * this.sprite.scale.y; + if (scaleX != this._sx || scaleY != this._sy) + { + this.hitArea.width = this.width * scaleX; + this.hitArea.height = this.height * scaleY; + this._sx = scaleX; + this._sy = scaleY; + } + + this.hitArea.centerX = x; + this.hitArea.centerY = y; + + // this._ox = x; + // this._oy = y; }, + updateMotion: function () { + + this._ox = this._x; + this._oy = this._y; + + this.game.physics.updateMotion(this); + + // delta force - _x and _y now contain the new positions, so work out the deltas + // separation and stuff happens here + + }, + + postUpdate: function () { + + sprite.x = this._x; + sprite.y = this._y; + + }, + + setSize: function (width, height) { + + this.width = width; + this.height = height; + this.hitArea.width = this.width * scaleX; + this.hitArea.height = this.height * scaleY; + + }, + + hullWidth: function () { + + if (this.deltaX > 0) + { + return this.hitArea.width + this.deltaX; + } + else + { + return this.hitArea.width - this.deltaX; + } + + }, + + hullHeight: function () { + + if (this.deltaY > 0) + { + return this.hitArea.height + this.deltaY; + } + else + { + return this.hitArea.height - this.deltaY; + } + + }, + + hullX: function () { + + if (this._x < this._ox) + { + return this._x; + } + else + { + return this._ox; + } + + }, + + hullY: function () { + + if (this._y < this._oy) + { + return this._y; + } + else + { + return this._oy; + } + + }, + + deltaXAbs: function () { + return (this.deltaX > 0 ? this.deltaX : -this.deltaX); + }, + + deltaYAbs: function () { + return (this.deltaY > 0 ? this.deltaY : -this.deltaY); + }, + + deltaX: function () { + return this._x - this._ox; + }, + + deltaY: function () { + return this._y - this._oy; + } + }; \ No newline at end of file diff --git a/src/tween/Tween.js b/src/tween/Tween.js index 65c57e1d..06b8fc54 100644 --- a/src/tween/Tween.js +++ b/src/tween/Tween.js @@ -62,21 +62,24 @@ Phaser.Tween.prototype = { */ to: function ( properties, duration, ease, autoStart, delay, repeat, yoyo ) { - if (typeof duration === "undefined") { duration = 1000; } - if (typeof ease === "undefined") { ease = null; } - if (typeof autoStart === "undefined") { autoStart = false; } - if (typeof delay === "undefined") { delay = 0; } - if (typeof repeat === "undefined") { repeat = 0; } - if (typeof yoyo === "undefined") { yoyo = false; } + duration = duration || 1000; + ease = ease || null; + autoStart = autoStart || false; + delay = delay || 0; + repeat = repeat || 0; + yoyo = yoyo || false; + this._repeat = repeat; this._duration = duration; this._valuesEnd = properties; - if (ease !== null) { + if (ease !== null) + { this._easingFunction = ease; } - if (delay > 0) { + if (delay > 0) + { this._delayTime = delay; } @@ -104,8 +107,6 @@ Phaser.Tween.prototype = { this._onStartCallbackFired = false; - // this._startTime = time !== undefined ? time : ( typeof window !== 'undefined' && window.performance !== undefined && window.performance.now !== undefined ? window.performance.now() : Date.now() ); - // this._startTime += _delayTime; this._startTime = this.game.time.now + this._delayTime; for ( var property in this._valuesEnd ) {