2017-06-21 23:47:35 +00:00
|
|
|
// Phaser.Physics.Impact.World
|
|
|
|
|
2017-08-15 22:38:35 +00:00
|
|
|
var Body = require('./Body');
|
2017-06-21 23:47:35 +00:00
|
|
|
var Class = require('../../utils/Class');
|
2017-08-15 22:38:35 +00:00
|
|
|
var COLLIDES = require('./COLLIDES');
|
|
|
|
var CollisionMap = require('./CollisionMap');
|
2017-06-21 23:47:35 +00:00
|
|
|
var Set = require('../../structs/Set');
|
|
|
|
var Solver = require('./Solver');
|
|
|
|
var TYPE = require('./TYPE');
|
|
|
|
|
|
|
|
var World = new Class({
|
|
|
|
|
|
|
|
initialize:
|
|
|
|
|
2017-08-15 22:38:35 +00:00
|
|
|
function World (scene, gravity, cellSize)
|
2017-06-21 23:47:35 +00:00
|
|
|
{
|
2017-06-22 01:40:10 +00:00
|
|
|
if (gravity === undefined) { gravity = 0; }
|
|
|
|
if (cellSize === undefined) { cellSize = 64; }
|
2017-06-21 23:47:35 +00:00
|
|
|
|
2017-08-15 22:38:35 +00:00
|
|
|
this.scene = scene;
|
|
|
|
|
2017-06-22 01:40:10 +00:00
|
|
|
this.bodies = new Set();
|
2017-06-21 23:47:35 +00:00
|
|
|
|
2017-06-22 01:40:10 +00:00
|
|
|
this.gravity = gravity;
|
2017-06-21 23:47:35 +00:00
|
|
|
|
|
|
|
// Spatial hash cell dimensions
|
2017-06-22 01:40:10 +00:00
|
|
|
this.cellSize = cellSize;
|
|
|
|
|
|
|
|
this.collisionMap = new CollisionMap();
|
|
|
|
|
|
|
|
this.delta = 0;
|
2017-08-16 13:02:10 +00:00
|
|
|
|
|
|
|
this._lastId = 0;
|
|
|
|
},
|
|
|
|
|
|
|
|
getNextID: function ()
|
|
|
|
{
|
|
|
|
return this._lastId++;
|
2017-06-21 23:47:35 +00:00
|
|
|
},
|
|
|
|
|
2017-06-22 01:40:10 +00:00
|
|
|
create: function (x, y, sizeX, sizeY)
|
2017-06-21 23:47:35 +00:00
|
|
|
{
|
2017-06-22 01:40:10 +00:00
|
|
|
var body = new Body(this, x, y, sizeX, sizeY);
|
2017-06-21 23:47:35 +00:00
|
|
|
|
|
|
|
this.bodies.set(body);
|
|
|
|
|
|
|
|
return body;
|
|
|
|
},
|
|
|
|
|
|
|
|
update: function (time, delta)
|
|
|
|
{
|
|
|
|
if (this.bodies.size === 0)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Impact uses a divided delta value
|
|
|
|
delta /= 1000;
|
|
|
|
|
|
|
|
this.delta = delta;
|
|
|
|
|
|
|
|
// Update all bodies
|
|
|
|
|
2017-08-15 22:38:35 +00:00
|
|
|
var i;
|
2017-08-16 13:02:10 +00:00
|
|
|
var body;
|
2017-08-15 22:38:35 +00:00
|
|
|
var bodies = this.bodies.entries;
|
|
|
|
var len = bodies.length;
|
|
|
|
var hash = {};
|
|
|
|
var size = this.cellSize;
|
|
|
|
|
|
|
|
// Update all active bodies
|
|
|
|
|
|
|
|
for (i = 0; i < len; i++)
|
2017-06-27 14:24:49 +00:00
|
|
|
{
|
2017-08-16 13:02:10 +00:00
|
|
|
body = bodies[i];
|
2017-08-15 22:38:35 +00:00
|
|
|
|
2017-06-21 23:47:35 +00:00
|
|
|
if (body.enabled)
|
|
|
|
{
|
|
|
|
body.update(delta);
|
|
|
|
}
|
2017-08-15 22:38:35 +00:00
|
|
|
}
|
2017-06-21 23:47:35 +00:00
|
|
|
|
2017-08-15 22:38:35 +00:00
|
|
|
// Run collision against them all now they're in the new positions
|
2017-06-21 23:47:35 +00:00
|
|
|
|
2017-08-15 22:38:35 +00:00
|
|
|
for (i = 0; i < len; i++)
|
2017-06-21 23:47:35 +00:00
|
|
|
{
|
2017-08-16 13:02:10 +00:00
|
|
|
body = bodies[i];
|
2017-06-21 23:47:35 +00:00
|
|
|
|
2017-08-16 13:02:10 +00:00
|
|
|
if (!body.skipHash())
|
2017-06-21 23:47:35 +00:00
|
|
|
{
|
|
|
|
this.checkHash(body, hash, size);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
// Check the body against the spatial hash
|
|
|
|
checkHash: function (body, hash, size)
|
|
|
|
{
|
|
|
|
var checked = {};
|
2017-08-15 22:38:35 +00:00
|
|
|
|
2017-06-21 23:47:35 +00:00
|
|
|
var xmin = Math.floor(body.pos.x / size);
|
|
|
|
var ymin = Math.floor(body.pos.y / size);
|
|
|
|
var xmax = Math.floor((body.pos.x + body.size.x) / size) + 1;
|
|
|
|
var ymax = Math.floor((body.pos.y + body.size.y) / size) + 1;
|
|
|
|
|
|
|
|
for (var x = xmin; x < xmax; x++)
|
|
|
|
{
|
|
|
|
for (var y = ymin; y < ymax; y++)
|
|
|
|
{
|
|
|
|
if (!hash[x])
|
|
|
|
{
|
|
|
|
hash[x] = {};
|
2017-06-23 17:08:22 +00:00
|
|
|
hash[x][y] = [ body ];
|
2017-06-21 23:47:35 +00:00
|
|
|
}
|
|
|
|
else if (!hash[x][y])
|
|
|
|
{
|
2017-06-23 17:08:22 +00:00
|
|
|
hash[x][y] = [ body ];
|
2017-06-21 23:47:35 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
var cell = hash[x][y];
|
|
|
|
|
|
|
|
for (var c = 0; c < cell.length; c++)
|
|
|
|
{
|
|
|
|
if (body.touches(cell[c]) && !checked[cell[c].id])
|
|
|
|
{
|
|
|
|
checked[cell[c].id] = true;
|
|
|
|
|
|
|
|
this.checkBodies(body, cell[c]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
cell.push(body);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
checkBodies: function (bodyA, bodyB)
|
|
|
|
{
|
|
|
|
// bitwise checks
|
|
|
|
if (bodyA.checkAgainst & bodyB.type)
|
|
|
|
{
|
|
|
|
bodyA.check(bodyB);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bodyB.checkAgainst & bodyA.type)
|
|
|
|
{
|
|
|
|
bodyB.check(bodyA);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bodyA.collides && bodyB.collides && bodyA.collides + bodyB.collides > COLLIDES.ACTIVE)
|
|
|
|
{
|
|
|
|
Solver(this, bodyA, bodyB);
|
|
|
|
}
|
2017-08-16 00:20:35 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
//////////////
|
|
|
|
// Helpers //
|
|
|
|
//////////////
|
|
|
|
|
|
|
|
setCollidesNever: function (bodies)
|
|
|
|
{
|
|
|
|
for (var i = 0; i < bodies.length; i++)
|
|
|
|
{
|
|
|
|
bodies[i].collides = COLLIDES.NEVER;
|
|
|
|
}
|
|
|
|
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
|
|
|
|
setLite: function (bodies)
|
|
|
|
{
|
|
|
|
for (var i = 0; i < bodies.length; i++)
|
|
|
|
{
|
|
|
|
bodies[i].collides = COLLIDES.LITE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
|
|
|
|
setPassive: function (bodies)
|
|
|
|
{
|
|
|
|
for (var i = 0; i < bodies.length; i++)
|
|
|
|
{
|
|
|
|
bodies[i].collides = COLLIDES.PASSIVE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
|
|
|
|
setActive: function (bodies)
|
|
|
|
{
|
|
|
|
for (var i = 0; i < bodies.length; i++)
|
|
|
|
{
|
|
|
|
bodies[i].collides = COLLIDES.ACTIVE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
|
|
|
|
setFixed: function (bodies)
|
|
|
|
{
|
|
|
|
for (var i = 0; i < bodies.length; i++)
|
|
|
|
{
|
|
|
|
bodies[i].collides = COLLIDES.FIXED;
|
|
|
|
}
|
|
|
|
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
|
|
|
|
setTypeNone: function (bodies)
|
|
|
|
{
|
|
|
|
for (var i = 0; i < bodies.length; i++)
|
|
|
|
{
|
|
|
|
bodies[i].type = TYPE.NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
|
|
|
|
setTypeA: function (bodies)
|
|
|
|
{
|
|
|
|
for (var i = 0; i < bodies.length; i++)
|
|
|
|
{
|
|
|
|
bodies[i].type = TYPE.A;
|
|
|
|
}
|
|
|
|
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
|
|
|
|
setTypeB: function (bodies)
|
|
|
|
{
|
|
|
|
for (var i = 0; i < bodies.length; i++)
|
|
|
|
{
|
|
|
|
bodies[i].type = TYPE.B;
|
|
|
|
}
|
|
|
|
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
|
|
|
|
setAvsB: function (bodies)
|
|
|
|
{
|
|
|
|
for (var i = 0; i < bodies.length; i++)
|
|
|
|
{
|
|
|
|
bodies[i].type = TYPE.A;
|
|
|
|
bodies[i].checkAgainst = TYPE.B;
|
|
|
|
}
|
|
|
|
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
|
|
|
|
setBvsA: function (bodies)
|
|
|
|
{
|
|
|
|
for (var i = 0; i < bodies.length; i++)
|
|
|
|
{
|
|
|
|
bodies[i].type = TYPE.B;
|
|
|
|
bodies[i].checkAgainst = TYPE.A;
|
|
|
|
}
|
|
|
|
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
|
|
|
|
setCheckAgainstNone: function (bodies)
|
|
|
|
{
|
|
|
|
for (var i = 0; i < bodies.length; i++)
|
|
|
|
{
|
|
|
|
bodies[i].checkAgainst = TYPE.NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
|
|
|
|
setCheckAgainstA: function (bodies)
|
|
|
|
{
|
|
|
|
for (var i = 0; i < bodies.length; i++)
|
|
|
|
{
|
|
|
|
bodies[i].checkAgainst = TYPE.A;
|
|
|
|
}
|
|
|
|
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
|
|
|
|
setCheckAgainstB: function (bodies)
|
|
|
|
{
|
|
|
|
for (var i = 0; i < bodies.length; i++)
|
|
|
|
{
|
|
|
|
bodies[i].checkAgainst = TYPE.B;
|
|
|
|
}
|
|
|
|
|
|
|
|
return this;
|
2017-06-21 23:47:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
module.exports = World;
|