Warning: This version has a new ArcadePhysics handler in it. Don't upgrade if you need this for live game code, wait until we go to master. Otherwise, this commit contains lots of new physics demos and a new updateMotion and Body class to try and fix, once and for all, the physics issues with applied forces.

This commit is contained in:
photonstorm 2014-01-02 23:28:22 +00:00
parent 902ffee808
commit 5526a7322b
17 changed files with 1167 additions and 136 deletions

View file

@ -84,8 +84,13 @@ New Examples:
* Physics - Bounce accelerator (use the keyboard) by Patrick OReilly.
* Physics - Bounce knock (use the keyboard) by Patrick OReilly.
* Physics - Snake (use the keyboard to control the snake like creature) by Patrick OReilly and Richard Davey.
* Physics - Launcher - Angry Birds style ball launcher demo by Patrick OReilly.
* Physics - Launcher Follow - throw the sprite anywhere in the world by Patrick OReilly.
* Physics - Launcher Follow World - an advanced version of the Launcher Follow example by Patrick OReilly.
* Input - Touch Joystick example showing how to use the clay.io virtual game controller (thanks gabehollombe)
* Games - Matching Pairs by Patrick OReilly.
* Games - Simon Says by Patrick OReilly.
* Games - Wabbits by Patrick OReilly.
* Tweens - Example showing how to use the tween events, onStart, onLoop and onComplete.
* Display - Pixi Render Texture. A Phaser conversion of the Pixi.js Render Texture example.
* Input - 5 new examples showing how to use the Gamepad API (thanks Karl Macklin)
@ -128,7 +133,7 @@ Bug Fixes:
* Fixed Group.scale so you can now scale a Group directly.
* Removed World.scale as it was preventing Group.scale from working - you can still scale the world, but you'll need to factor in Input changes yourself.
* Moved 'dirty' flag for Tilemap to a per-layer flag. Fixes #242
* Group.length now returns the number of children in the Group regardless of their exists/alive state, or 0 if the Group is has no children.
* Group.length now returns the number of children in the Group regardless of their exists/alive state, or 0 if the Group has no children.
* Switch Camera.setBoundsToWorld to match world.bounds instead of world (thanks cocoademon)
* Fixed an issue where passing null as the Group parent wouldn't set it to game.world as it should have (thanks tito100)
* Fixed Pixi bug (#425) incorrect width property for multi-line BitmapText (thanks jcd-as)
@ -143,6 +148,7 @@ Bug Fixes:
* Buttons now clear previously set frames correctly if you call setFrames.
* Sounds will now loop correctly if they are paused and resumed (thanks haden)
* InputHandler.checkBoundsRect and checkBoundsSprite now take into account if the Sprite is fixedToCamera or not.
* Removed the frame property from TileSprites as it cannot use them, it tiles the whole image only, not just a section of it.
You can view the Change Log for all previous versions at https://github.com/photonstorm/phaser/changelog.md
@ -343,3 +349,5 @@ Phaser is released under the [MIT License](http://opensource.org/licenses/MIT).
[1]: https://github.com/photonstorm/phaser/issues
[phaser]: https://github.com/photonstorm/phaser
[![Analytics](https://ga-beacon.appspot.com/UA-44006568-2/phaser/index)](https://github.com/igrigorik/ga-beacon)

View file

@ -254,6 +254,10 @@
"file": "matching+pairs.js",
"title": "matching pairs"
},
{
"file": "simon.js",
"title": "simon"
},
{
"file": "starstruck.js",
"title": "starstruck"
@ -261,6 +265,10 @@
{
"file": "tanks.js",
"title": "tanks"
},
{
"file": "wabbits.js",
"title": "wabbits"
}
],
"geometry": [
@ -608,6 +616,18 @@
"file": "framerate+independence.js",
"title": "framerate independence"
},
{
"file": "launcher+follow+world.js",
"title": "launcher follow world"
},
{
"file": "launcher+follow.js",
"title": "launcher follow"
},
{
"file": "launcher.js",
"title": "launcher"
},
{
"file": "mass+velocity+test.js",
"title": "mass velocity test"

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 710 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

214
examples/games/simon.js Normal file
View file

@ -0,0 +1,214 @@
// mods by Patrick OReilly
// Twitter: @pato_reilly Web: http://patricko.byethost9.com
var game = new Phaser.Game(800, 600, Phaser.CANVAS, 'phaser-example', { preload: preload, create: create, update: update, render: render });
function preload() {
game.load.spritesheet('item', 'assets/buttons/number-buttons.png', 160, 160);
}
var simon;
var N = 1;
var userCount = 0;
var currentCount = 0;
var sequenceCount = 16;
var sequenceList = [];
var simonSez = false;
var timeCheck;
var litSquare;
var winner;
var loser;
var intro;
function create() {
simon = game.add.group();
var item;
for (var i = 0; i < 3; i++)
{
item = simon.create(150 + 168 * i, 150, 'item', i);
// Enable input.
item.input.start(0, true);
item.events.onInputDown.add(select);
item.events.onInputUp.add(release);
item.events.onInputOut.add(moveOff);
simon.getAt(i).alpha = 0;
}
for (var i = 0; i < 3; i++)
{
item = simon.create(150 + 168 * i, 318, 'item', i + 3);
// Enable input.
item.input.start(0, true);
item.events.onInputDown.add(select);
item.events.onInputUp.add(release);
item.events.onInputOut.add(moveOff);
simon.getAt(i + 3).alpha = 0;
}
introTween();
setUp();
setTimeout(function(){simonSequence(); intro = false;}, 5000);
}
function restart() {
N = 1;
userCount = 0;
currentCount = 0;
sequenceList = [];
winner = false;
loser = false;
introTween();
setUp();
setTimeout(function(){simonSequence(); intro=false;}, 5000);
}
function introTween() {
intro = true;
for (var i = 0; i < 6; i++)
{
game.add.tween(simon.getAt(i)).to( { alpha: 1 }, 500, Phaser.Easing.Linear.None, true, 0, 4, true).to( { alpha: .25 }, 500, Phaser.Easing.Linear.None, true);
}
}
function update() {
if (simonSez)
{
if (game.time.now - timeCheck >700-N*40)
{
simon.getAt(litSquare).alpha = .25;
game.paused = true;
setTimeout(function()
{
if ( currentCount< N)
{
game.paused = false;
simonSequence();
}
else
{
simonSez = false;
game.paused = false;
}
}, 400 - N * 20);
}
}
}
function playerSequence(selected) {
correctSquare = sequenceList[userCount];
userCount++;
thisSquare = simon.getIndex(selected);
if (thisSquare == correctSquare)
{
if (userCount == N)
{
if (N == sequenceCount)
{
winner = true;
setTimeout(function(){restart();}, 3000);
}
else
{
userCount = 0;
currentCount = 0;
N++;
simonSez = true;
}
}
}
else
{
loser = true;
setTimeout(function(){restart();}, 3000);
}
}
function simonSequence () {
simonSez = true;
litSquare = sequenceList[currentCount];
simon.getAt(litSquare).alpha = 1;
timeCheck = game.time.now;
currentCount++;
}
function setUp() {
for (var i = 0; i < sequenceCount; i++)
{
thisSquare = game.rnd.integerInRange(0,6);
sequenceList.push(thisSquare);
}
}
function select(item, pointer) {
if (!simonSez && !intro && !loser && !winner)
{
item.alpha = 1;
}
}
function release(item, pointer) {
if (!simonSez && !intro && !loser && !winner)
{
item.alpha = .25;
playerSequence(item);
}
}
function moveOff(item, pointer) {
if (!simonSez && !intro && !loser && !winner)
{
item.alpha = .25;
}
}
function render() {
if (!intro)
{
if (simonSez)
{
game.debug.renderText('Simon Sez', 360, 96, 'rgb(255,0,0)');
}
else
{
game.debug.renderText('Your Turn', 360, 96, 'rgb(0,255,0)');
}
}
else
{
game.debug.renderText('Get Ready', 360, 96, 'rgb(0,0,255)');
}
if (winner)
{
game.debug.renderText('You Win!', 360, 32, 'rgb(0,0,255)');
}
else if (loser)
{
game.debug.renderText('You Lose!', 360, 32, 'rgb(0,0,255)');
}
}

162
examples/games/wabbits.js Normal file
View file

@ -0,0 +1,162 @@
// mods by Patrick OReilly
// twitter: @pato_reilly
var game = new Phaser.Game(800, 600, Phaser.CANVAS, 'phaser-example', { preload: preload, create: create, update: update, render: render });
function preload() {
game.load.image('analog', 'assets/tests/fusia.png');
game.load.image('arrow', 'assets/sprites/longarrow2.png');
game.load.image('ball', 'assets/sprites/pangball.png');
game.load.image('hill', 'assets/pics/atari_fujilogo.png');
game.load.image('block', 'assets/sprites/block.png');
game.load.image('wabbit', 'assets/sprites/wabbit.png');
}
var arrow;
var ball;
var catchFlag = false;
var wabbits;
var wab;
var launchVelocity = 0;
var shotCount = 0;
var wabbitCount = 0;
function create() {
// set global gravity
game.physics.gravity.setTo(0, 4);
game.stage.backgroundColor = '#0072bc';
var graphics = game.add.graphics(0, 0);
graphics.beginFill(0x049e0c);
graphics.drawRect(195, 450, 10, 150);
wabbits = game.add.group();
for (var i = 0; i < 5; i++)
{
wab = wabbits.create(game.rnd.integerInRange(575, 650), game.rnd.integerInRange(150, 260), 'wabbit');
wab.name = 'wab' + i;
wab.body.collideWorldBounds = true;
wab.body.mass = 0.1;
wab.body.drag.setTo(50, 50);
}
hill = game.add.sprite(450, 400, 'hill');
hill.body.collideWorldBounds = true;
hill.body.mass = 10;
hill.body.immovable = true;
block = game.add.sprite(575, 300, 'block');
block.body.collideWorldBounds = true;
block.body.mass = 5;
block.body.drag.setTo(100, 100);
analog = game.add.sprite(200, 450, 'analog');
analog.body.allowGravity = false;
analog.width = 8;
analog.rotation = 220;
analog.alpha = 0;
analog.anchor.setTo(0.5, 0.0);
arrow = game.add.sprite(200, 450, 'arrow');
arrow.anchor.setTo(0.1, 0.5);
arrow.body.allowGravity = false;
arrow.alpha = 0;
ball = game.add.sprite(100, 400, 'ball');
ball.anchor.setTo(0.5, 0.5);
ball.inputEnabled = true;
ball.body.collideWorldBounds = true;
ball.body.bounce.setTo(0.9, 0.9);
ball.body.drag.setTo(100, 100);
// Enable input.
ball.input.start(0, true);
ball.events.onInputDown.add(set);
ball.events.onInputUp.add(launch);
}
function set(ball, pointer) {
ball.body.velocity.setTo(0, 0);
ball.body.allowGravity = false;
catchFlag = true;
}
function launch() {
catchFlag = false;
shotCount++;
arrow.alpha = 0;
analog.alpha = 0;
Xvector = (arrow.x - ball.x) * 4.1;
Yvector = (arrow.y - ball.y) * 4.1;
ball.body.allowGravity = true;
ball.body.velocity.setTo(Xvector,Yvector);
}
function update() {
arrow.rotation = game.physics.angleBetween(arrow, ball);
if (catchFlag == true)
{
// Track the ball sprite to the mouse
ball.x = game.input.activePointer.worldX;
ball.y = game.input.activePointer.worldY;
arrow.alpha = 1;
analog.alpha = 0.5;
analog.rotation = arrow.rotation - 3.14 / 2;
analog.height = game.physics.distanceToPointer(arrow);
launchVelocity = analog.height;
}
game.physics.collide(ball, wabbits);
game.physics.collide(wabbits, wabbits);
game.physics.collide(wabbits, hill);
game.physics.collide(ball, hill);
game.physics.collide(block, hill);
game.physics.collide(block, ball);
game.physics.collide(block, wabbits);
// check wabbits
var wabs = 0;
for (var i = 0; i < 5; i++)
{
thisWab = wabbits.getAt(i);
if (thisWab.x > 770 && thisWab.y > 400)
{
thisWab.alive = false;
wabs++;
}
}
wabbitCount = 5 - wabs;
console.log(ball.body.y, ball.body.motionVelocity.y);
}
function render() {
game.debug.renderSpriteCollision(ball, 32, 32);
// var graphics = game.add.graphics(0, 0);
// game.context.fillStyle = 'rgba(0,0,255,0.5)';
// game.context.fillRect(770, 400, 30, 200);
// game.debug.renderText("Drag the ball to launch", 32, 32);
// game.debug.renderText("Try to get all 5 wabbits in the blue area with the least number of shots", 32, 64);
// game.debug.renderText("Shot Count: " + shotCount, 32, 96);
// game.debug.renderText("Wabbits Left: " + wabbitCount, 32, 128);
}

View file

@ -0,0 +1,149 @@
// mods by Patrick OReilly
// twitter: @pato_reilly
var game = new Phaser.Game(800, 600, Phaser.CANVAS, 'phaser-example', { preload: preload, create: create, update: update, render: render });
function preload() {
game.load.image('background','assets/misc/starfield.jpg');
game.load.image('player','assets/sprites/phaser-dude.png');
game.load.image('analog', 'assets/tests/fusia.png');
game.load.image('arrow', 'assets/sprites/longarrow2.png');
}
var myTween;
var player;
var cursors;
var arrow;
var catchFlag = false;
var launchVelocity = 0;
var launched;
function create() {
game.world.setBounds(0, 0, 5000, 600);
game.add.tileSprite(0, 0, 5000, 600, 'background');
var graphics = game.add.graphics(0,0);
graphics.beginFill(0x049e0c);
graphics.drawRect(395, 400, 10, 250);
analog = game.add.sprite(400, 400, 'analog');
analog.width = 8;
analog.rotation = 220;
analog.alpha = 0;
analog.anchor.setTo(0.5, 0.0);
arrow = game.add.sprite(400, 400, 'arrow');
arrow.anchor.setTo(0.1, 0.5);
arrow.alpha = 0;
player = game.add.sprite(150, 320, 'player');
player.anchor.setTo(0.5, 0.5);
player.body.collideWorldBounds = true;
player.body.bounce.setTo(0.9, 0.9);
player.body.drag.setTo(100, 100);
player.body.gravity.setTo(0, 8);
// Enable input.
player.inputEnabled = true;
player.input.start(0, true);
player.events.onInputDown.add(set);
player.events.onInputUp.add(launch);
//player.events.onInputOut.add(launch);
// this tween is to make the camera return to left side of world when done launching
// so it is not used until then
myTween = game.add.tween(player).to({x: 150}, 5000, Phaser.Easing.Linear.None);
myTween.onComplete.add(reappear, this);
game.camera.follow(player, Phaser.Camera.FOLLOW_TOPDOWN);
}
function reappear() {
launched = false;
player.alpha = 1;
}
function set(player,pointer) {
//disallow launching until reset
if (!launched)
{
catchFlag = true;
game.camera.follow(null);
player.body.gravity.setTo(0,0);
player.body.velocity.setTo(0,0);
}
}
function launch() {
if (catchFlag)
{
catchFlag = false;
launched = true;
game.camera.follow(player, Phaser.Camera.FOLLOW_TOPDOWN);
arrow.alpha = 0;
analog.alpha = 0;
Xvector = (arrow.x - player.x)*3.8;
Yvector = (arrow.y - player.y)*3.8;
player.body.gravity.setTo(0,8);
player.body.velocity.setTo(Xvector,Yvector);
}
}
function update() {
arrow.rotation = game.physics.angleBetween(arrow, player);
// Track the player sprite to the mouse
if (catchFlag)
{
distance = game.physics.distanceToPointer(arrow);
theta = game.physics.angleToPointer(arrow);
// Govern the distance the sprite is dragged away from launch post
if (distance > 300)
{
distance = 300;
adjacentX = Math.cos(theta) * distance;
oppositeY = Math.sin(theta) * distance;
player.x = 400 + adjacentX;
player.y = 400 + oppositeY;
analog.height = distance;
}
else
{
player.x = game.input.activePointer.worldX;
player.y = game.input.activePointer.worldY;
analog.height = distance;
}
arrow.alpha = 1;
analog.alpha = 0.5;
analog.rotation = arrow.rotation - Math.PI/2;
launchVelocity = analog.height;
}
//check sprite motion and if done, return camera to left side of world
var tweening = myTween.isRunning;
if (!tweening && launched && (player.x >= game.world.width-20 || player.body.deltaX() == 0))
{
player.body.velocity.setTo(0, 0);
player.alpha = 0;
myTween.start();
}
}
function render() {
game.debug.renderText("Drag the sprite and release to launch", 32, 32, 'rgb(0,255,0)');
game.debug.renderCameraInfo(game.camera, 32, 64);
game.debug.renderSpriteCoords(player, 32, 150);
game.debug.renderText("Launch Velocity: " + parseInt(launchVelocity), 550, 32, 'rgb(0,255,0)');
}

View file

@ -0,0 +1,102 @@
// mods by Patrick OReilly
// twitter: @pato_reilly
var game = new Phaser.Game(800, 600, Phaser.CANVAS, 'phaser-example', { preload: preload, create: create, update: update, render: render });
function preload() {
game.load.image('background','assets/misc/starfield.jpg');
game.load.image('player','assets/sprites/phaser-dude.png');
game.load.image('analog', 'assets/tests/fusia.png');
game.load.image('arrow', 'assets/sprites/longarrow2.png');
}
var player;
var cursors;
var arrow;
var catchFlag = false;
var launchVelocity = 0;
function create() {
game.world.setBounds(0, 0, 3400, 1000);
game.add.tileSprite(0, 0, 3400, 1000, 'background');
analog = game.add.sprite(200, 450, 'analog');
analog.width = 8;
analog.rotation = 220;
analog.alpha = 0;
analog.anchor.setTo(0.5, 0.0);
arrow = game.add.sprite(200, 450, 'arrow');
arrow.anchor.setTo(0.1, 0.5);
arrow.alpha = 0;
player = game.add.sprite(150, 320, 'player');
player.anchor.setTo(0.5, 0.5);
player.body.collideWorldBounds = true;
player.body.bounce.setTo(0.9, 0.9);
player.body.drag.setTo(50, 50);
// Enable input.
player.inputEnabled = true;
player.input.start(0, true);
player.events.onInputDown.add(set);
player.events.onInputUp.add(launch);
game.camera.follow(player, Phaser.Camera.FOLLOW_TOPDOWN);
}
function set(player,pointer) {
catchFlag = true;
game.camera.follow(null);
player.body.velocity.setTo(0, 0);
arrow.reset(player.x, player.y);
analog.reset(player.x, player.y);
}
function launch() {
catchFlag = false;
game.camera.follow(player, Phaser.Camera.FOLLOW_TOPDOWN);
arrow.alpha = 0;
analog.alpha = 0;
Xvector = (arrow.x - player.x) * 4.1;
Yvector = (arrow.y - player.y) * 4.1;
player.body.velocity.setTo(Xvector,Yvector);
}
function update() {
arrow.rotation = game.physics.angleBetween(arrow, player);
if (catchFlag == true)
{
// Track the ball sprite to the mouse
player.x = game.input.activePointer.worldX;
player.y = game.input.activePointer.worldY;
arrow.alpha = 1;
analog.alpha = 0.5;
analog.rotation = arrow.rotation - 3.14 / 2;
analog.height = game.physics.distanceBetween(arrow, player);
launchVelocity = analog.height;
}
}
function render() {
game.debug.renderText("Drag the sprite and release to launch", 32, 32, 'rgb(0,255,0)');
game.debug.renderCameraInfo(game.camera, 32, 64);
game.debug.renderSpriteCoords(player, 32, 150);
game.debug.renderText("Launch Velocity: " + parseInt(launchVelocity), 550, 32, 'rgb(0,255,0)');
}

View file

@ -0,0 +1,101 @@
// mods by Patrick OReilly
// twitter: @pato_reilly
var game = new Phaser.Game(800, 600, Phaser.CANVAS, 'phaser-example', { preload: preload, create: create, update: update, render: render });
function preload() {
game.load.image('analog', 'assets/tests/fusia.png');
game.load.image('arrow', 'assets/sprites/longarrow2.png');
game.load.image('ball', 'assets/sprites/pangball.png');
}
var arrow;
var ball;
var catchFlag = false;
var launchVelocity = 0;
function create() {
// set global gravity
game.physics.gravity.setTo(0,8);
game.stage.backgroundColor = '#0072bc';
var graphics = game.add.graphics(0,0);
graphics.beginFill(0x049e0c);
graphics.drawRect(395, 350, 10, 250);
analog = game.add.sprite(400, 350, 'analog');
analog.body.allowGravity = false;
analog.width = 8;
analog.rotation = 220;
analog.alpha = 0;
analog.anchor.setTo(0.5, 0.0);
arrow = game.add.sprite(400, 350, 'arrow');
arrow.anchor.setTo(0.1, 0.5);
arrow.body.allowGravity = false;
arrow.alpha = 0;
ball = game.add.sprite(100, 400, 'ball');
ball.anchor.setTo(0.5, 0.5);
ball.body.collideWorldBounds = true;
ball.body.bounce.setTo(0.9, 0.9);
ball.body.drag.setTo(50, 50);
// Enable input.
ball.inputEnabled = true;
ball.input.start(0, true);
ball.events.onInputDown.add(set);
ball.events.onInputUp.add(launch);
}
function set(ball, pointer) {
ball.body.velocity.setTo(0, 0);
ball.body.allowGravity = false;
catchFlag = true;
}
function launch() {
catchFlag = false;
arrow.alpha = 0;
analog.alpha = 0;
Xvector = (arrow.x - ball.x) * 4.1;
Yvector = (arrow.y - ball.y) * 4.1;
ball.body.allowGravity = true;
ball.body.velocity.setTo(Xvector,Yvector);
}
function update() {
arrow.rotation = game.physics.angleBetween(arrow, ball);
if (catchFlag == true)
{
// Track the ball sprite to the mouse
ball.x = game.input.activePointer.worldX;
ball.y = game.input.activePointer.worldY;
arrow.alpha = 1;
analog.alpha = 0.5;
analog.rotation = arrow.rotation - 3.14/2;
analog.height = game.physics.distanceToPointer(arrow);
launchVelocity = analog.height;
}
}
function render() {
game.debug.renderText("Drag the ball and release to launch", 32, 32);
game.debug.renderSpriteInfo(ball, 32, 64);
game.debug.renderText("Launch Velocity: " + parseInt(launchVelocity), 32, 250);
}

View file

@ -0,0 +1,57 @@
var game = new Phaser.Game(800, 600, Phaser.CANVAS, 'phaser-example', { preload: preload, create: create, update: update, render: render });
function preload() {
game.load.image('chunk', 'assets/sprites/chunk.png');
}
var sprite;
var bmd;
function create() {
game.stage.backgroundColor = '#2384e7';
bmd = game.add.bitmapData(800, 600);
bmd.fillStyle('#ffffff');
game.add.sprite(0, 0, bmd);
sprite = game.add.sprite(32, 600, 'chunk');
sprite.body.collideWorldBounds = true;
sprite.body.bounce.setTo(0.5, 0.5);
sprite.body.drag.setTo(0, -20);
// sprite.body.drag.setTo(2, 0);
// sprite.body.sleepMin.setTo(-50, -20);
// sprite.body.sleepMax.setTo(50, 20);
// sprite.body.sleepDuration = 1000;
sprite.body.sleepMin.setTo(0, -5);
sprite.body.sleepMax.setTo(0, 5);
sprite.body.sleepDuration = 1000;
game.input.onDown.add(launch, this);
}
function launch() {
sprite.body.velocity.setTo(0, -300);
// sprite.body.gravity.setTo(0, 200);
}
function update() {
bmd.fillRect(sprite.x, sprite.y, 2, 2);
}
function render() {
game.debug.renderBodyInfo(sprite, 16, 16);
}

View file

@ -144,15 +144,14 @@ Phaser.GameObjectFactory.prototype = {
* @param {number} width - the width of the tilesprite.
* @param {number} height - the height of the tilesprite.
* @param {string|Phaser.RenderTexture|PIXI.Texture} key - This is the image or texture used by the Sprite during rendering. It can be a string which is a reference to the Cache entry, or an instance of a RenderTexture or PIXI.Texture.
* @param {string|number} frame - If this Sprite is using part of a sprite sheet or texture atlas you can specify the exact frame to use by giving a string or numeric index.
* @param {Phaser.Group} [group] - Optional Group to add the object to. If not specified it will be added to the World group.
* @return {Phaser.TileSprite} The newly created tileSprite object.
*/
tileSprite: function (x, y, width, height, key, frame, group) {
tileSprite: function (x, y, width, height, key, group) {
if (typeof group === 'undefined') { group = this.world; }
return group.add(new Phaser.TileSprite(this.game, x, y, width, height, key, frame));
return group.add(new Phaser.TileSprite(this.game, x, y, width, height, key));
},

View file

@ -15,18 +15,16 @@
* @param {number} width - the width of the tilesprite.
* @param {number} height - the height of the tilesprite.
* @param {string|Phaser.RenderTexture|PIXI.Texture} key - This is the image or texture used by the Sprite during rendering. It can be a string which is a reference to the Cache entry, or an instance of a RenderTexture or PIXI.Texture.
* @param {string|number} frame - If this Sprite is using part of a sprite sheet or texture atlas you can specify the exact frame to use by giving a string or numeric index.
*/
Phaser.TileSprite = function (game, x, y, width, height, key, frame) {
Phaser.TileSprite = function (game, x, y, width, height, key) {
x = x || 0;
y = y || 0;
width = width || 256;
height = height || 256;
key = key || null;
frame = frame || null;
Phaser.Sprite.call(this, game, x, y, key, frame);
Phaser.Sprite.call(this, game, x, y, key);
/**
* @property {PIXI.Texture} texture - The texture that the sprite renders with.

View file

@ -167,7 +167,7 @@ Phaser.Physics.Arcade.prototype = {
* @method Phaser.Physics.Arcade#updateMotion
* @param {Phaser.Physics.Arcade.Body} The Body object to be updated.
*/
updateMotion: function (body) {
OLDupdateMotion: function (body) {
// If you're wondering why the velocity is halved and applied twice, read this: http://www.niksula.hut.fi/~hkankaan/Homepages/gravity.html
@ -177,27 +177,120 @@ Phaser.Physics.Arcade.prototype = {
body.rotation += (body.angularVelocity * this.game.time.physicsElapsed);
body.angularVelocity += this._velocityDelta;
if(body.allowGravity)
if (body.allowGravity)
{
// Gravity was previously applied without taking physicsElapsed into account
// so it needs to be multiplied by 60 (fps) for compatibility with existing games
this._gravityX = (this.gravity.x + body.gravity.x) * 60;
this._gravityY = (this.gravity.y + body.gravity.y) * 60;
} else {
this._gravityX = this._gravityY = 0;
}
else
{
this._gravityX = 0;
this._gravityY = 0;
}
body.motionVelocity.x = (this.computeVelocity(body, body.velocity.x, body.acceleration.x, body.drag.x, body.maxVelocity.x, this._gravityX) - body.velocity.x) * 0.5;
body.motionVelocity.y = (this.computeVelocity(body, body.velocity.y, body.acceleration.y, body.drag.y, body.maxVelocity.y, this._gravityY) - body.velocity.y) * 0.5;
// Horizontal
this._velocityDelta = (this.computeVelocity(body, body.velocity.x, body.acceleration.x, body.drag.x, body.maxVelocity.x, this._gravityX) - body.velocity.x) * 0.5;
body.velocity.x += this._velocityDelta;
body.x += (body.velocity.x * this.game.time.physicsElapsed);
body.velocity.x += this._velocityDelta;
// this._velocityDelta = (this.computeVelocity(body, body.velocity.x, body.acceleration.x, body.drag.x, body.maxVelocity.x, this._gravityX) - body.velocity.x) * 0.5;
// body.velocity.x += this._velocityDelta;
// body.x += (body.velocity.x * this.game.time.physicsElapsed);
// body.velocity.x += this._velocityDelta;
// Vertical
this._velocityDelta = (this.computeVelocity(body, body.velocity.y, body.acceleration.y, body.drag.y, body.maxVelocity.y, this._gravityY) - body.velocity.y) * 0.5;
body.velocity.y += this._velocityDelta;
body.y += (body.velocity.y * this.game.time.physicsElapsed);
body.velocity.y += this._velocityDelta;
// this._velocityDelta = (this.computeVelocity(body, body.velocity.y, body.acceleration.y, body.drag.y, body.maxVelocity.y, this._gravityY) - body.velocity.y) * 0.5;
// body.motionVelocity.y = this._velocityDelta;
// body.velocity.y += this._velocityDelta;
// body.y += (body.velocity.y * this.game.time.physicsElapsed);
// body.velocity.y += this._velocityDelta;
},
/**
* Called automatically by a Physics body, it updates all motion related values on the Body.
*
* @method Phaser.Physics.Arcade#updateMotion
* @param {Phaser.Physics.Arcade.Body} The Body object to be updated.
*/
updateMotion: function (body) {
// If you're wondering why the velocity is halved and applied twice, read this: http://www.niksula.hut.fi/~hkankaan/Homepages/gravity.html
if (body.allowGravity)
{
this._gravityX = (this.gravity.x + body.gravity.x);
this._gravityY = (this.gravity.y + body.gravity.y);
}
else
{
this._gravityX = 0;
this._gravityY = 0;
}
// Rotation
// this._velocityDelta = (this.computeVelocity(body, body.angularVelocity, body.angularAcceleration, body.angularDrag, body.maxAngular, 0) - body.angularVelocity) * 0.5;
// body.angularVelocity += this._velocityDelta;
// body.rotation += (body.angularVelocity * this.game.time.physicsElapsed);
// body.angularVelocity += this._velocityDelta;
// body.motionVelocity.x = (this.computeVelocity(body, body.velocity.x, body.acceleration.x, body.drag.x, body.maxVelocity.x, this._gravityX) - body.velocity.x) * 0.5;
// body.motionVelocity.y = (this.computeVelocity(body, body.velocity.y, body.acceleration.y, body.drag.y, body.maxVelocity.y, this._gravityY) - body.velocity.y) * 0.5;
// velocity = velocity + gravity*delta_time/2
// position = position + velocity*delta_time
// velocity = velocity + gravity*delta_time/2
// temp = acc*dt
// pos = pos + dt*(vel + temp/2)
// vel = vel + temp
this._drag = 0;
if (body.drag.x !== 0 && body.velocity.x !== 0 && body.acceleration.x === 0)
{
if (body.velocity.x - body.drag.x > 0)
{
this._drag = -body.drag.x;
}
else if (body.velocity.x + body.drag.x < 0)
{
this._drag = body.drag.x;
}
}
// body.motionVelocity.x = body.acceleration.x + this._gravityX - body.drag.x * this.game.time.physicsElapsed;
// body.motionVelocity.x = body.acceleration.x + this._gravityX * this.game.time.physicsElapsed;
body.motionVelocity.x = (body.acceleration.x + this._gravityX + this._drag) * this.game.time.physicsElapsed;
this._drag = 0;
if (body.drag.y !== 0 && body.velocity.y !== 0 && body.acceleration.y === 0)
{
if (body.velocity.y - body.drag.y > 0)
{
this._drag = -body.drag.y;
}
else if (body.velocity.y + body.drag.y < 0)
{
this._drag = body.drag.y;
}
}
// body.motionVelocity.y = body.acceleration.y + this._gravityY - body.drag.y * this.game.time.physicsElapsed;
// body.motionVelocity.y = body.acceleration.y + this._gravityY * this.game.time.physicsElapsed;
body.motionVelocity.y = (body.acceleration.y + this._gravityY + this._drag) * this.game.time.physicsElapsed;
// if (body.sleeping === false)
// {
// body.x = body.x + this.game.time.physicsElapsed * (body.velocity.x + body.motionVelocity.x / 2);
// body.velocity.x = body.velocity.x + body.motionVelocity.x;
// body.y = body.y + this.game.time.physicsElapsed * (body.velocity.y + body.motionVelocity.y / 2);
// body.velocity.y = body.velocity.y + body.motionVelocity.y;
// }
},
@ -213,7 +306,56 @@ Phaser.Physics.Arcade.prototype = {
* @param {number} gravity - The acceleration due to gravity. Gravity will not induce drag.
* @return {number} The altered Velocity value.
*/
computeVelocity: function (body, velocity, acceleration, drag, max, gravity) {
computeVelocity: function (body, velocity, acceleration, drag, max) {
max = max || 10000;
velocity += acceleration;
if (acceleration === 0 && drag !== 0)
{
this._drag = drag;
if (velocity - this._drag > 0)
{
velocity -= this._drag;
}
else if (velocity + this._drag < 0)
{
velocity += this._drag;
}
else
{
velocity = 0;
}
}
if (velocity > max)
{
velocity = max;
}
else if (velocity < -max)
{
velocity = -max;
}
return velocity;
},
/**
* A tween-like function that takes a starting velocity and some other factors and returns an altered velocity.
*
* @method Phaser.Physics.Arcade#computeVelocity
* @param {Phaser.Physics.Arcade.Body} body - The Body object to be updated.
* @param {number} velocity - Any component of velocity (e.g. 20).
* @param {number} acceleration - Rate at which the velocity is changing.
* @param {number} drag - Really kind of a deceleration, this is how much the velocity changes if Acceleration is not set.
* @param {number} [max=10000] - An absolute value cap for the velocity.
* @param {number} gravity - The acceleration due to gravity. Gravity will not induce drag.
* @return {number} The altered Velocity value.
*/
OLDcomputeVelocity: function (body, velocity, acceleration, drag, max, gravity) {
max = max || 10000;

View file

@ -121,11 +121,21 @@ Phaser.Physics.Arcade.Body = function (sprite) {
*/
this._sy = sprite.scale.y;
/**
* @property {Phaser.Point} motionVelocity - The data from the updateMotion function.
*/
this.motionVelocity = new Phaser.Point();
/**
* @property {Phaser.Point} velocity - The velocity in pixels per second sq. of the Body.
*/
this.velocity = new Phaser.Point();
/**
* @property {Phaser.Point} prevVelocity - The velocity in pixels per second sq. of the Body.
*/
this.prevVelocity = new Phaser.Point();
/**
* @property {Phaser.Point} acceleration - The velocity in pixels per second sq. of the Body.
*/
@ -137,7 +147,7 @@ Phaser.Physics.Arcade.Body = function (sprite) {
this.drag = new Phaser.Point();
/**
* @property {Phaser.Point} gravity - A private Gravity setting for the Body.
* @property {Phaser.Point} gravity - The gravity applied to the motion of the Body.
*/
this.gravity = new Phaser.Point();
@ -232,7 +242,7 @@ Phaser.Physics.Arcade.Body = function (sprite) {
this.facing = Phaser.NONE;
/**
* @property {boolean} immovable - An immovable Body will not receive any impacts from other bodies.
* @property {boolean} immovable - An immovable Body will not receive any impacts or exchanges of velocity from other bodies.
* @default
*/
this.immovable = false;
@ -289,17 +299,16 @@ Phaser.Physics.Arcade.Body = function (sprite) {
*/
this.overlapY = 0;
this.hull = new Phaser.Rectangle();
/**
* @property {Phaser.Rectangle} hullX - The dynamically calculated hull used during collision.
* @property {boolean} canSleep - A Body that canSleep will have its velocity set to zero if it falls below sleepThreshold for longer than sleepDuration.
* @default
*/
this.hullX = new Phaser.Rectangle();
/**
* @property {Phaser.Rectangle} hullY - The dynamically calculated hull used during collision.
*/
this.hullY = new Phaser.Rectangle();
this.sleeping = true;
this.canSleep = true;
this.sleepMin = new Phaser.Point(-20, -20);
this.sleepMax = new Phaser.Point(20, 20);
this.sleepDuration = 2000; // ms
this._sleepTimer = 0; // ms
/**
* If a body is overlapping with another body, but neither of them are moving (maybe they spawned on-top of each other?) this is set to true.
@ -368,16 +377,18 @@ Phaser.Physics.Arcade.Body.prototype = {
this.preX = (this.sprite.world.x - (this.sprite.anchor.x * this.width)) + this.offset.x;
this.preY = (this.sprite.world.y - (this.sprite.anchor.y * this.height)) + this.offset.y;
this.preRotation = this.sprite.angle;
if (this.canSleep && this.sleeping && this.velocity.equals(this.prevVelocity) === false)
{
this.sleeping = false;
this._sleepTimer = 0;
}
this.x = this.preX;
this.y = this.preY;
this.rotation = this.preRotation;
// this.overlapX = 0;
// this.overlapY = 0;
this.blocked.up = false;
this.blocked.down = false;
this.blocked.left = false;
@ -392,10 +403,46 @@ Phaser.Physics.Arcade.Body.prototype = {
this.checkWorldBounds();
}
// this.hull.setTo(this.preX, this.preY, this.width, this.height);
// this.hullX.setTo(this.x, this.preY, this.width, this.height);
// this.hullY.setTo(this.preX, this.y, this.width, this.height);
// this.updateHulls(true);
if (this.velocity.x > this.maxVelocity.x)
{
this.velocity.x = this.maxVelocity.x;
}
else if (this.velocity.x < -this.maxVelocity.x)
{
this.velocity.x = -this.maxVelocity.x;
}
if (this.canSleep)
{
if (!this.sleeping)
{
if (this.velocity.x >= this.sleepMin.x && this.velocity.x <= this.sleepMax.x && this.velocity.y >= this.sleepMin.y && this.velocity.y <= this.sleepMax.y)
{
if (this._sleepTimer >= this.sleepDuration)
{
console.log('sleeping true');
this.sleeping = true;
// this.velocity.setTo(0, 0);
// this.motionVelocity.setTo(0, 0);
// this.preX = this.x;
// this.preY = this.y;
}
else
{
this._sleepTimer += this.game.time.elapsed;
this.applyMotion();
}
}
else
{
this.applyMotion();
}
}
}
else
{
this.applyMotion();
}
}
if (this.skipQuadTree === false && this.allowCollision.none === false && this.sprite.visible && this.sprite.alive)
@ -405,99 +452,69 @@ Phaser.Physics.Arcade.Body.prototype = {
this.game.physics.quadTree.insert(this);
}
this.prevVelocity.copyFrom(this.velocity);
},
applyMotion: function () {
this.x = this.x + this.game.time.physicsElapsed * (this.velocity.x + this.motionVelocity.x / 2);
this.velocity.x = this.velocity.x + this.motionVelocity.x;
this.y = this.y + this.game.time.physicsElapsed * (this.velocity.y + this.motionVelocity.y / 2);
this.velocity.y = this.velocity.y + this.motionVelocity.y;
},
/**
* Internal method.
* Internal method. This is called directly before the sprites are sent to the renderer.
*
* @method Phaser.Physics.Arcade#postUpdate
* @protected
*/
postUpdate: function () {
// if (this.overlapX !== 0)
// {
// this.x -= this.overlapX;
// }
// if (this.overlapY !== 0)
// {
// this.y -= this.overlapY;
// }
if (this.deltaX() < 0 && this.blocked.left === false)
if (this.moves)
{
this.facing = Phaser.LEFT;
this.sprite.x += this.deltaX();
}
else if (this.deltaX() > 0 && this.blocked.right === false)
{
this.facing = Phaser.RIGHT;
this.sprite.x += this.deltaX();
}
if (this.collideWorldBounds)
{
// this.checkWorldBounds();
}
if (this.deltaY() < 0 && this.blocked.up === false)
{
this.facing = Phaser.UP;
this.sprite.y += this.deltaY();
}
else if (this.deltaY() > 0 && this.blocked.down === false)
{
this.facing = Phaser.DOWN;
this.sprite.y += this.deltaY();
}
if (this.deltaX() < 0 && this.blocked.left === false)
{
this.facing = Phaser.LEFT;
this.sprite.x += this.deltaX();
}
else if (this.deltaX() > 0 && this.blocked.right === false)
{
this.facing = Phaser.RIGHT;
this.sprite.x += this.deltaX();
}
// if (this.deltaY() !== 0 && this.blocked.up === false && this.blocked.down === false)
// {
// this.sprite.y += this.deltaY();
// }
if (this.deltaY() < 0 && this.blocked.up === false)
{
this.facing = Phaser.UP;
this.sprite.y += this.deltaY();
}
else if (this.deltaY() > 0 && this.blocked.down === false)
{
this.facing = Phaser.DOWN;
this.sprite.y += this.deltaY();
}
// if (this.deltaX() !== 0 || this.deltaY() !== 0)
// {
// this.sprite.x += this.deltaX();
// this.sprite.y += this.deltaY();
// this.center.setTo(this.x + this.halfWidth, this.y + this.halfHeight);
// }
// if (this.deltaX() !== 0 || this.deltaY() !== 0)
// {
this.center.setTo(this.x + this.halfWidth, this.y + this.halfHeight);
// }
if (this.allowRotation)
{
this.sprite.angle += this.deltaZ();
if (this.allowRotation)
{
this.sprite.angle += this.deltaZ();
}
}
},
/**
* Internal method.
*
* @method Phaser.Physics.Arcade#updateHulls
* @protected
*/
updateHulls: function (separation) {
// this.hull.setTo(this.x, this.y, this.width, this.height);
// if (separation)
// {
// this.hullX.setTo(this.x, this.preY, this.width, this.height);
// this.hullY.setTo(this.preX, this.y, this.width, this.height);
// }
// else
// {
// if this has separated then the preX/Y values are no longer valid
// this.hullX.setTo(this.x, this.y, this.width, this.height);
// this.hullY.setTo(this.x, this.y, this.width, this.height);
// }
},
/**
* Internal method.
* Internal method used to check the Body against the World Bounds.
*
* @method Phaser.Physics.Arcade#checkWorldBounds
* @protected
@ -506,22 +523,26 @@ Phaser.Physics.Arcade.Body.prototype = {
if (this.x < this.game.world.bounds.x)
{
this.blocked.left = true;
this.x = this.game.world.bounds.x;
this.velocity.x *= -this.bounce.x;
}
else if (this.right > this.game.world.bounds.right)
{
this.blocked.right = true;
this.x = this.game.world.bounds.right - this.width;
this.velocity.x *= -this.bounce.x;
}
if (this.y < this.game.world.bounds.y)
{
this.blocked.up = true;
this.y = this.game.world.bounds.y;
this.velocity.y *= -this.bounce.y;
}
else if (this.bottom > this.game.world.bounds.bottom)
{
this.blocked.down = true;
this.y = this.game.world.bounds.bottom - this.height;
this.velocity.y *= -this.bounce.y;
}

View file

@ -58,7 +58,7 @@ Phaser.Time = function (game) {
this.now = 0;
/**
* @property {number} elapsed - Elapsed time since the last frame.
* @property {number} elapsed - Elapsed time since the last frame (in ms).
*/
this.elapsed = 0;

View file

@ -30,6 +30,11 @@ Phaser.Utils.Debug = function (game) {
*/
this.font = '14px Courier';
/**
* @property {number} columnWidth - The spacing between columns.
*/
this.columnWidth = 100;
/**
* @property {number} lineHeight - The line height between the debug text.
*/
@ -65,11 +70,12 @@ Phaser.Utils.Debug.prototype = {
/**
* Internal method that resets and starts the debug output values.
* @method Phaser.Utils.Debug#start
* @param {number} x - The X value the debug info will start from.
* @param {number} y - The Y value the debug info will start from.
* @param {string} color - The color the debug info will drawn in.
* @param {number} [x=0] - The X value the debug info will start from.
* @param {number} [y=0] - The Y value the debug info will start from.
* @param {string} [color='rgb(255,255,255)'] - The color the debug text will drawn in.
* @param {number} [columnWidth=0] - The spacing between columns.
*/
start: function (x, y, color) {
start: function (x, y, color, columnWidth) {
if (this.context == null)
{
@ -78,13 +84,14 @@ Phaser.Utils.Debug.prototype = {
if (typeof x !== 'number') { x = 0; }
if (typeof y !== 'number') { y = 0; }
color = color || 'rgb(255,255,255)';
if (typeof columnWidth === 'undefined') { columnWidth = 0; }
this.currentX = x;
this.currentY = y;
this.currentColor = color;
this.currentAlpha = this.context.globalAlpha;
this.columnWidth = columnWidth;
this.context.save();
this.context.setTransform(1, 0, 0, 1, 0, 0);
@ -100,7 +107,6 @@ Phaser.Utils.Debug.prototype = {
*/
stop: function () {
this.context.restore();
this.context.globalAlpha = this.currentAlpha;
@ -110,8 +116,8 @@ Phaser.Utils.Debug.prototype = {
* Internal method that outputs a single line of text.
* @method Phaser.Utils.Debug#line
* @param {string} text - The line of text to draw.
* @param {number} x - The X value the debug info will start from.
* @param {number} y - The Y value the debug info will start from.
* @param {number} [x] - The X value the debug info will start from.
* @param {number} [y] - The Y value the debug info will start from.
*/
line: function (text, x, y) {
@ -120,16 +126,8 @@ Phaser.Utils.Debug.prototype = {
return;
}
x = x || null;
y = y || null;
if (x !== null) {
this.currentX = x;
}
if (y !== null) {
this.currentY = y;
}
if (typeof x !== 'undefined') { this.currentX = x; }
if (typeof y !== 'undefined') { this.currentY = y; }
if (this.renderShadow)
{
@ -143,6 +141,38 @@ Phaser.Utils.Debug.prototype = {
},
/**
* Internal method that outputs a single line of text split over as many columns as needed, one per parameter.
* @method Phaser.Utils.Debug#splitline
* @param {string} text - The text to render. You can have as many columns of text as you want, just pass them as additional parameters.
*/
splitline: function (text) {
if (this.context == null)
{
return;
}
var x = this.currentX;
for (var i = 0; i < arguments.length; i++)
{
if (this.renderShadow)
{
this.context.fillStyle = 'rgb(0,0,0)';
this.context.fillText(arguments[i], x + 1, this.currentY + 1);
this.context.fillStyle = this.currentColor;
}
this.context.fillText(arguments[i], x, this.currentY);
x += this.columnWidth;
}
this.currentY += this.lineHeight;
},
/**
* Visually renders a QuadTree to the display.
* @method Phaser.Utils.Debug#renderQuadTree
@ -399,14 +429,42 @@ Phaser.Utils.Debug.prototype = {
color = color || 'rgb(255,255,255)';
this.start(x, y, color);
this.line('Sprite Collision: (' + sprite.width + ' x ' + sprite.height + ')');
this.start(x, y, color, 100);
this.line('Body: (width: ' + sprite.width + ' height: ' + sprite.height + ')');
this.line('left: ' + sprite.body.touching.left);
this.line('right: ' + sprite.body.touching.right);
this.line('up: ' + sprite.body.touching.up);
this.line('down: ' + sprite.body.touching.down);
this.line('velocity.x: ' + sprite.body.velocity.x);
this.line('velocity.y: ' + sprite.body.velocity.y);
this.stop();
},
/**
* Render Sprite Body Physics Data as text.
* @method Phaser.Utils.Debug#renderBodyInfo
* @param {Phaser.Sprite} sprite - The sprite to be rendered.
* @param {number} x - X position of the debug info to be rendered.
* @param {number} y - Y position of the debug info to be rendered.
* @param {string} [color='rgb(255,255,255)'] - color of the debug info to be rendered. (format is css color string).
*/
renderBodyInfo: function (sprite, x, y, color) {
color = color || 'rgb(255,255,255)';
this.start(x, y, color, 220);
this.splitline('Width: ' + sprite.width, 'Height: ' + sprite.height);
this.splitline('x: ' + sprite.body.x.toFixed(2), 'y: ' + sprite.body.y.toFixed(2));
this.splitline('old x: ' + sprite.body.preX.toFixed(2), 'y: ' + sprite.body.preY.toFixed(2));
this.splitline('drag x: ' + sprite.body.drag.x, 'y: ' + sprite.body.drag.y);
this.splitline('gravity x: ' + sprite.body.gravity.x, 'y: ' + sprite.body.gravity.y);
this.splitline('acceleration x: ' + sprite.body.acceleration.x.toFixed(2), 'y: ' + sprite.body.acceleration.y.toFixed(2));
this.splitline('velocity x: ' + sprite.body.velocity.x.toFixed(2), 'y: ' + sprite.body.velocity.y.toFixed(2));
this.splitline('motion x: ' + sprite.body.motionVelocity.x.toFixed(2), 'y: ' + sprite.body.motionVelocity.y.toFixed(2));
this.splitline('sleeping: ' + sprite.body.sleeping, 'sleepTimer: ' + sprite.body._sleepTimer.toFixed(2));
this.splitline('sleepMin x: ' + sprite.body.sleepMin.x, 'y: ' + sprite.body.sleepMin.y);
this.splitline('sleepMax x: ' + sprite.body.sleepMax.x, 'y: ' + sprite.body.sleepMax.y);
this.stop();
},