New tiles and new map test.

This commit is contained in:
photonstorm
2014-03-06 09:48:42 +00:00
parent e97a207816
commit 6815c5909a
117 changed files with 429 additions and 95 deletions
+7 -2
View File
@@ -94,7 +94,7 @@ Phaser.Physics.prototype = {
* Phaser.Physics.Arcade is running by default, but all others need activating directly.
* You can start the following physics systems:
* Phaser.Physics.P2 - A full-body advanced physics system by Stefan Hedman.
* Phaser.Physics.NINJA - A port of the metanet N+ physics system.
* Phaser.Physics.NINJA - A port of Metanet Softwares N+ physics system.
* Phaser.Physics.BOX2D and Phaser.Physics.CHIPMUNK are still in development.
*
* @method Phaser.Physics#startSystem
@@ -132,7 +132,7 @@ Phaser.Physics.prototype = {
*
* Phaser.Physics.Arcade - A light weight AABB based collision system with basic separation.
* Phaser.Physics.P2 - A full-body advanced physics system supporting multiple object shapes, polygon loading, contact materials, springs and constraints.
* Phaser.Physics.NINJA - A port of the metanet N+ physics system. Advanced AABB and Circle vs. Tile collision.
* Phaser.Physics.NINJA - A port of Metanet Softwares N+ physics system. Advanced AABB and Circle vs. Tile collision.
* Phaser.Physics.BOX2D and Phaser.Physics.CHIPMUNK are still in development.
*
* @method Phaser.Physics#enable
@@ -203,6 +203,11 @@ Phaser.Physics.prototype = {
*/
setBoundsToWorld: function () {
if (this.ninja)
{
this.ninja.setBoundsToWorld();
}
},
/**
+6 -1
View File
@@ -6,11 +6,16 @@
/**
* Ninja Physics AABB constructor.
* Note: This class could be massively optimised and reduced in size. I leave that challenge up to you.
*
* @class Phaser.Physics.Ninja.AABB
* @classdesc Arcade Physics Constructor
* @constructor
* @param {Phaser.Game} game reference to the current game instance.
* @param {Phaser.Physics.Ninja} system - A reference to the physics system.
* @param {number} x - The x coordinate to create this shape at.
* @param {number} y - The y coordinate to create this shape at.
* @param {number} width - The width of this AABB.
* @param {number} height - The height of this AABB.
*/
Phaser.Physics.Ninja.AABB = function (system, x, y, width, height) {
+42 -13
View File
@@ -63,37 +63,66 @@ Phaser.Physics.Ninja.Body = function (system, sprite, type, id, radius) {
*/
this.shape = null;
var sx = sprite.x;
var sy = sprite.y;
if (sprite.anchor.x === 0)
{
sx += (sprite.width * 0.5);
}
if (sprite.anchor.y === 0)
{
sy += (sprite.height * 0.5);
}
if (type === 1)
{
this.aabb = new Phaser.Physics.Ninja.AABB(system, sprite.x, sprite.y, sprite.width, sprite.height);
this.aabb = new Phaser.Physics.Ninja.AABB(this, sx, sy, sprite.width, sprite.height);
this.shape = this.aabb;
}
else if (type === 2)
{
this.circle = new Phaser.Physics.Ninja.Circle(system, sprite.x, sprite.y, radius);
this.circle = new Phaser.Physics.Ninja.Circle(this, sx, sy, radius);
this.shape = this.circle;
}
else if (type === 3)
{
this.tile = new Phaser.Physics.Ninja.Tile(system, sprite.x, sprite.y, sprite.width, sprite.height, id);
this.tile = new Phaser.Physics.Ninja.Tile(this, sx, sy, sprite.width, sprite.height, id);
this.shape = this.tile;
}
// Setting drag to 0 and friction to 0 means you get a normalised speed (px psec)
/**
* @property {number} drag - The drag applied to this object as it moves.
* @default
*/
this.drag = 1;
/**
* @property {number} friction - The friction applied to this object as it moves.
* @default
*/
this.friction = 0.05;
/**
* @property {number} gravityScale - How much of the world gravity should be applied to this object? 1 = all of it, 0.5 = 50%, etc.
* @default
*/
this.gravityScale = 1;
/**
* @property {number} bounce - The bounciness of this object when it collides. A value between 0 and 1. We recommend setting it to 0.999 to avoid jittering.
* @default
*/
this.bounce = 0.3;
/**
* @property {Phaser.Point} velocity - The velocity in pixels per second sq. of the Body.
*/
this.velocity = new Phaser.Point();
/**
* @property {Phaser.Point} drag - The drag applied to the motion of the Body.
*/
this.drag = new Phaser.Point();
/**
* @property {Phaser.Point} bounce - The elasticitiy of the Body when colliding. bounce.x/y = 1 means full rebound, bounce.x/y = 0.5 means 50% rebound velocity.
*/
this.bounce = new Phaser.Point();
/**
* @property {boolean} skipQuadTree - If the Body is an irregular shape you can set this to true to avoid it being added to any QuadTrees.
* @default
+83 -35
View File
@@ -6,33 +6,77 @@
/**
* Ninja Physics Circle constructor.
* Note: This class could be massively optimised and reduced in size. I leave that challenge up to you.
*
* @class Phaser.Physics.Ninja.Circle
* @classdesc Arcade Physics Constructor
* @constructor
* @param {Phaser.Game} game reference to the current game instance.
* @param {Phaser.Physics.Ninja.Body} body - The body that owns this shape.
* @param {number} x - The x coordinate to create this shape at.
* @param {number} y - The y coordinate to create this shape at.
* @param {number} radius - The radius of this Circle.
*/
Phaser.Physics.Ninja.Circle = function (system, x, y, radius) {
Phaser.Physics.Ninja.Circle = function (body, x, y, radius) {
this.system = system;
/**
* @property {Phaser.Physics.Ninja.Body} system - A reference to the body that owns this shape.
*/
this.body = body;
/**
* @property {Phaser.Physics.Ninja} system - A reference to the physics system.
*/
this.system = body.system;
/**
* @property {Phaser.Point} pos - The position of this object.
*/
this.pos = new Phaser.Point(x, y);
/**
* @property {Phaser.Point} oldpos - The position of this object in the previous update.
*/
this.oldpos = new Phaser.Point(x, y);
/**
* @property {number} radius - The radius of this circle shape.
*/
this.radius = radius;
/**
* @property {number} width - The width.
* @readonly
*/
this.width = radius * 2;
/**
* @property {number} height - The height.
* @readonly
*/
this.height = radius * 2;
/**
* @property {number} oH - Internal var.
* @private
*/
this.oH = 0;
/**
* @property {number} oV - Internal var.
* @private
*/
this.oV = 0;
// Setting drag to 0 and friction to 0 means you get a normalised speed (px psec)
this.drag = 1;
this.friction = 0.05;
this.gravityScale = 1;
this.bounce = 0.3;
/**
* @property {Phaser.Point} velocity - The velocity of this object.
*/
this.velocity = new Phaser.Point();
/**
* @property {object} circleTileProjections - All of the collision response handlers.
*/
this.circleTileProjections = {};
this.circleTileProjections[Phaser.Physics.Ninja.Tile.TYPE_FULL] = this.projCircle_Full;
this.circleTileProjections[Phaser.Physics.Ninja.Tile.TYPE_45DEG] = this.projCircle_45Deg;
this.circleTileProjections[Phaser.Physics.Ninja.Tile.TYPE_CONCAVE] = this.projCircle_Concave;
@@ -64,8 +108,8 @@ Phaser.Physics.Ninja.Circle.prototype = {
var py = this.pos.y;
// integrate
this.pos.x += (this.drag * this.pos.x) - (this.drag * this.oldpos.x);
this.pos.y += (this.drag * this.pos.y) - (this.drag * this.oldpos.y) + (this.system.gravity * this.gravityScale);
this.pos.x += (this.body.drag * this.pos.x) - (this.body.drag * this.oldpos.x);
this.pos.y += (this.body.drag * this.pos.y) - (this.body.drag * this.oldpos.y) + (this.system.gravity * this.body.gravityScale);
// store
this.velocity.set(this.pos.x - px, this.pos.y - py);
@@ -88,29 +132,28 @@ Phaser.Physics.Ninja.Circle.prototype = {
var p = this.pos;
var o = this.oldpos;
//calc velocity
// Calc velocity
var vx = p.x - o.x;
var vy = p.y - o.y;
//find component of velocity parallel to collision normal
// Find component of velocity parallel to collision normal
var dp = (vx * dx + vy * dy);
var nx = dp * dx;//project velocity onto collision normal
var nx = dp * dx; //project velocity onto collision normal
var ny = dp * dy;//nx,ny is normal velocity
var ny = dp * dy; //nx,ny is normal velocity
var tx = vx - nx;//px,py is tangent velocity
var tx = vx - nx; //px,py is tangent velocity
var ty = vy - ny;
//we only want to apply collision response forces if the object is travelling into, and not out of, the collision
var b, bx, by, f, fx, fy;
// We only want to apply collision response forces if the object is travelling into, and not out of, the collision
var b, bx, by, fx, fy;
if (dp < 0)
{
//f = FRICTION;
fx = tx * this.friction;
fy = ty * this.friction;
fx = tx * this.body.friction;
fy = ty * this.body.friction;
b = 1 + this.bounce;
b = 1 + this.body.bounce;
bx = (nx * b);
by = (ny * b);
@@ -118,14 +161,16 @@ Phaser.Physics.Ninja.Circle.prototype = {
}
else
{
//moving out of collision, do not apply forces
// Moving out of collision, do not apply forces
bx = by = fx = fy = 0;
}
p.x += px;//project object out of collision
// Project object out of collision
p.x += px;
p.y += py;
o.x += px + bx + fx;//apply bounce+friction impulses which alter velocity
// Apply bounce+friction impulses which alter velocity
o.x += px + bx + fx;
o.y += py + by + fy;
},
@@ -197,40 +242,41 @@ Phaser.Physics.Ninja.Circle.prototype = {
var txw = c.xw;
var tyw = c.yw;
var dx = pos.x - tx;//tile->obj delta
var px = (txw + r) - Math.abs(dx);//penetration depth in x
var dx = pos.x - tx; // tile->obj delta
var px = (txw + r) - Math.abs(dx); // penetration depth in x
if (0 < px)
{
var dy = pos.y - ty;//tile->obj delta
var py = (tyw + r) - Math.abs(dy);//pen depth in y
var dy = pos.y - ty; // tile->obj delta
var py = (tyw + r) - Math.abs(dy); // pen depth in y
if (0 < py)
{
//object may be colliding with tile
// object may be colliding with tile
//determine grid/voronoi region of circle center
// determine grid/voronoi region of circle center
this.oH = 0;
this.oV = 0;
if (dx < -txw)
{
//circle is on left side of tile
// circle is on left side of tile
this.oH = -1;
}
else if (txw < dx)
{
//circle is on right side of tile
// circle is on right side of tile
this.oH = 1;
}
if (dy < -tyw)
{
//circle is on top side of tile
// circle is on top side of tile
this.oV = -1;
}
else if (tyw < dy)
{
//circle is on bottom side of tile
// circle is on bottom side of tile
this.oV = 1;
}
@@ -260,7 +306,7 @@ Phaser.Physics.Ninja.Circle.prototype = {
}
else
{
console.log("ResolveCircleTile() was called with an empty (or unknown) tile!: ID=" + t.id + ")");
// console.log("ResolveCircleTile() was called with an empty (or unknown) tile!: ID=" + t.id + ")");
return false;
}
@@ -352,6 +398,7 @@ Phaser.Physics.Ninja.Circle.prototype = {
var len = Math.sqrt(dx * dx + dy * dy);
var pen = obj.radius - len;
if (0 < pen)
{
//vertex is in the circle; project outward
@@ -417,6 +464,7 @@ Phaser.Physics.Ninja.Circle.prototype = {
//if the dotprod of (ox,oy) and (sx,sy) is negative, the innermost point is in the slope
//and we need toproject it out by the magnitude of the projection of (ox,oy) onto (sx,sy)
var dp = (ox * sx) + (oy * sy);
if (dp < 0)
{
//collision; project delta onto slope and use this as the slope penetration vector
+102 -41
View File
@@ -6,22 +6,53 @@
/**
* Ninja Physics Tile constructor.
*
* Note: This class could be massively optimised and reduced in size. I leave that challenge up to you.
*
* @class Phaser.Physics.Ninja.Tile
* @classdesc Arcade Physics Constructor
* @classdesc The Ninja Physics Tile class. Based on code by Metanet Software.
* @constructor
* @param {Phaser.Game} game reference to the current game instance.
* @param {Phaser.Physics.Ninja.Body} body - The body that owns this shape.
* @param {number} x - The x coordinate to create this shape at.
* @param {number} y - The y coordinate to create this shape at.
* @param {number} width - The width of this AABB.
* @param {number} height - The height of this AABB.
* @param {number} [type=1] - The type of Ninja shape to create. 1 = AABB, 2 = Circle or 3 = Tile.
*/
Phaser.Physics.Ninja.Tile = function (system, x, y, width, height, type) {
Phaser.Physics.Ninja.Tile = function (body, x, y, width, height, type) {
if (typeof type === 'undefined') { type = Phaser.Physics.Ninja.Tile.EMPTY; }
this.system = system;
/**
* @property {Phaser.Physics.Ninja.Body} system - A reference to the body that owns this shape.
*/
this.body = body;
/**
* @property {Phaser.Physics.Ninja} system - A reference to the physics system.
*/
this.system = body.system;
/**
* @property {number} id - The ID of this Tile.
* @readonly
*/
this.id = type;
/**
* @property {number} type - The type of this Tile.
* @readonly
*/
this.type = Phaser.Physics.Ninja.Tile.TYPE_EMPTY;
/**
* @property {Phaser.Point} pos - The position of this object.
*/
this.pos = new Phaser.Point(x, y);
/**
* @property {Phaser.Point} oldpos - The position of this object in the previous update.
*/
this.oldpos = new Phaser.Point(x, y);
if (this.id > 1 && this.id < 30)
@@ -30,22 +61,57 @@ Phaser.Physics.Ninja.Tile = function (system, x, y, width, height, type) {
height = width;
}
/**
* @property {number} xw - Half the width.
* @readonly
*/
this.xw = Math.abs(width / 2);
/**
* @property {number} xw - Half the height.
* @readonly
*/
this.yw = Math.abs(height / 2);
/**
* @property {number} width - The width.
* @readonly
*/
this.width = width;
/**
* @property {number} height - The height.
* @readonly
*/
this.height = height;
this.drag = 1;
this.friction = 0.05;
this.gravityScale = 1;
this.bounce = 0.3;
/**
* @property {Phaser.Point} velocity - The velocity of this object.
*/
this.velocity = new Phaser.Point();
// This stores tile-specific collision information
/**
* @property {number} signx - Internal var.
* @private
*/
this.signx = 0;
/**
* @property {number} signy - Internal var.
* @private
*/
this.signy = 0;
/**
* @property {number} sx - Internal var.
* @private
*/
this.sx = 0;
/**
* @property {number} sy - Internal var.
* @private
*/
this.sy = 0;
if (this.id > 0)
@@ -60,29 +126,37 @@ Phaser.Physics.Ninja.Tile.prototype.constructor = Phaser.Physics.Ninja.Tile;
Phaser.Physics.Ninja.Tile.prototype = {
/**
* Updates this AABBs position.
* Updates this objects position.
*
* @method Phaser.Physics.Ninja.AABB#integrate
* @method Phaser.Physics.Ninja.Tile#integrate
*/
integrate: function () {
var px = this.pos.x;
var py = this.pos.y;
this.pos.x += (this.drag * this.pos.x) - (this.drag * this.oldpos.x);
this.pos.y += (this.drag * this.pos.y) - (this.drag * this.oldpos.y);
this.pos.x += (this.body.drag * this.pos.x) - (this.body.drag * this.oldpos.x);
this.pos.y += (this.body.drag * this.pos.y) - (this.body.drag * this.oldpos.y);
this.velocity.set(this.pos.x - px, this.pos.y - py);
this.oldpos.set(px, py);
},
/**
* Tiles cannot collide with the world bounds, it's up to you to keep them where you want them. But we need this API stub to satisfy the Body.
*
* @method Phaser.Physics.Ninja.Tile#collideWorldBounds
*/
collideWorldBounds: function () {
},
//these functions are used to update the cell
//note: id is assumed to NOT be "empty" state..
//if it IS the empty state, the tile clears itself
/**
* Tiles cannot collide with the world bounds, it's up to you to keep them where you want them. But we need this API stub to satisfy the Body.
*
* @method Phaser.Physics.Ninja.Tile#setType
* @param {number} id - The type of Tile this will use, i.e. Phaser.Physics.Ninja.Tile.SLOPE_45DEGpn, Phaser.Physics.Ninja.Tile.CONVEXpp, etc.
*/
setType: function (id) {
if (id === Phaser.Physics.Ninja.Tile.EMPTY)
@@ -91,7 +165,6 @@ Phaser.Physics.Ninja.Tile.prototype = {
}
else
{
//set tile state to a non-emtpy value, and update it's edges and those of the neighbors
this.id = id;
this.updateType();
}
@@ -100,6 +173,11 @@ Phaser.Physics.Ninja.Tile.prototype = {
},
/**
* Sets this tile to be empty.
*
* @method Phaser.Physics.Ninja.Tile#clear
*/
clear: function () {
this.id = Phaser.Physics.Ninja.Tile.EMPTY;
@@ -107,28 +185,13 @@ Phaser.Physics.Ninja.Tile.prototype = {
},
render: function (context, key) {
if (this.id === 0)
{
return;
}
var image = this.system.game.cache.getImage(key);
var data = this.system.game.cache.getFrameData(key);
var frame = data._frames[this.id - 1];
context.drawImage(image, frame.x, frame.y, frame.width, frame.height, this.x, this.y, this.width, this.height);
// context.beginPath();
// context.strokeStyle = 'rgb(255,255,0)';
// context.strokeRect(this.x, this.y, this.width, this.height);
// context.strokeRect(this.pos.x, this.pos.y, 2, 2); // center point
// context.closePath();
},
//this converts a tile from implicitly-defined (via id), to explicit (via properties)
/**
* This converts a tile from implicitly-defined (via id), to explicit (via properties).
* Don't call directly, instead of setType.
*
* @method Phaser.Physics.Ninja.Tile#updateType
* @private
*/
updateType: function () {
if (this.id === 0)
@@ -567,7 +630,6 @@ Object.defineProperty(Phaser.Physics.Ninja.Tile.prototype, "right", {
});
// TILETYPE ENUMERATION
Phaser.Physics.Ninja.Tile.EMPTY = 0;
Phaser.Physics.Ninja.Tile.FULL = 1;//fullAABB tile
Phaser.Physics.Ninja.Tile.SLOPE_45DEGpn = 2;//45-degree triangle, whose normal is (+ve,-ve)
@@ -603,7 +665,6 @@ Phaser.Physics.Ninja.Tile.HALFr = 31;
Phaser.Physics.Ninja.Tile.HALFu = 32;
Phaser.Physics.Ninja.Tile.HALFl = 33;
//collision shape "types"
Phaser.Physics.Ninja.Tile.TYPE_EMPTY = 0;
Phaser.Physics.Ninja.Tile.TYPE_FULL = 1;
Phaser.Physics.Ninja.Tile.TYPE_45DEG = 2;
+31 -3
View File
@@ -7,8 +7,10 @@
/**
* Ninja Physics constructor.
*
* The Ninja Physics system was created in Flash by Metanet Software and ported to JavaScript by Richard Davey.
*
* @class Phaser.Physics.Ninja
* @classdesc Arcade Physics Constructor
* @classdesc Ninja Physics Constructor
* @constructor
* @param {Phaser.Game} game reference to the current game instance.
*/
@@ -83,7 +85,7 @@ Phaser.Physics.Ninja.prototype = {
*
* @method Phaser.Physics.Ninja#enableTile
* @param {object|array} object - The game object to create the physics body on. Can also be an array of objects, a body will be created on every object in the array.
* @param {number} radius - The radius of the Circle.
* @param {number} [id=1] - The type of Tile this will use, i.e. Phaser.Physics.Ninja.Tile.SLOPE_45DEGpn, Phaser.Physics.Ninja.Tile.CONVEXpp, etc.
*/
enableTile: function (object, id) {
@@ -131,14 +133,40 @@ Phaser.Physics.Ninja.prototype = {
},
/**
* Updates the size of this physics world.
*
* @method Phaser.Physics.Ninja#setBounds
* @param {number} x - Top left most corner of the world.
* @param {number} y - Top left most corner of the world.
* @param {number} width - New width of the world. Can never be smaller than the Game.width.
* @param {number} height - New height of the world. Can never be smaller than the Game.height.
*/
setBounds: function (x, y, width, height) {
this.bounds.setTo(x, y, width, height);
},
/**
* Updates the size of this physics world to match the size of the game world.
*
* @method Phaser.Physics.Ninja#setBoundsToWorld
*/
setBoundsToWorld: function () {
this.bounds.setTo(this.game.world.bounds.x, this.game.world.bounds.y, this.game.world.bounds.width, this.game.world.bounds.height);
},
/**
* Called automatically by a Physics body, it updates all motion related values on the Body.
*
* @method Phaser.Physics.Ninja#updateMotion
* @param {Phaser.Physics.Ninja.Body} The Body object to be updated.
*/
update: function () {
},
*/
/**
* Checks for overlaps between two game objects. The objects can be Sprites, Groups or Emitters.