2017-11-08 17:18:41 +00:00
|
|
|
var Body = require('./Body');
|
2017-11-09 04:03:59 +00:00
|
|
|
var Class = require('../../utils/Class');
|
2017-11-09 17:03:58 +00:00
|
|
|
var Collider = require('./Collider');
|
2017-11-09 15:32:34 +00:00
|
|
|
var CONST = require('./const');
|
2018-01-12 17:09:09 +00:00
|
|
|
var EventEmitter = require('eventemitter3');
|
2017-11-08 17:18:41 +00:00
|
|
|
var GetValue = require('../../utils/object/GetValue');
|
2018-01-12 17:09:09 +00:00
|
|
|
var ProcessQueue = require('../../structs/ProcessQueue');
|
2017-11-09 04:03:59 +00:00
|
|
|
var Rectangle = require('../../geom/rectangle/Rectangle');
|
|
|
|
var RTree = require('../../structs/RTree');
|
2017-11-08 17:18:41 +00:00
|
|
|
var Set = require('../../structs/Set');
|
2017-11-09 15:32:34 +00:00
|
|
|
var StaticBody = require('./StaticBody');
|
2017-11-09 04:03:59 +00:00
|
|
|
var Vector2 = require('../../math/Vector2');
|
2017-11-06 04:50:07 +00:00
|
|
|
|
2018-01-17 03:41:58 +00:00
|
|
|
// Phaser.Physics.Arcade.World
|
|
|
|
|
2017-11-06 04:50:07 +00:00
|
|
|
var World = new Class({
|
|
|
|
|
2018-01-12 17:09:09 +00:00
|
|
|
Extends: EventEmitter,
|
|
|
|
|
2017-11-06 04:50:07 +00:00
|
|
|
initialize:
|
|
|
|
|
2017-11-08 17:18:41 +00:00
|
|
|
function World (scene, config)
|
2017-11-06 04:50:07 +00:00
|
|
|
{
|
2018-01-12 17:09:09 +00:00
|
|
|
EventEmitter.call(this);
|
2017-11-06 04:50:07 +00:00
|
|
|
|
2018-01-12 17:09:09 +00:00
|
|
|
this.scene = scene;
|
2017-11-06 04:50:07 +00:00
|
|
|
|
2017-11-09 15:32:34 +00:00
|
|
|
// Dynamic Bodies
|
2017-11-08 17:18:41 +00:00
|
|
|
this.bodies = new Set();
|
2017-11-06 04:50:07 +00:00
|
|
|
|
2017-11-09 15:32:34 +00:00
|
|
|
// Static Bodies
|
|
|
|
this.staticBodies = new Set();
|
|
|
|
|
2017-11-09 23:56:28 +00:00
|
|
|
this.colliders = new ProcessQueue();
|
2017-11-09 17:03:58 +00:00
|
|
|
|
2017-11-08 17:18:41 +00:00
|
|
|
this.gravity = new Vector2(GetValue(config, 'gravity.x', 0), GetValue(config, 'gravity.y', 0));
|
2017-11-06 04:50:07 +00:00
|
|
|
|
2017-11-08 17:18:41 +00:00
|
|
|
this.bounds = new Rectangle(
|
|
|
|
GetValue(config, 'x', 0),
|
|
|
|
GetValue(config, 'y', 0),
|
|
|
|
GetValue(config, 'width', scene.sys.game.config.width),
|
|
|
|
GetValue(config, 'height', scene.sys.game.config.height)
|
|
|
|
);
|
2017-11-06 04:50:07 +00:00
|
|
|
|
2017-11-08 17:18:41 +00:00
|
|
|
this.checkCollision = {
|
|
|
|
up: GetValue(config, 'checkCollision.up', true),
|
|
|
|
down: GetValue(config, 'checkCollision.down', true),
|
|
|
|
left: GetValue(config, 'checkCollision.left', true),
|
|
|
|
right: GetValue(config, 'checkCollision.right', true)
|
|
|
|
};
|
2017-11-06 04:50:07 +00:00
|
|
|
|
2017-11-08 17:18:41 +00:00
|
|
|
this.OVERLAP_BIAS = GetValue(config, 'overlapBias', 4);
|
|
|
|
|
2018-01-11 14:32:07 +00:00
|
|
|
this.TILE_BIAS = GetValue(config, 'tileBias', 16);
|
|
|
|
|
2017-11-08 17:18:41 +00:00
|
|
|
this.forceX = GetValue(config, 'forceX', false);
|
2017-11-06 04:50:07 +00:00
|
|
|
|
2017-11-08 17:18:41 +00:00
|
|
|
this.isPaused = GetValue(config, 'isPaused', false);
|
2017-11-06 04:50:07 +00:00
|
|
|
|
|
|
|
this._total = 0;
|
|
|
|
|
2017-11-08 17:18:41 +00:00
|
|
|
this.drawDebug = GetValue(config, 'debug', false);
|
|
|
|
|
2017-11-09 04:03:59 +00:00
|
|
|
this.debugGraphic;
|
2017-11-08 17:18:41 +00:00
|
|
|
|
|
|
|
this.defaults = {
|
|
|
|
debugShowBody: GetValue(config, 'debugShowBody', true),
|
2017-11-09 16:32:09 +00:00
|
|
|
debugShowStaticBody: GetValue(config, 'debugShowStaticBody', true),
|
2017-11-08 17:18:41 +00:00
|
|
|
debugShowVelocity: GetValue(config, 'debugShowVelocity', true),
|
|
|
|
bodyDebugColor: GetValue(config, 'debugBodyColor', 0xff00ff),
|
2017-11-09 16:32:09 +00:00
|
|
|
staticBodyDebugColor: GetValue(config, 'debugBodyColor', 0x0000ff),
|
2017-11-08 17:18:41 +00:00
|
|
|
velocityDebugColor: GetValue(config, 'debugVelocityColor', 0x00ff00)
|
|
|
|
};
|
|
|
|
|
2017-11-09 04:03:59 +00:00
|
|
|
this.maxEntries = GetValue(config, 'maxEntries', 16);
|
|
|
|
|
2017-11-09 13:02:55 +00:00
|
|
|
this.tree = new RTree(this.maxEntries, [ '.left', '.top', '.right', '.bottom' ]);
|
2017-11-09 15:32:34 +00:00
|
|
|
this.staticTree = new RTree(this.maxEntries, [ '.left', '.top', '.right', '.bottom' ]);
|
2017-11-09 04:03:59 +00:00
|
|
|
|
|
|
|
this.treeMinMax = { minX: 0, minY: 0, maxX: 0, maxY: 0 };
|
|
|
|
|
2017-11-08 17:18:41 +00:00
|
|
|
if (this.drawDebug)
|
|
|
|
{
|
|
|
|
this.createDebugGraphic();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2017-11-09 15:32:34 +00:00
|
|
|
enable: function (object, type)
|
2017-11-09 13:02:55 +00:00
|
|
|
{
|
2017-11-09 15:32:34 +00:00
|
|
|
if (type === undefined) { type = CONST.DYNAMIC_BODY; }
|
|
|
|
|
2017-11-09 13:02:55 +00:00
|
|
|
var i = 1;
|
|
|
|
|
|
|
|
if (Array.isArray(object))
|
|
|
|
{
|
|
|
|
i = object.length;
|
|
|
|
|
|
|
|
while (i--)
|
|
|
|
{
|
|
|
|
if (object[i].hasOwnProperty('children'))
|
|
|
|
{
|
|
|
|
// If it's a Group then we do it on the children regardless
|
2017-11-09 15:32:34 +00:00
|
|
|
this.enable(object[i].children.entries, type);
|
2017-11-09 13:02:55 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-11-09 15:32:34 +00:00
|
|
|
this.enableBody(object[i], type);
|
2017-11-09 13:02:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (object.hasOwnProperty('children'))
|
|
|
|
{
|
|
|
|
// If it's a Group then we do it on the children regardless
|
2017-11-09 15:32:34 +00:00
|
|
|
this.enable(object.children.entries, type);
|
2017-11-09 13:02:55 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-11-09 15:32:34 +00:00
|
|
|
this.enableBody(object, type);
|
2017-11-09 13:02:55 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2017-11-09 15:32:34 +00:00
|
|
|
enableBody: function (object, type)
|
2017-11-09 13:02:55 +00:00
|
|
|
{
|
|
|
|
if (object.body === null)
|
|
|
|
{
|
2017-11-09 15:32:34 +00:00
|
|
|
if (type === CONST.DYNAMIC_BODY)
|
|
|
|
{
|
|
|
|
object.body = new Body(this, object);
|
|
|
|
|
|
|
|
this.bodies.set(object.body);
|
|
|
|
}
|
|
|
|
else if (type === CONST.STATIC_BODY)
|
|
|
|
{
|
|
|
|
object.body = new StaticBody(this, object);
|
|
|
|
|
|
|
|
this.staticBodies.set(object.body);
|
2017-11-09 13:02:55 +00:00
|
|
|
|
2017-11-09 15:32:34 +00:00
|
|
|
this.staticTree.insert(object.body);
|
|
|
|
}
|
2017-11-09 13:02:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return object;
|
|
|
|
},
|
|
|
|
|
2017-12-02 04:04:15 +00:00
|
|
|
remove: function (object)
|
|
|
|
{
|
|
|
|
this.disableBody(object);
|
|
|
|
},
|
|
|
|
|
2017-11-09 13:02:55 +00:00
|
|
|
disable: function (object)
|
|
|
|
{
|
|
|
|
var i = 1;
|
|
|
|
|
|
|
|
if (Array.isArray(object))
|
|
|
|
{
|
|
|
|
i = object.length;
|
|
|
|
|
|
|
|
while (i--)
|
|
|
|
{
|
|
|
|
if (object[i].hasOwnProperty('children'))
|
|
|
|
{
|
|
|
|
// If it's a Group then we do it on the children regardless
|
|
|
|
this.disable(object[i].children.entries);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this.disableBody(object[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (object.hasOwnProperty('children'))
|
|
|
|
{
|
|
|
|
// If it's a Group then we do it on the children regardless
|
|
|
|
this.disable(object.children.entries);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this.disableBody(object);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
disableBody: function (object)
|
|
|
|
{
|
|
|
|
if (object.body)
|
|
|
|
{
|
2017-11-09 15:32:34 +00:00
|
|
|
if (object.body.physicsType === CONST.DYNAMIC_BODY)
|
|
|
|
{
|
|
|
|
this.bodies.delete(object.body);
|
|
|
|
}
|
|
|
|
else if (object.body.physicsType === CONST.STATIC_BODY)
|
|
|
|
{
|
|
|
|
this.staticBodies.delete(object.body);
|
|
|
|
this.staticTree.remove(object.body);
|
|
|
|
}
|
2017-11-09 13:02:55 +00:00
|
|
|
|
|
|
|
object.body.destroy();
|
|
|
|
object.body = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
return object;
|
|
|
|
},
|
|
|
|
|
2017-11-08 17:18:41 +00:00
|
|
|
createDebugGraphic: function ()
|
|
|
|
{
|
|
|
|
var graphic = this.scene.sys.add.graphics({ x: 0, y: 0 });
|
|
|
|
|
|
|
|
graphic.setZ(Number.MAX_SAFE_INTEGER);
|
|
|
|
|
|
|
|
this.debugGraphic = graphic;
|
|
|
|
|
|
|
|
this.drawDebug = true;
|
|
|
|
|
|
|
|
return graphic;
|
2017-11-06 04:50:07 +00:00
|
|
|
},
|
|
|
|
|
2017-12-02 04:04:15 +00:00
|
|
|
setBounds: function (x, y, width, height, checkLeft, checkRight, checkUp, checkDown)
|
2017-11-06 04:50:07 +00:00
|
|
|
{
|
|
|
|
this.bounds.setTo(x, y, width, height);
|
|
|
|
|
2017-12-02 04:04:15 +00:00
|
|
|
if (checkLeft !== undefined)
|
|
|
|
{
|
|
|
|
this.setBoundsCollision(checkLeft, checkRight, checkUp, checkDown);
|
|
|
|
}
|
|
|
|
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
|
|
|
|
setBoundsCollision: function (left, right, up, down)
|
|
|
|
{
|
|
|
|
if (left === undefined) { left = true; }
|
|
|
|
if (right === undefined) { right = true; }
|
|
|
|
if (up === undefined) { up = true; }
|
|
|
|
if (down === undefined) { down = true; }
|
|
|
|
|
|
|
|
this.checkCollision.left = left;
|
|
|
|
this.checkCollision.right = right;
|
|
|
|
this.checkCollision.up = up;
|
|
|
|
this.checkCollision.down = down;
|
|
|
|
|
2017-11-06 04:50:07 +00:00
|
|
|
return this;
|
|
|
|
},
|
|
|
|
|
2017-11-08 17:18:41 +00:00
|
|
|
pause: function ()
|
|
|
|
{
|
|
|
|
this.isPaused = true;
|
|
|
|
|
2018-01-12 17:09:09 +00:00
|
|
|
this.emit('pause');
|
|
|
|
|
2017-11-08 17:18:41 +00:00
|
|
|
return this;
|
|
|
|
},
|
|
|
|
|
|
|
|
resume: function ()
|
|
|
|
{
|
|
|
|
this.isPaused = false;
|
|
|
|
|
2018-01-12 17:09:09 +00:00
|
|
|
this.emit('resume');
|
|
|
|
|
2017-11-08 17:18:41 +00:00
|
|
|
return this;
|
|
|
|
},
|
|
|
|
|
2017-11-09 17:03:58 +00:00
|
|
|
addCollider: function (object1, object2, collideCallback, processCallback, callbackContext)
|
|
|
|
{
|
|
|
|
if (collideCallback === undefined) { collideCallback = null; }
|
|
|
|
if (processCallback === undefined) { processCallback = null; }
|
|
|
|
if (callbackContext === undefined) { callbackContext = collideCallback; }
|
|
|
|
|
|
|
|
var collider = new Collider(this, false, object1, object2, collideCallback, processCallback, callbackContext);
|
|
|
|
|
2017-11-09 23:56:28 +00:00
|
|
|
this.colliders.add(collider);
|
2017-11-09 17:03:58 +00:00
|
|
|
|
|
|
|
return collider;
|
|
|
|
},
|
|
|
|
|
|
|
|
addOverlap: function (object1, object2, collideCallback, processCallback, callbackContext)
|
|
|
|
{
|
|
|
|
if (collideCallback === undefined) { collideCallback = null; }
|
|
|
|
if (processCallback === undefined) { processCallback = null; }
|
|
|
|
if (callbackContext === undefined) { callbackContext = collideCallback; }
|
|
|
|
|
|
|
|
var collider = new Collider(this, true, object1, object2, collideCallback, processCallback, callbackContext);
|
|
|
|
|
2017-11-09 23:56:28 +00:00
|
|
|
this.colliders.add(collider);
|
2017-11-09 17:03:58 +00:00
|
|
|
|
|
|
|
return collider;
|
|
|
|
},
|
|
|
|
|
2017-11-09 17:10:33 +00:00
|
|
|
removeCollider: function (collider)
|
|
|
|
{
|
2017-11-09 23:56:28 +00:00
|
|
|
this.colliders.remove(collider);
|
2017-11-09 17:10:33 +00:00
|
|
|
},
|
|
|
|
|
2017-11-08 17:18:41 +00:00
|
|
|
update: function (time, delta)
|
|
|
|
{
|
|
|
|
if (this.isPaused || this.bodies.size === 0)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// this.delta = Math.min(delta / 1000, this.maxStep) * this.timeScale;
|
|
|
|
delta /= 1000;
|
|
|
|
|
|
|
|
this.delta = delta;
|
|
|
|
|
|
|
|
// Update all active bodies
|
|
|
|
|
|
|
|
var i;
|
|
|
|
var body;
|
|
|
|
var bodies = this.bodies.entries;
|
|
|
|
var len = bodies.length;
|
|
|
|
|
|
|
|
for (i = 0; i < len; i++)
|
|
|
|
{
|
|
|
|
body = bodies[i];
|
|
|
|
|
|
|
|
if (body.enable)
|
|
|
|
{
|
|
|
|
body.update(delta);
|
|
|
|
}
|
|
|
|
}
|
2017-11-09 04:03:59 +00:00
|
|
|
|
2017-11-09 15:32:34 +00:00
|
|
|
// Populate our dynamic collision tree
|
2017-11-09 04:03:59 +00:00
|
|
|
this.tree.clear();
|
|
|
|
this.tree.load(bodies);
|
2017-11-09 17:03:58 +00:00
|
|
|
|
|
|
|
// Process any colliders
|
2017-11-09 23:56:28 +00:00
|
|
|
var colliders = this.colliders.update();
|
2017-11-09 17:03:58 +00:00
|
|
|
|
2017-11-09 23:56:28 +00:00
|
|
|
for (i = 0; i < colliders.length; i++)
|
2017-11-09 17:03:58 +00:00
|
|
|
{
|
2017-11-09 23:56:28 +00:00
|
|
|
var collider = colliders[i];
|
2017-11-09 17:10:33 +00:00
|
|
|
|
|
|
|
if (collider.active)
|
|
|
|
{
|
|
|
|
collider.update();
|
|
|
|
}
|
2017-11-09 17:03:58 +00:00
|
|
|
}
|
2017-11-08 17:18:41 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
postUpdate: function ()
|
|
|
|
{
|
|
|
|
var i;
|
|
|
|
var body;
|
|
|
|
var bodies = this.bodies.entries;
|
|
|
|
var len = bodies.length;
|
|
|
|
|
|
|
|
for (i = 0; i < len; i++)
|
|
|
|
{
|
|
|
|
body = bodies[i];
|
|
|
|
|
|
|
|
if (body.enable)
|
|
|
|
{
|
|
|
|
body.postUpdate();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this.drawDebug)
|
|
|
|
{
|
|
|
|
var graphics = this.debugGraphic;
|
|
|
|
|
|
|
|
graphics.clear();
|
|
|
|
|
|
|
|
for (i = 0; i < len; i++)
|
|
|
|
{
|
|
|
|
body = bodies[i];
|
|
|
|
|
|
|
|
if (body.willDrawDebug())
|
|
|
|
{
|
|
|
|
body.drawDebug(graphics);
|
|
|
|
}
|
|
|
|
}
|
2017-11-09 15:32:34 +00:00
|
|
|
|
|
|
|
bodies = this.staticBodies.entries;
|
|
|
|
len = bodies.length;
|
|
|
|
|
|
|
|
for (i = 0; i < len; i++)
|
|
|
|
{
|
|
|
|
body = bodies[i];
|
|
|
|
|
|
|
|
if (body.willDrawDebug())
|
|
|
|
{
|
|
|
|
body.drawDebug(graphics);
|
|
|
|
}
|
|
|
|
}
|
2017-11-08 17:18:41 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2017-11-09 13:02:55 +00:00
|
|
|
updateMotion: require('./inc/UpdateMotion'),
|
|
|
|
computeVelocity: require('./inc/ComputeVelocity'),
|
|
|
|
separate: require('./inc/Separate'),
|
|
|
|
separateCircle: require('./inc/SeparateCircle'),
|
|
|
|
intersects: require('./inc/Intersects'),
|
|
|
|
circleBodyIntersects: require('./inc/CircleBodyIntersects'),
|
|
|
|
overlap: require('./inc/Overlap'),
|
|
|
|
collide: require('./inc/Collide'),
|
|
|
|
collideObjects: require('./inc/CollideObjects'),
|
|
|
|
collideHandler: require('./inc/CollideHandler'),
|
|
|
|
collideSpriteVsSprite: require('./inc/CollideSpriteVsSprite'),
|
|
|
|
collideSpriteVsGroup: require('./inc/CollideSpriteVsGroup'),
|
2018-01-11 02:43:11 +00:00
|
|
|
collideGroupVsTilemapLayer: require('./inc/CollideGroupVsTilemapLayer'),
|
|
|
|
collideSpriteVsTilemapLayer: require('./inc/CollideSpriteVsTilemapLayer'),
|
2017-11-09 13:02:55 +00:00
|
|
|
|
|
|
|
// TODO
|
2017-11-09 04:03:59 +00:00
|
|
|
collideGroupVsGroup: function (group1, group2, collideCallback, processCallback, callbackContext, overlapOnly)
|
|
|
|
{
|
|
|
|
if (group1.length === 0 || group2.length === 0)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2017-11-09 13:02:55 +00:00
|
|
|
shutdown: function ()
|
2017-11-09 04:03:59 +00:00
|
|
|
{
|
2018-01-12 17:09:09 +00:00
|
|
|
this.removeAllListeners();
|
2017-11-09 04:03:59 +00:00
|
|
|
},
|
|
|
|
|
2017-11-09 13:02:55 +00:00
|
|
|
destroy: function ()
|
2017-11-08 17:18:41 +00:00
|
|
|
{
|
2018-01-12 17:09:09 +00:00
|
|
|
this.removeAllListeners();
|
2017-11-08 17:18:41 +00:00
|
|
|
}
|
|
|
|
|
2017-11-06 04:50:07 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
module.exports = World;
|