Small new demo and refactored collision list - now far less comparisons to perform!

This commit is contained in:
Richard Davey
2013-09-13 04:22:12 +01:00
parent 0a42269479
commit 62d77e7038
8 changed files with 535 additions and 319 deletions
+2
View File
@@ -1,3 +1,5 @@
<a href="http://yui.2clics.net/">Minify it</a><br />
<textarea style="width: 800px; height: 800px">
<?php
+1 -1
View File
File diff suppressed because one or more lines are too long
+381 -170
View File
@@ -1,7 +1,7 @@
/**
* Phaser - http://www.phaser.io
*
* v1.0.0 - Built at: Thu, 12 Sep 2013 19:55:57 +0000
* v1.0.0 - Built at: Fri, 13 Sep 2013 03:04:56 +0000
*
* @author Richard Davey http://www.photonstorm.com @photonstorm
*
@@ -38,7 +38,20 @@ var Phaser = Phaser || {
GAMES: [],
AUTO: 0,
CANVAS: 1,
WEBGL: 2
WEBGL: 2,
SPRITE: 0,
BUTTON: 1,
BULLET: 2,
GRAPHICS: 3,
TEXT: 4,
TILESPRITE: 5,
BITMAPTEXT: 6,
GROUP: 7,
RENDERTEXTURE: 8,
TILEMAP: 9,
TILEMAPLAYER: 10,
EMITTER: 11
};
@@ -8850,6 +8863,8 @@ Phaser.Group = function (game, parent, name, useStage) {
}
}
this.type = Phaser.GROUP;
this.exists = true;
/**
@@ -13813,6 +13828,8 @@ Phaser.Sprite = function (game, x, y, key, frame) {
this.name = '';
this.type = Phaser.SPRITE;
this.renderOrderID = -1;
// If you would like the Sprite to have a lifespan once 'born' you can set this to a positive value. Handy for particles, bullets, etc.
@@ -13961,6 +13978,9 @@ Phaser.Sprite = function (game, x, y, key, frame) {
// Set-up the physics body
this.body = new Phaser.Physics.Arcade.Body(this);
this.velocity = this.body.velocity;
this.acceleration = this.body.acceleration;
// World bounds check
this.inWorld = Phaser.Rectangle.intersects(this.bounds, this.game.world.bounds);
this.inWorldThreshold = 0;
@@ -14384,6 +14404,8 @@ Phaser.TileSprite = function (game, x, y, width, height, key, frame) {
PIXI.TilingSprite.call(this, this.texture, width, height);
this.type = Phaser.TILESPRITE;
/**
* The scaling of the image that is being tiled
*
@@ -14423,6 +14445,8 @@ Phaser.Text = function (game, x, y, text, style) {
Phaser.Sprite.call(this, game, x, y, canvasID);
this.type = Phaser.TEXT;
this.setText(text);
this.setStyle(style);
@@ -14459,6 +14483,8 @@ Phaser.Button = function (game, x, y, key, callback, callbackContext, overFrame,
Phaser.Sprite.call(this, game, x, y, key, outFrame);
this.type = Phaser.BUTTON;
this._onOverFrameName = null;
this._onOutFrameName = null;
this._onDownFrameName = null;
@@ -14622,6 +14648,8 @@ Phaser.Graphics = function (game, x, y) {
PIXI.DisplayObjectContainer.call(this);
this.type = Phaser.GRAPHICS;
this.position.x = x;
this.position.y = y;
@@ -14776,6 +14804,8 @@ Phaser.RenderTexture = function (game, key, width, height) {
this.frame = new PIXI.Rectangle(0, 0, this.width, this.height);
this.type = Phaser.RENDERTEXTURE;
if (PIXI.gl)
{
this.initWebGL();
@@ -24795,16 +24825,19 @@ Phaser.Physics.Arcade = function (game) {
this.quadTree = new Phaser.QuadTree(this, this.game.world.bounds.x, this.game.world.bounds.y, this.game.world.bounds.width, this.game.world.bounds.height, this.maxObjects, this.maxLevels);
this.quadTreeID = 0;
// avoid gc spikes by caching these values for re-use
this._obj1Bounds = new Phaser.Rectangle;
this._obj2Bounds = new Phaser.Rectangle;
// Avoid gc spikes by caching these values for re-use
this._bounds1 = new Phaser.Rectangle;
this._bounds2 = new Phaser.Rectangle;
this._overlap = 0;
this._maxOverlap = 0;
this._obj1Velocity = 0;
this._obj2Velocity = 0;
this._obj1NewVelocity = 0;
this._obj2NewVelocity = 0;
this._velocity1 = 0;
this._velocity2 = 0;
this._newVelocity1 = 0;
this._newVelocity2 = 0;
this._average = 0;
this._mapData = [];
this._result = false;
this._total = 0;
};
@@ -24910,27 +24943,197 @@ Phaser.Physics.Arcade.prototype = {
},
// Collides the given object with everything in the world quadtree
collide: function (object, notifyCallback, callbackContext) {
/**
* Checks for collision between two game objects. The objects can be Sprites, Groups or Tilemaps.
* You can perform Sprite vs. Sprite, Sprite vs. Group, Group vs. Group, Sprite vs. Tilemap or Group vs. Tilemap collisions.
*
* @param object1 The first object to check. Can be an instance of Phaser.Sprite, Phaser.Group or Phaser.Tilemap
* @param object2 The second object to check. Can be an instance of Phaser.Sprite, Phaser.Group or Phaser.Tilemap
* @param collideCallback An optional callback function that is called if the objects overlap. The two objects will be passed to this function in the same order in which you passed them to Collision.overlap.
* @param processCallback A callback function that lets you perform additional checks against the two objects if they overlap. If this is set then collideCallback will only be called if processCallback returns true.
* @param callbackContext The context in which to run the callbacks.
* @returns {boolean} true if any collisions were detected, otherwise false.
**/
collide: function (object1, object2, collideCallback, processCallback, callbackContext) {
return this.overlap(object, null, notifyCallback, this.separate, callbackContext);
collideCallback = collideCallback || null;
processCallback = processCallback || null;
callbackContext = callbackContext || collideCallback;
this._result = false;
this._total = 0;
// Only collide valid objects
if (object1 && object2 && object1.exists && object2.exists)
{
// Can expand to support Buttons, Text, etc at a later date. For now these are the essentials.
// SPRITE vs. SPRITE
if (object1.type == Phaser.SPRITE && object2.type == Phaser.SPRITE)
{
this.collideSpriteVsSprite(object1, object2, collideCallback, processCallback, callbackContext);
}
// SPRITE vs. GROUP
else if (object1.type == Phaser.SPRITE && object2.type == Phaser.GROUP)
{
this.collideSpriteVsGroup(object1, object2, collideCallback, processCallback, callbackContext);
}
// GROUP vs. SPRITE
else if (object1.type == Phaser.GROUP && object2.type == Phaser.SPRITE)
{
this.collideSpriteVsGroup(object2, object1, collideCallback, processCallback, callbackContext);
}
// GROUP vs. GROUP
else if (object1.type == Phaser.GROUP && object2.type == Phaser.GROUP)
{
this.collideGroupVsGroup(object1, object2, collideCallback, processCallback, callbackContext);
}
// SPRITE vs. TILEMAP
else if (object1.type == Phaser.SPRITE && object2.type == Phaser.TILEMAP)
{
this.collideSpriteVsTilemap(object1, object2, collideCallback, processCallback, callbackContext);
}
// TILEMAP vs. SPRITE
else if (object1.type == Phaser.TILEMAP && object2.type == Phaser.SPRITE)
{
this.collideSpriteVsTilemap(object2, object1, collideCallback, processCallback, callbackContext);
}
// GROUP vs. TILEMAP
else if (object1.type == Phaser.GROUP && object2.type == Phaser.TILEMAP)
{
this.collideGroupVsTilemap(object1, object2, collideCallback, processCallback, callbackContext);
}
// TILEMAP vs. GROUP
else if (object1.type == Phaser.TILEMAP && object2.type == Phaser.GROUP)
{
this.collideGroupVsTilemap(object2, object1, collideCallback, processCallback, callbackContext);
}
// EMITTER vs. TILEMAP
else if (object1.type == Phaser.EMITTER && object2.type == Phaser.TILEMAP)
{
this.collideGroupVsTilemap(object1, object2, collideCallback, processCallback, callbackContext);
}
// TILEMAP vs. EMITTER
else if (object1.type == Phaser.TILEMAP && object2.type == Phaser.EMITTER)
{
this.collideGroupVsTilemap(object2, object1, collideCallback, processCallback, callbackContext);
}
}
return (this._total > 0);
},
collideGroup: function (group, notifyCallback, callbackContext) {
collideSpriteVsSprite: function (sprite1, sprite2, collideCallback, processCallback, callbackContext) {
notifyCallback = notifyCallback || null;
callbackContext = callbackContext || notifyCallback;
this.separate(sprite1.body, sprite2.body);
for (var g = 0, len = group.length; g < len; g++)
if (this._result)
{
for (var i = 0, gi = group.length; i < gi; i++)
// They collided, is there a custom process callback?
if (processCallback)
{
if (this.separate(group[g].body, group[i].body))
if (processCallback.call(callbackContext, sprite1, sprite2))
{
if (notifyCallback)
this._total++;
if (collideCallback)
{
notifyCallback.call(callbackContext, group[g], group[i].sprite);
collideCallback.call(callbackContext, sprite1, sprite2);
}
}
}
else
{
this._total++;
if (collideCallback)
{
collideCallback.call(callbackContext, sprite1, sprite2);
}
}
}
},
collideGroupVsTilemap: function (group, tilemap, collideCallback, processCallback, callbackContext) {
if (group._container.first._iNext)
{
var currentNode = group._container.first._iNext;
do
{
if (currentNode.exists)
{
this.collideSpriteVsTilemap(currentNode, tilemap, collideCallback, processCallback, callbackContext);
}
currentNode = currentNode._iNext;
}
while (currentNode != group._container.last._iNext);
}
},
collideSpriteVsTilemap: function (sprite, tilemap, collideCallback, processCallback, callbackContext) {
this._mapData = tilemap.collisionLayer.getTileOverlaps(sprite);
// If the sprite actually collided with the tilemap then _mapData contains an array of the tiles it collided with
var i = this._mapData.length;
while (i--)
{
if (processCallback)
{
// We've got a custom process callback to hit first
if (processCallback.call(callbackContext, sprite, this._mapData[i].tile))
{
this._total++;
if (collideCallback)
{
collideCallback.call(callbackContext, sprite, this._mapData[i].tile);
}
}
}
else
{
this._total++;
if (collideCallback)
{
collideCallback.call(callbackContext, sprite, this._mapData[i].tile);
}
}
}
},
collideSpriteVsGroup: function (sprite, group, collideCallback, processCallback, callbackContext) {
// What is the sprite colliding with in the quadtree?
this._potentials = this.quadTree.retrieve(sprite);
for (var i = 0, len = this._potentials.length; i < len; i++)
{
// We have our potential suspects, are they in this group?
if (this._potentials[i].sprite.group == group)
{
this.separate(sprite.body, this._potentials[i]);
if (this._result && processCallback)
{
this._result = processCallback.call(callbackContext, sprite, this._potentials[i].sprite);
}
if (this._result)
{
this._total++;
if (collideCallback)
{
collideCallback.call(callbackContext, sprite, this._potentials[i].sprite);
}
}
}
@@ -24938,111 +25141,98 @@ Phaser.Physics.Arcade.prototype = {
},
/**
* Checks for overlaps between two objects using the world QuadTree. Can be GameObject vs. GameObject, GameObject vs. Group or Group vs. Group.
* Note: Does not take the objects scrollFactor into account. All overlaps are check in world space.
* @param object1 The first GameObject or Group to check. If null the world.group is used.
* @param object2 The second GameObject or Group to check.
* @param notifyCallback A callback function that is called if the objects overlap. The two objects will be passed to this function in the same order in which you passed them to Collision.overlap.
* @param processCallback A callback function that lets you perform additional checks against the two objects if they overlap. If this is set then notifyCallback will only be called if processCallback returns true.
* @returns {boolean} true if the objects overlap, otherwise false.
*/
overlap: function (object1, object2, notifyCallback, processCallback, callbackContext) {
collideGroupVsGroup: function (group1, group2, collideCallback, processCallback, callbackContext) {
object2 = object2 || null;
notifyCallback = notifyCallback || null;
processCallback = processCallback || this.separate;
callbackContext = callbackContext || this;
// Get the ships top-most ID. If the length of that ID is 1 then we can ignore every other result,
// it's simply not colliding with anything :)
var potentials = this.quadTree.retrieve(object1);
var output = [];
for (var i = 0, len = potentials.length; i < len; i++)
if (group1._container.first._iNext)
{
if (processCallback.call(callbackContext, object1.body, potentials[i]))
var currentNode = group1._container.first._iNext;
do
{
if (notifyCallback)
if (currentNode.exists)
{
notifyCallback.call(callbackContext, object1, potentials[i].sprite);
this.collideSpriteVsGroup(currentNode, group2, collideCallback, processCallback, callbackContext);
}
output.push(potentials[i]);
currentNode = currentNode._iNext;
}
while (currentNode != group1._container.last._iNext);
}
return (output.length);
},
/**
* The core Collision separation function used by Collision.overlap.
* @param object1 The first GameObject to separate
* @param object2 The second GameObject to separate
* @returns {boolean} Returns true if the objects were separated, otherwise false.
* The core separation function to separate two physics bodies.
* @param body1 The first Sprite.Body to separate
* @param body2 The second Sprite.Body to separate
* @returns {boolean} Returns true if the bodies were separated, otherwise false.
*/
separate: function (object1, object2) {
separate: function (body1, body2) {
return this.separateX(object1, object2) || this.separateY(object1, object2)
this._result = (this.separateX(body1, body2) || this.separateY(body1, body2));
if (this._result)
{
body1.postUpdate();
body2.postUpdate();
}
},
/**
* Separates the two objects on their x axis
* @param object1 The first GameObject to separate
* @param object2 The second GameObject to separate
* Separates the two physics bodies on their X axis
* @param body1 The first Sprite.Body to separate
* @param body2 The second Sprite.Body to separate
* @returns {boolean} Whether the objects in fact touched and were separated along the X axis.
*/
separateX: function (object1, object2) {
separateX: function (body1, body2) {
// Can't separate two immovable objects
if (object1.immovable && object2.immovable)
// Can't separate two immovable or non-existing bodys
if (body1.immovable && body2.immovable)
{
return false;
}
// First, get the two object deltas
// First, get the two body deltas
this._overlap = 0;
if (object1.deltaX() != object2.deltaX())
if (body1.deltaX() != body2.deltaX())
{
// Check if the X hulls actually overlap
this._obj1Bounds.setTo(object1.x - ((object1.deltaX() > 0) ? object1.deltaX() : 0), object1.lastY, object1.width + ((object1.deltaX() > 0) ? object1.deltaX() : -object1.deltaX()), object1.height);
this._obj2Bounds.setTo(object2.x - ((object2.deltaX() > 0) ? object2.deltaX() : 0), object2.lastY, object2.width + ((object2.deltaX() > 0) ? object2.deltaX() : -object2.deltaX()), object2.height);
this._bounds1.setTo(body1.x - ((body1.deltaX() > 0) ? body1.deltaX() : 0), body1.lastY, body1.width + ((body1.deltaX() > 0) ? body1.deltaX() : -body1.deltaX()), body1.height);
this._bounds2.setTo(body2.x - ((body2.deltaX() > 0) ? body2.deltaX() : 0), body2.lastY, body2.width + ((body2.deltaX() > 0) ? body2.deltaX() : -body2.deltaX()), body2.height);
if ((this._obj1Bounds.right > this._obj2Bounds.x) && (this._obj1Bounds.x < this._obj2Bounds.right) && (this._obj1Bounds.bottom > this._obj2Bounds.y) && (this._obj1Bounds.y < this._obj2Bounds.bottom))
if ((this._bounds1.right > this._bounds2.x) && (this._bounds1.x < this._bounds2.right) && (this._bounds1.bottom > this._bounds2.y) && (this._bounds1.y < this._bounds2.bottom))
{
this._maxOverlap = object1.deltaAbsX() + object2.deltaAbsX() + this.OVERLAP_BIAS;
this._maxOverlap = body1.deltaAbsX() + body2.deltaAbsX() + this.OVERLAP_BIAS;
// If they did overlap (and can), figure out by how much and flip the corresponding flags
if (object1.deltaX() > object2.deltaX())
if (body1.deltaX() > body2.deltaX())
{
this._overlap = object1.x + object1.width - object2.x;
this._overlap = body1.x + body1.width - body2.x;
if ((this._overlap > this._maxOverlap) || object1.allowCollision.right == false || object2.allowCollision.left == false)
if ((this._overlap > this._maxOverlap) || body1.allowCollision.right == false || body2.allowCollision.left == false)
{
this._overlap = 0;
}
else
{
object1.touching.right = true;
object2.touching.left = true;
body1.touching.right = true;
body2.touching.left = true;
}
}
else if (object1.deltaX() < object2.deltaX())
else if (body1.deltaX() < body2.deltaX())
{
this._overlap = object1.x - object2.width - object2.x;
this._overlap = body1.x - body2.width - body2.x;
if ((-this._overlap > this._maxOverlap) || object1.allowCollision.left == false || object2.allowCollision.right == false)
if ((-this._overlap > this._maxOverlap) || body1.allowCollision.left == false || body2.allowCollision.right == false)
{
this._overlap = 0;
}
else
{
object1.touching.left = true;
object2.touching.right = true;
body1.touching.left = true;
body2.touching.right = true;
}
}
}
@@ -25051,33 +25241,44 @@ Phaser.Physics.Arcade.prototype = {
// Then adjust their positions and velocities accordingly (if there was any overlap)
if (this._overlap != 0)
{
this._obj1Velocity = object1.velocity.x;
this._obj2Velocity = object2.velocity.x;
body1.overlapX = this._overlap;
body2.overlapX = this._overlap;
if (!object1.immovable && !object2.immovable)
if (body1.customSeparateX || body2.customSeparateX)
{
return true;
}
this._velocity1 = body1.velocity.x;
this._velocity2 = body2.velocity.x;
if (!body1.immovable && !body2.immovable)
{
this._overlap *= 0.5;
object1.x = object1.x - this._overlap;
object2.x += this._overlap;
this._obj1NewVelocity = Math.sqrt((this._obj2Velocity * this._obj2Velocity * object2.mass) / object1.mass) * ((this._obj2Velocity > 0) ? 1 : -1);
this._obj2NewVelocity = Math.sqrt((this._obj1Velocity * this._obj1Velocity * object1.mass) / object2.mass) * ((this._obj1Velocity > 0) ? 1 : -1);
this._average = (this._obj1NewVelocity + this._obj2NewVelocity) * 0.5;
this._obj1NewVelocity -= this._average;
this._obj2NewVelocity -= this._average;
object1.velocity.x = this._average + this._obj1NewVelocity * object1.bounce.x;
object2.velocity.x = this._average + this._obj2NewVelocity * object2.bounce.x;
body1.x = body1.x - this._overlap;
body2.x += this._overlap;
this._newVelocity1 = Math.sqrt((this._velocity2 * this._velocity2 * body2.mass) / body1.mass) * ((this._velocity2 > 0) ? 1 : -1);
this._newVelocity2 = Math.sqrt((this._velocity1 * this._velocity1 * body1.mass) / body2.mass) * ((this._velocity1 > 0) ? 1 : -1);
this._average = (this._newVelocity1 + this._newVelocity2) * 0.5;
this._newVelocity1 -= this._average;
this._newVelocity2 -= this._average;
body1.velocity.x = this._average + this._newVelocity1 * body1.bounce.x;
body2.velocity.x = this._average + this._newVelocity2 * body2.bounce.x;
}
else if (!object1.immovable)
else if (!body1.immovable)
{
object1.x = object1.x - this._overlap;
object1.velocity.x = this._obj2Velocity - this._obj1Velocity * object1.bounce.x;
body1.x = body1.x - this._overlap;
body1.velocity.x = this._velocity2 - this._velocity1 * body1.bounce.x;
}
else if (!object2.immovable)
else if (!body2.immovable)
{
object2.x += this._overlap;
object2.velocity.x = this._obj1Velocity - this._obj2Velocity * object2.bounce.x;
body2.x += this._overlap;
body2.velocity.x = this._velocity1 - this._velocity2 * body2.bounce.x;
}
return true;
}
else
@@ -25088,59 +25289,59 @@ Phaser.Physics.Arcade.prototype = {
},
/**
* Separates the two objects on their y axis
* @param object1 The first GameObject to separate
* @param object2 The second GameObject to separate
* @returns {boolean} Whether the objects in fact touched and were separated along the Y axis.
* Separates the two physics bodies on their Y axis
* @param body1 The first Sprite.Body to separate
* @param body2 The second Sprite.Body to separate
* @returns {boolean} Whether the bodys in fact touched and were separated along the Y axis.
*/
separateY: function (object1, object2) {
separateY: function (body1, body2) {
// Can't separate two immovable objects
if (object1.immovable && object2.immovable)
// Can't separate two immovable or non-existing bodys
if (body1.immovable && body2.immovable)
{
return false;
}
// First, get the two object deltas
// First, get the two body deltas
this._overlap = 0;
if (object1.deltaY() != object2.deltaY())
if (body1.deltaY() != body2.deltaY())
{
// Check if the Y hulls actually overlap
this._obj1Bounds.setTo(object1.x, object1.y - ((object1.deltaY() > 0) ? object1.deltaY() : 0), object1.width, object1.height + object1.deltaAbsY());
this._obj2Bounds.setTo(object2.x, object2.y - ((object2.deltaY() > 0) ? object2.deltaY() : 0), object2.width, object2.height + object2.deltaAbsY());
this._bounds1.setTo(body1.x, body1.y - ((body1.deltaY() > 0) ? body1.deltaY() : 0), body1.width, body1.height + body1.deltaAbsY());
this._bounds2.setTo(body2.x, body2.y - ((body2.deltaY() > 0) ? body2.deltaY() : 0), body2.width, body2.height + body2.deltaAbsY());
if ((this._obj1Bounds.right > this._obj2Bounds.x) && (this._obj1Bounds.x < this._obj2Bounds.right) && (this._obj1Bounds.bottom > this._obj2Bounds.y) && (this._obj1Bounds.y < this._obj2Bounds.bottom))
if ((this._bounds1.right > this._bounds2.x) && (this._bounds1.x < this._bounds2.right) && (this._bounds1.bottom > this._bounds2.y) && (this._bounds1.y < this._bounds2.bottom))
{
this._maxOverlap = object1.deltaAbsY() + object2.deltaAbsY() + this.OVERLAP_BIAS;
this._maxOverlap = body1.deltaAbsY() + body2.deltaAbsY() + this.OVERLAP_BIAS;
// If they did overlap (and can), figure out by how much and flip the corresponding flags
if (object1.deltaY() > object2.deltaY())
if (body1.deltaY() > body2.deltaY())
{
this._overlap = object1.y + object1.height - object2.y;
this._overlap = body1.y + body1.height - body2.y;
if ((this._overlap > this._maxOverlap) || object1.allowCollision.down == false || object2.allowCollision.up == false)
if ((this._overlap > this._maxOverlap) || body1.allowCollision.down == false || body2.allowCollision.up == false)
{
this._overlap = 0;
}
else
{
object1.touching.down = true;
object2.touching.up = true;
body1.touching.down = true;
body2.touching.up = true;
}
}
else if (object1.deltaY() < object2.deltaY())
else if (body1.deltaY() < body2.deltaY())
{
this._overlap = object1.y - object2.height - object2.y;
this._overlap = body1.y - body2.height - body2.y;
if ((-this._overlap > this._maxOverlap) || object1.allowCollision.up == false || object2.allowCollision.down == false)
if ((-this._overlap > this._maxOverlap) || body1.allowCollision.up == false || body2.allowCollision.down == false)
{
this._overlap = 0;
}
else
{
object1.touching.up = true;
object2.touching.down = true;
body1.touching.up = true;
body2.touching.down = true;
}
}
}
@@ -25149,43 +25350,56 @@ Phaser.Physics.Arcade.prototype = {
// Then adjust their positions and velocities accordingly (if there was any overlap)
if (this._overlap != 0)
{
this._obj1Velocity = object1.velocity.y;
this._obj2Velocity = object2.velocity.y;
body1.overlapY = this._overlap;
body2.overlapY = this._overlap;
if (!object1.immovable && !object2.immovable)
if (body1.customSeparateY || body2.customSeparateY)
{
return true;
}
this._velocity1 = body1.velocity.y;
this._velocity2 = body2.velocity.y;
if (!body1.immovable && !body2.immovable)
{
this._overlap *= 0.5;
object1.y = object1.y - this._overlap;
object2.y += this._overlap;
this._obj1NewVelocity = Math.sqrt((this._obj2Velocity * this._obj2Velocity * object2.mass) / object1.mass) * ((this._obj2Velocity > 0) ? 1 : -1);
this._obj2NewVelocity = Math.sqrt((this._obj1Velocity * this._obj1Velocity * object1.mass) / object2.mass) * ((this._obj1Velocity > 0) ? 1 : -1);
this._average = (this._obj1NewVelocity + this._obj2NewVelocity) * 0.5;
this._obj1NewVelocity -= this._average;
this._obj2NewVelocity -= this._average;
object1.velocity.y = this._average + this._obj1NewVelocity * object1.bounce.y;
object2.velocity.y = this._average + this._obj2NewVelocity * object2.bounce.y;
body1.y = body1.y - this._overlap;
body2.y += this._overlap;
this._newVelocity1 = Math.sqrt((this._velocity2 * this._velocity2 * body2.mass) / body1.mass) * ((this._velocity2 > 0) ? 1 : -1);
this._newVelocity2 = Math.sqrt((this._velocity1 * this._velocity1 * body1.mass) / body2.mass) * ((this._velocity1 > 0) ? 1 : -1);
this._average = (this._newVelocity1 + this._newVelocity2) * 0.5;
this._newVelocity1 -= this._average;
this._newVelocity2 -= this._average;
body1.velocity.y = this._average + this._newVelocity1 * body1.bounce.y;
body2.velocity.y = this._average + this._newVelocity2 * body2.bounce.y;
}
else if (!object1.immovable)
else if (!body1.immovable)
{
object1.y = object1.y - this._overlap;
object1.velocity.y = this._obj2Velocity - this._obj1Velocity * object1.bounce.y;
body1.y = body1.y - this._overlap;
body1.velocity.y = this._velocity2 - this._velocity1 * body1.bounce.y;
// This is special case code that handles things like horizontal moving platforms you can ride
if (object2.active && object2.moves && (object1.deltaY() > object2.deltaY()))
if (body2.active && body2.moves && (body1.deltaY() > body2.deltaY()))
{
object1.x += object2.x - object2.lastX;
body1.x += body2.x - body2.lastX;
}
}
else if (!object2.immovable)
else if (!body2.immovable)
{
object2.y += this._overlap;
object2.velocity.y = this._obj1Velocity - this._obj2Velocity * object2.bounce.y;
body2.y += this._overlap;
body2.velocity.y = this._velocity1 - this._velocity2 * body2.bounce.y;
// This is special case code that handles things like horizontal moving platforms you can ride
if (object1.sprite.active && object1.moves && (object1.deltaY() < object2.deltaY()))
if (body1.sprite.active && body1.moves && (body1.deltaY() < body2.deltaY()))
{
object2.x += object1.x - object1.lastX;
body2.x += body1.x - body1.lastX;
}
}
return true;
}
else
@@ -25237,9 +25451,9 @@ Phaser.Physics.Arcade.prototype = {
if (object.deltaX() != 0)
{
this._obj1Bounds.setTo(object.x, object.y, object.width, object.height);
this._bounds1.setTo(object.x, object.y, object.width, object.height);
if ((this._obj1Bounds.right > x) && (this._obj1Bounds.x < x + width) && (this._obj1Bounds.bottom > y) && (this._obj1Bounds.y < y + height))
if ((this._bounds1.right > x) && (this._bounds1.x < x + width) && (this._bounds1.bottom > y) && (this._bounds1.y < y + height))
{
// The hulls overlap, let's process it
this._maxOverlap = object.deltaAbsX() + this.OVERLAP_BIAS;
@@ -25324,9 +25538,9 @@ Phaser.Physics.Arcade.prototype = {
if (object.deltaY() != 0)
{
this._obj1Bounds.setTo(object.x, object.y, object.width, object.height);
this._bounds1.setTo(object.x, object.y, object.width, object.height);
if ((this._obj1Bounds.right > x) && (this._obj1Bounds.x < x + width) && (this._obj1Bounds.bottom > y) && (this._obj1Bounds.y < y + height))
if ((this._bounds1.right > x) && (this._bounds1.x < x + width) && (this._bounds1.bottom > y) && (this._bounds1.y < y + height))
{
// The hulls overlap, let's process it
@@ -25808,6 +26022,17 @@ Phaser.Physics.Arcade.Body = function (sprite) {
this.allowRotation = true;
this.allowGravity = true;
// These two flags allow you to disable the custom separation that takes place
// Used in combination with your own collision processHandler you can create whatever
// type of collision response you need.
this.customSeparateX = false;
this.customSeparateY = false;
// When this body collides with another the amount of overlap is stored in here
// These values are useful if you want to provide your own custom separation logic.
this.overlapX = 0;
this.overlapY = 0;
this.collideWorldBounds = false;
this.lastX = sprite.x;
@@ -25893,23 +26118,6 @@ Phaser.Physics.Arcade.Body.prototype = {
},
/*
postUpdate: function () {
// this.sprite.x = this.x - this.offset.x + (this.sprite.anchor.x * this.width);
// this.sprite.y = this.y - this.offset.y + (this.sprite.anchor.y * this.height);
this.sprite.x = (this.x - this.offset.x + (this.sprite.anchor.x * this.width)) - (this.game.world.camera.x * this.sprite.scrollFactor.x);
this.sprite.y = (this.y - this.offset.y + (this.sprite.anchor.y * this.height)) - (this.game.world.camera.y * this.sprite.scrollFactor.y);
if (this.allowRotation)
{
this.sprite.angle = this.rotation;
}
},
*/
checkWorldBounds: function () {
if (this.x < this.game.world.bounds.x)
@@ -25953,18 +26161,16 @@ Phaser.Physics.Arcade.Body.prototype = {
reset: function () {
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.velocity.setTo(0, 0);
this.acceleration.setTo(0, 0);
this.angularVelocity = 0;
this.angularAcceleration = 0;
this.angularDrag = 0;
this.maxAngular = 1000;
this.mass = 1;
this.x = (this.sprite.x - (this.sprite.anchor.x * this.width)) + this.offset.x;
this.y = (this.sprite.y - (this.sprite.anchor.y * this.height)) + this.offset.y;
this.lastX = this.x;
this.lastY = this.y;
},
@@ -26106,6 +26312,8 @@ Phaser.Particles.Arcade.Emitter = function (game, x, y, maxParticles) {
this.name = 'emitter' + this.game.particles.ID++;
this.type = Phaser.EMITTER;
/**
* The X position of the top left corner of the emitter in world space.
*/
@@ -26428,7 +26636,7 @@ Phaser.Particles.Arcade.Emitter.prototype.emitParticle = function () {
if (this.width > 1 || this.height > 1)
{
particle.reset(this.x - this.game.rnd.integerInRange(this.left, this.right), this.y - this.game.rnd.integerInRange(this.top, this.bottom));
particle.reset(this.emiteX - this.game.rnd.integerInRange(this.left, this.right), this.emiteY - this.game.rnd.integerInRange(this.top, this.bottom));
}
else
{
@@ -26697,6 +26905,8 @@ Phaser.Tilemap = function (game, key, x, y, resizeWorld, tileWidth, tileHeight)
this.position.x = x;
this.position.y = y;
this.type = Phaser.TILEMAP;
this.renderer = new Phaser.TilemapRenderer(this.game);
this.mapFormat = map.format;
@@ -27145,6 +27355,7 @@ Phaser.TilemapLayer = function (parent, id, key, mapFormat, name, tileWidth, til
this.ID = id;
this.name = name;
this.key = key;
this.type = Phaser.TILEMAPLAYER;
this.mapFormat = mapFormat;
this.tileWidth = tileWidth;
+69
View File
@@ -0,0 +1,69 @@
<!DOCTYPE HTML>
<html>
<head>
<title>phaser.js - oh balls</title>
<script src="phaser-min.js"></script>
<style type="text/css">
body {
margin: 0;
font-family: sans-serif;
}
p {
padding: 16px;
margin: 0px;
}
</style>
</head>
<body>
<div id="game"></div>
<script type="text/javascript">
(function () {
var game = new Phaser.Game(800, 600, Phaser.AUTO, 'game', { preload: preload, create: create, update: update });
var p;
function preload() {
game.load.spritesheet('balls', 'assets/balls.png', 17, 17);
}
function create() {
game.stage.backgroundColor = 0x337799;
p = game.add.emitter(100, 100, 250);
p.makeParticles('balls', [0,1,2,3,4,5]);
p.minParticleSpeed.setTo(-100, -100);
p.maxParticleSpeed.setTo(100, -200);
p.gravity = 10;
p.start(false, 3000, 10);
game.add.tween(p).to({ x: 700 }, 1000, Phaser.Easing.Quadratic.InOut, true, 0, 1000, true);
}
function update() {
p.y = game.input.y;
if (p.y < 100)
{
p.y = 100;
}
}
})();
</script>
<p>Mouse to move</p>
<p>Created with <a href="https://github.com/photonstorm/phaser">Phaser 1.0</a> by <a href="https://twitter.com/photonstorm">@photonstorm</a></p>
</body>
</html>
+15 -12
View File
@@ -19,12 +19,12 @@
function preload() {
game.load.image('carrot', 'assets/sprites/carrot.png');
game.load.image('star', 'assets/misc/star_particle.png');
game.load.image('diamond', 'assets/sprites/diamond.png');
game.load.image('dude', 'assets/sprites/phaser-dude.png');
game.load.image('coke', 'assets/sprites/cokecan.png');
game.load.atlasJSONHash('pixies', 'assets/sprites/pixi_monsters.png', 'assets/sprites/pixi_monsters.json');
// game.load.image('carrot', 'assets/sprites/carrot.png');
// game.load.image('star', 'assets/misc/star_particle.png');
// game.load.image('diamond', 'assets/sprites/diamond.png');
// game.load.image('dude', 'assets/sprites/phaser-dude.png');
// game.load.image('coke', 'assets/sprites/cokecan.png');
// game.load.atlasJSONHash('pixies', 'assets/sprites/pixi_monsters.png', 'assets/sprites/pixi_monsters.json');
game.load.spritesheet('balls', 'assets/sprites/balls.png', 17, 17);
}
@@ -33,18 +33,18 @@
game.stage.backgroundColor = 0x337799;
p = game.add.emitter(200, 100, 250);
p = game.add.emitter(100, 100, 250);
// p.width = 200;
// p.height = 200;
// keys, frames, quantity, collide
// p.makeParticles(['diamond', 'carrot', 'star']);
// p.makeParticles('balls', [0,1,2,3,4,5]);
p.makeParticles('pixies', [0,1,2,3]);
p.makeParticles('balls', [0,1,2,3,4,5]);
// p.makeParticles('pixies', [0,1,2,3]);
p.minParticleScale = 0.1;
p.maxParticleScale = 0.5;
// p.minParticleScale = 0.1;
// p.maxParticleScale = 0.5;
// Steady constant stream at 250ms delay and 10 seconds lifespan
// p.start(false, 10000, 250, 100);
@@ -56,11 +56,14 @@
p.gravity = 10;
p.start(false, 3000, 10);
game.add.tween(p).to({ emitX: 400 }, 1000, Phaser.Easing.Quadratic.InOut, true, 0, 1000, true);
game.add.tween(p).to({ x: 700 }, 1000, Phaser.Easing.Quadratic.InOut, true, 0, 1000, true);
}
function update() {
p.y = game.math.min(100, game.input.y);
}
function render() {
+11 -17
View File
@@ -12,7 +12,7 @@
(function () {
var game = new Phaser.Game(800, 600, Phaser.AUTO, '', { preload: preload, create: create, update: update, render: render });
var game = new Phaser.Game(800, 600, Phaser.AUTO, '', { preload: preload, create: create, update: update });
function preload() {
@@ -22,10 +22,8 @@
}
var p;
var balls;
var map;
var test = [];
var g;
function create() {
@@ -36,22 +34,21 @@
map = game.add.tilemap(0, 0, 'level1');
map.setCollisionByIndex([9,10,11,14,15,16,18,19,22,23,24,32,37,38], true, true, true, true);
p = game.add.emitter(300, 50, 500);
p.bounce = 0.5;
p.makeParticles('balls', [0,1,2,3,4,5], 500, 1);
p.minParticleSpeed.setTo(-150, 150);
p.maxParticleSpeed.setTo(100, 100);
p.gravity = 8;
p.start(false, 5000, 50);
balls = game.add.emitter(300, 50, 500);
balls.bounce = 0.5;
balls.makeParticles('balls', [0,1,2,3,4,5], 500, 1);
balls.minParticleSpeed.setTo(-150, 150);
balls.maxParticleSpeed.setTo(100, 100);
balls.gravity = 8;
balls.start(false, 5000, 50);
game.add.tween(p).to({ x: 4000 }, 7500, Phaser.Easing.Quadratic.InOut, true, 0, 1000, true);
game.add.tween(balls).to({ x: 4000 }, 7500, Phaser.Easing.Sinusoidal.InOut, true, 0, 1000, true);
}
function update() {
map.collide(g);
map.collide(p);
game.physics.collide(balls, map);
if (game.input.keyboard.isDown(Phaser.Keyboard.LEFT))
{
@@ -73,9 +70,6 @@
}
function render() {
}
})();
</script>
+56 -102
View File
@@ -144,11 +144,11 @@ Phaser.Physics.Arcade.prototype = {
},
/**
* Checks for collision between two game objects. The objects can be Sprites, Groups or Tilemaps.
* Checks for collision between two game objects. The objects can be Sprites, Groups, Emitters or Tilemaps.
* You can perform Sprite vs. Sprite, Sprite vs. Group, Group vs. Group, Sprite vs. Tilemap or Group vs. Tilemap collisions.
*
* @param object1 The first object to check. Can be an instance of Phaser.Sprite, Phaser.Group or Phaser.Tilemap
* @param object2 The second object to check. Can be an instance of Phaser.Sprite, Phaser.Group or Phaser.Tilemap
* @param object1 The first object to check. Can be an instance of Phaser.Sprite, Phaser.Group, Phaser.Particles.Emitter, or Phaser.Tilemap
* @param object2 The second object to check. Can be an instance of Phaser.Sprite, Phaser.Group, Phaser.Particles.Emitter or Phaser.Tilemap
* @param collideCallback An optional callback function that is called if the objects overlap. The two objects will be passed to this function in the same order in which you passed them to Collision.overlap.
* @param processCallback A callback function that lets you perform additional checks against the two objects if they overlap. If this is set then collideCallback will only be called if processCallback returns true.
* @param callbackContext The context in which to run the callbacks.
@@ -168,45 +168,65 @@ Phaser.Physics.Arcade.prototype = {
{
// Can expand to support Buttons, Text, etc at a later date. For now these are the essentials.
// SPRITE vs. SPRITE
if (object1.type == Phaser.SPRITE && object2.type == Phaser.SPRITE)
// SPRITES
if (object1.type == Phaser.SPRITE)
{
this.collideSpriteVsSprite(object1, object2, collideCallback, processCallback, callbackContext);
if (object2.type == Phaser.SPRITE)
{
this.collideSpriteVsSprite(object1, object2, collideCallback, processCallback, callbackContext);
}
else if (object2.type == Phaser.GROUP || object2.type == Phaser.EMITTER)
{
this.collideSpriteVsGroup(object1, object2, collideCallback, processCallback, callbackContext);
}
else if (object2.type == Phaser.TILEMAP)
{
this.collideSpriteVsTilemap(object1, object2, collideCallback, processCallback, callbackContext);
}
}
// SPRITE vs. GROUP
else if (object1.type == Phaser.SPRITE && object2.type == Phaser.GROUP)
// GROUPS
else if (object1.type == Phaser.GROUP)
{
this.collideSpriteVsGroup(object1, object2, collideCallback, processCallback, callbackContext);
if (object2.type == Phaser.SPRITE)
{
this.collideSpriteVsGroup(object2, object1, collideCallback, processCallback, callbackContext);
}
else if (object2.type == Phaser.GROUP || object2.type == Phaser.EMITTER)
{
this.collideGroupVsGroup(object1, object2, collideCallback, processCallback, callbackContext);
}
else if (object2.type == Phaser.TILEMAP)
{
this.collideGroupVsTilemap(object1, object2, collideCallback, processCallback, callbackContext);
}
}
// GROUP vs. SPRITE
else if (object1.type == Phaser.GROUP && object2.type == Phaser.SPRITE)
// TILEMAPS
else if (object1.type == Phaser.TILEMAP)
{
this.collideSpriteVsGroup(object2, object1, collideCallback, processCallback, callbackContext);
if (object2.type == Phaser.SPRITE)
{
this.collideSpriteVsTilemap(object2, object1, collideCallback, processCallback, callbackContext);
}
else if (object2.type == Phaser.GROUP || object2.type == Phaser.EMITTER)
{
this.collideGroupVsTilemap(object2, object1, collideCallback, processCallback, callbackContext);
}
}
// GROUP vs. GROUP
else if (object1.type == Phaser.GROUP && object2.type == Phaser.GROUP)
// EMITTER
else if (object1.type == Phaser.EMITTER)
{
this.collideGroupVsGroup(object1, object2, collideCallback, processCallback, callbackContext);
}
// SPRITE vs. TILEMAP
else if (object1.type == Phaser.SPRITE && object2.type == Phaser.TILEMAP)
{
this.collideSpriteVsTilemap(object1, object2, collideCallback, processCallback, callbackContext);
}
// TILEMAP vs. SPRITE
else if (object1.type == Phaser.TILEMAP && object2.type == Phaser.SPRITE)
{
this.collideSpriteVsTilemap(object2, object1, collideCallback, processCallback, callbackContext);
}
// GROUP vs. TILEMAP
else if (object1.type == Phaser.GROUP && object2.type == Phaser.TILEMAP)
{
this.collideGroupVsTilemap(object1, object2, collideCallback, processCallback, callbackContext);
}
// TILEMAP vs. GROUP
else if (object1.type == Phaser.TILEMAP && object2.type == Phaser.GROUP)
{
this.collideGroupVsTilemap(object2, object1, collideCallback, processCallback, callbackContext);
if (object2.type == Phaser.SPRITE)
{
this.collideSpriteVsGroup(object2, object1, collideCallback, processCallback, callbackContext);
}
else if (object2.type == Phaser.GROUP || object2.type == Phaser.EMITTER)
{
this.collideGroupVsGroup(object1, object2, collideCallback, processCallback, callbackContext);
}
else if (object2.type == Phaser.TILEMAP)
{
this.collideGroupVsTilemap(object1, object2, collideCallback, processCallback, callbackContext);
}
}
}
@@ -214,8 +234,6 @@ Phaser.Physics.Arcade.prototype = {
},
// collideSpriteVsWorld
collideSpriteVsSprite: function (sprite1, sprite2, collideCallback, processCallback, callbackContext) {
this.separate(sprite1.body, sprite2.body);
@@ -352,72 +370,8 @@ Phaser.Physics.Arcade.prototype = {
},
/**
* Checks for overlaps between two objects using the world QuadTree. Can be GameObject vs. GameObject, GameObject vs. Group or Group vs. Group.
* Note: Does not take the objects scrollFactor into account. All overlaps are check in world space.
* @param object1 The first GameObject or Group to check. If null the world.group is used.
* @param object2 The second GameObject or Group to check.
* @param notifyCallback A callback function that is called if the objects overlap. The two objects will be passed to this function in the same order in which you passed them to Collision.overlap.
* @param processCallback A callback function that lets you perform additional checks against the two objects if they overlap. If this is set then notifyCallback will only be called if processCallback returns true.
* @returns {boolean} true if the objects overlap, otherwise false.
overlap: function (object1, object2, notifyCallback, processCallback, callbackContext) {
object2 = object2 || null;
notifyCallback = notifyCallback || null;
processCallback = processCallback || this.separate;
callbackContext = callbackContext || this;
// You have to give an object first
if (object.type )
// World vs. World check
if (object1 == null)
{
// Scan the entire display list, comparing every object! (ouch)
if (this.game.world._container.first._iNext)
{
var currentNode = this.game.world._container.first._iNext;
do
{
if (checkExists == false || (checkExists && currentNode.exists))
{
callback.call(callbackContext, currentNode);
}
currentNode = currentNode._iNext;
}
while (currentNode != this.game.world._container.last._iNext);
}
}
// Get the ships top-most ID. If the length of that ID is 1 then we can ignore every other result,
// it's simply not colliding with anything :)
var potentials = this.quadTree.retrieve(object1);
var output = [];
for (var i = 0, len = potentials.length; i < len; i++)
{
if (processCallback.call(callbackContext, object1.body, potentials[i]))
{
if (notifyCallback)
{
notifyCallback.call(callbackContext, object1, potentials[i].sprite);
}
output.push(potentials[i]);
}
}
return (output.length);
},
*/
/**
* The core Collision separation function to separate two physics bodies.
* The core separation function to separate two physics bodies.
* @param body1 The first Sprite.Body to separate
* @param body2 The second Sprite.Body to separate
* @returns {boolean} Returns true if the bodies were separated, otherwise false.
-17
View File
@@ -145,23 +145,6 @@ Phaser.Physics.Arcade.Body.prototype = {
},
/*
postUpdate: function () {
// this.sprite.x = this.x - this.offset.x + (this.sprite.anchor.x * this.width);
// this.sprite.y = this.y - this.offset.y + (this.sprite.anchor.y * this.height);
this.sprite.x = (this.x - this.offset.x + (this.sprite.anchor.x * this.width)) - (this.game.world.camera.x * this.sprite.scrollFactor.x);
this.sprite.y = (this.y - this.offset.y + (this.sprite.anchor.y * this.height)) - (this.game.world.camera.y * this.sprite.scrollFactor.y);
if (this.allowRotation)
{
this.sprite.angle = this.rotation;
}
},
*/
checkWorldBounds: function () {
if (this.x < this.game.world.bounds.x)