2017-11-21 02:04:05 +00:00
|
|
|
// Phaser.Physics.Matter.World
|
2017-11-20 16:54:26 +00:00
|
|
|
|
2017-11-21 16:54:54 +00:00
|
|
|
var Bodies = require('./lib/factory/Bodies');
|
2017-11-20 16:54:26 +00:00
|
|
|
var Class = require('../../utils/Class');
|
2017-11-27 03:45:46 +00:00
|
|
|
var Composite = require('./lib/body/Composite');
|
2017-11-21 16:54:54 +00:00
|
|
|
var Engine = require('./lib/core/Engine');
|
2018-01-12 17:09:09 +00:00
|
|
|
var EventEmitter = require('eventemitter3');
|
2017-11-21 16:54:54 +00:00
|
|
|
var GetFastValue = require('../../utils/object/GetFastValue');
|
2017-11-22 02:25:30 +00:00
|
|
|
var GetValue = require('../../utils/object/GetValue');
|
|
|
|
var MatterBody = require('./lib/body/Body');
|
|
|
|
var MatterEvents = require('./lib/core/Events');
|
2017-11-21 16:54:54 +00:00
|
|
|
var MatterWorld = require('./lib/body/World');
|
2017-11-20 16:54:26 +00:00
|
|
|
|
|
|
|
var World = new Class({
|
|
|
|
|
2018-01-12 18:59:11 +00:00
|
|
|
Extends: EventEmitter,
|
|
|
|
|
2017-11-20 16:54:26 +00:00
|
|
|
initialize:
|
|
|
|
|
|
|
|
function World (scene, config)
|
|
|
|
{
|
2018-01-12 18:59:11 +00:00
|
|
|
EventEmitter.call(this);
|
|
|
|
|
2017-11-20 16:54:26 +00:00
|
|
|
this.scene = scene;
|
|
|
|
|
2017-11-21 16:54:54 +00:00
|
|
|
this.engine = Engine.create(config);
|
|
|
|
|
|
|
|
this.localWorld = this.engine.world;
|
|
|
|
|
|
|
|
var gravity = GetValue(config, 'gravity', null);
|
|
|
|
|
|
|
|
if (gravity)
|
|
|
|
{
|
|
|
|
this.setGravity(gravity.x, gravity.y, gravity.scale);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @property {object} walls - An object containing the 4 wall bodies that bound the physics world.
|
|
|
|
*/
|
|
|
|
this.walls = { left: null, right: null, top: null, bottom: null };
|
|
|
|
|
|
|
|
if (GetFastValue(config, 'setBounds', false))
|
|
|
|
{
|
|
|
|
var boundsConfig = config['setBounds'];
|
|
|
|
|
|
|
|
if (typeof boundsConfig === 'boolean')
|
|
|
|
{
|
|
|
|
this.setBounds();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
var x = GetFastValue(boundsConfig, 'x', 0);
|
|
|
|
var y = GetFastValue(boundsConfig, 'y', 0);
|
|
|
|
var width = GetFastValue(boundsConfig, 'width', scene.sys.game.config.width);
|
|
|
|
var height = GetFastValue(boundsConfig, 'height', scene.sys.game.config.height);
|
|
|
|
var thickness = GetFastValue(boundsConfig, 'thickness', 64);
|
|
|
|
var left = GetFastValue(boundsConfig, 'left', true);
|
|
|
|
var right = GetFastValue(boundsConfig, 'right', true);
|
|
|
|
var top = GetFastValue(boundsConfig, 'top', true);
|
|
|
|
var bottom = GetFastValue(boundsConfig, 'bottom', true);
|
|
|
|
|
|
|
|
this.setBounds(x, y, width, height, thickness, left, right, top, bottom);
|
|
|
|
}
|
|
|
|
}
|
2017-11-22 02:25:30 +00:00
|
|
|
|
2017-11-27 03:45:46 +00:00
|
|
|
this.isPaused = GetValue(config, 'isPaused', false);
|
|
|
|
|
|
|
|
this.drawDebug = GetValue(config, 'debug', false);
|
|
|
|
|
|
|
|
this.debugGraphic;
|
|
|
|
|
|
|
|
this.defaults = {
|
|
|
|
debugShowBody: GetValue(config, 'debugShowBody', true),
|
|
|
|
debugShowStaticBody: GetValue(config, 'debugShowStaticBody', true),
|
|
|
|
debugShowVelocity: GetValue(config, 'debugShowVelocity', true),
|
|
|
|
bodyDebugColor: GetValue(config, 'debugBodyColor', 0xff00ff),
|
|
|
|
staticBodyDebugColor: GetValue(config, 'debugBodyColor', 0x0000ff),
|
|
|
|
velocityDebugColor: GetValue(config, 'debugVelocityColor', 0x00ff00)
|
|
|
|
};
|
|
|
|
|
|
|
|
if (this.drawDebug)
|
|
|
|
{
|
|
|
|
this.createDebugGraphic();
|
|
|
|
}
|
|
|
|
|
2017-11-22 02:25:30 +00:00
|
|
|
this.setEventsProxy();
|
|
|
|
},
|
|
|
|
|
|
|
|
setEventsProxy: function ()
|
|
|
|
{
|
2018-01-12 18:59:11 +00:00
|
|
|
var _this = this;
|
|
|
|
var engine = this.engine;
|
2017-11-22 02:25:30 +00:00
|
|
|
|
2018-01-12 18:59:11 +00:00
|
|
|
MatterEvents.on(engine, 'beforeUpdate', function (event) {
|
2017-11-23 01:45:38 +00:00
|
|
|
|
2018-01-12 18:59:11 +00:00
|
|
|
_this.emit('beforeupdate', event);
|
2017-11-23 01:45:38 +00:00
|
|
|
|
|
|
|
});
|
|
|
|
|
2018-01-12 18:59:11 +00:00
|
|
|
MatterEvents.on(engine, 'afterUpdate', function (event) {
|
2017-11-23 01:45:38 +00:00
|
|
|
|
2018-01-12 18:59:11 +00:00
|
|
|
_this.emit('afterupdate', event);
|
2017-11-23 01:45:38 +00:00
|
|
|
|
|
|
|
});
|
|
|
|
|
2018-01-12 18:59:11 +00:00
|
|
|
MatterEvents.on(engine, 'collisionStart', function (event) {
|
|
|
|
|
|
|
|
var pairs = event.pairs;
|
|
|
|
var bodyA;
|
|
|
|
var bodyB;
|
2017-11-22 02:25:30 +00:00
|
|
|
|
2018-01-12 18:59:11 +00:00
|
|
|
if (pairs.length > 0)
|
|
|
|
{
|
|
|
|
bodyA = pairs[0].bodyA;
|
|
|
|
bodyB = pairs[0].bodyB;
|
|
|
|
}
|
|
|
|
|
|
|
|
_this.emit('collisionstart', event, bodyA, bodyB);
|
2017-11-22 02:25:30 +00:00
|
|
|
|
|
|
|
});
|
|
|
|
|
2018-01-12 18:59:11 +00:00
|
|
|
MatterEvents.on(engine, 'collisionActive', function (event) {
|
2017-11-22 02:25:30 +00:00
|
|
|
|
2018-01-12 18:59:11 +00:00
|
|
|
var pairs = event.pairs;
|
|
|
|
var bodyA;
|
|
|
|
var bodyB;
|
|
|
|
|
|
|
|
if (pairs.length > 0)
|
|
|
|
{
|
|
|
|
bodyA = pairs[0].bodyA;
|
|
|
|
bodyB = pairs[0].bodyB;
|
|
|
|
}
|
|
|
|
|
|
|
|
_this.emit('collisionactive', event, bodyA, bodyB);
|
2017-11-22 02:25:30 +00:00
|
|
|
|
|
|
|
});
|
|
|
|
|
2018-01-12 18:59:11 +00:00
|
|
|
MatterEvents.on(engine, 'collisionEnd', function (event) {
|
|
|
|
|
|
|
|
var pairs = event.pairs;
|
|
|
|
var bodyA;
|
|
|
|
var bodyB;
|
|
|
|
|
|
|
|
if (pairs.length > 0)
|
|
|
|
{
|
|
|
|
bodyA = pairs[0].bodyA;
|
|
|
|
bodyB = pairs[0].bodyB;
|
|
|
|
}
|
2017-11-22 02:25:30 +00:00
|
|
|
|
2018-01-12 18:59:11 +00:00
|
|
|
_this.emit('collisionend', event, bodyA, bodyB);
|
2017-11-22 02:25:30 +00:00
|
|
|
|
|
|
|
});
|
2017-11-21 16:54:54 +00:00
|
|
|
},
|
2017-11-21 02:04:05 +00:00
|
|
|
|
2017-11-21 16:54:54 +00:00
|
|
|
/**
|
|
|
|
* Sets the bounds of the Physics world to match the given world pixel dimensions.
|
|
|
|
* You can optionally set which 'walls' to create: left, right, top or bottom.
|
|
|
|
* If none of the walls are given it will default to use the walls settings it had previously.
|
|
|
|
* I.e. if you previously told it to not have the left or right walls, and you then adjust the world size
|
|
|
|
* the newly created bounds will also not have the left and right walls.
|
|
|
|
* Explicitly state them in the parameters to override this.
|
|
|
|
*
|
|
|
|
* @method Phaser.Physics.P2#setBounds
|
|
|
|
* @param {number} x - The x coordinate of the top-left corner of the bounds.
|
|
|
|
* @param {number} y - The y coordinate of the top-left corner of the bounds.
|
|
|
|
* @param {number} width - The width of the bounds.
|
|
|
|
* @param {number} height - The height of the bounds.
|
|
|
|
* @param {boolean} [left=true] - If true will create the left bounds wall.
|
|
|
|
* @param {boolean} [right=true] - If true will create the right bounds wall.
|
|
|
|
* @param {boolean} [top=true] - If true will create the top bounds wall.
|
|
|
|
* @param {boolean} [bottom=true] - If true will create the bottom bounds wall.
|
|
|
|
*/
|
|
|
|
setBounds: function (x, y, width, height, thickness, left, right, top, bottom)
|
|
|
|
{
|
|
|
|
if (x === undefined) { x = 0; }
|
|
|
|
if (y === undefined) { y = 0; }
|
|
|
|
if (width === undefined) { width = this.scene.sys.game.config.width; }
|
|
|
|
if (height === undefined) { height = this.scene.sys.game.config.height; }
|
2017-11-23 14:59:15 +00:00
|
|
|
if (thickness === undefined) { thickness = 128; }
|
2017-11-21 16:54:54 +00:00
|
|
|
if (left === undefined) { left = true; }
|
|
|
|
if (right === undefined) { right = true; }
|
|
|
|
if (top === undefined) { top = true; }
|
|
|
|
if (bottom === undefined) { bottom = true; }
|
|
|
|
|
|
|
|
this.updateWall(left, 'left', x - thickness, y, thickness, height);
|
|
|
|
this.updateWall(right, 'right', x + width, y, thickness, height);
|
|
|
|
this.updateWall(top, 'top', x, y - thickness, width, thickness);
|
|
|
|
this.updateWall(bottom, 'bottom', x, y + height, width, thickness);
|
|
|
|
|
|
|
|
return this;
|
|
|
|
},
|
2017-11-21 02:04:05 +00:00
|
|
|
|
2017-11-21 16:54:54 +00:00
|
|
|
// position = 'left', 'right', 'top' or 'bottom'
|
|
|
|
updateWall: function (add, position, x, y, width, height)
|
|
|
|
{
|
|
|
|
var wall = this.walls[position];
|
|
|
|
|
|
|
|
if (add)
|
|
|
|
{
|
|
|
|
if (wall)
|
|
|
|
{
|
2017-11-29 23:36:35 +00:00
|
|
|
MatterWorld.remove(this.localWorld, wall);
|
2017-11-21 16:54:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// adjust center
|
|
|
|
x += (width / 2);
|
|
|
|
y += (height / 2);
|
|
|
|
|
2017-11-27 03:45:46 +00:00
|
|
|
this.walls[position] = this.create(x, y, width, height, { isStatic: true, friction: 0, frictionStatic: 0 });
|
2017-11-21 16:54:54 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (wall)
|
|
|
|
{
|
2017-11-29 23:36:35 +00:00
|
|
|
MatterWorld.remove(this.localWorld, wall);
|
2017-11-21 16:54:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
this.walls[position] = null;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2017-11-27 03:45:46 +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;
|
|
|
|
},
|
|
|
|
|
|
|
|
disableGravity: function ()
|
|
|
|
{
|
|
|
|
this.localWorld.gravity.x = 0;
|
|
|
|
this.localWorld.gravity.y = 0;
|
|
|
|
this.localWorld.gravity.scale = 0;
|
|
|
|
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
|
2017-11-21 16:54:54 +00:00
|
|
|
setGravity: function (x, y, scale)
|
|
|
|
{
|
2017-11-27 16:29:33 +00:00
|
|
|
if (x === undefined) { x = 0; }
|
|
|
|
if (y === undefined) { y = 1; }
|
|
|
|
|
2017-11-21 16:54:54 +00:00
|
|
|
this.localWorld.gravity.x = x;
|
|
|
|
this.localWorld.gravity.y = y;
|
|
|
|
|
|
|
|
if (scale !== undefined)
|
|
|
|
{
|
|
|
|
this.localWorld.gravity.scale = scale;
|
|
|
|
}
|
|
|
|
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
|
|
|
|
create: function (x, y, width, height, options)
|
|
|
|
{
|
|
|
|
var body = Bodies.rectangle(x, y, width, height, options);
|
|
|
|
|
|
|
|
MatterWorld.add(this.localWorld, body);
|
|
|
|
|
|
|
|
return body;
|
|
|
|
},
|
|
|
|
|
2017-11-27 03:45:46 +00:00
|
|
|
// object can be single or an array, and can be a body, composite or constraint
|
|
|
|
add: function (object)
|
2017-11-21 16:54:54 +00:00
|
|
|
{
|
2017-11-27 03:45:46 +00:00
|
|
|
MatterWorld.add(this.localWorld, object);
|
|
|
|
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
|
|
|
|
remove: function (object, deep)
|
|
|
|
{
|
2017-12-02 04:05:27 +00:00
|
|
|
var body = (object.body) ? object.body : object;
|
|
|
|
|
|
|
|
Composite.removeBody(this.localWorld, body, deep);
|
2017-11-21 02:04:05 +00:00
|
|
|
|
2017-11-21 16:54:54 +00:00
|
|
|
return this;
|
2017-11-20 16:54:26 +00:00
|
|
|
},
|
|
|
|
|
2017-11-22 02:25:30 +00:00
|
|
|
nextGroup: function (isNonColliding)
|
|
|
|
{
|
2017-11-27 16:29:33 +00:00
|
|
|
return MatterBody.nextGroup(isNonColliding);
|
2017-11-22 02:25:30 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
nextCategory: function ()
|
|
|
|
{
|
|
|
|
return MatterBody.nextCategory();
|
|
|
|
},
|
|
|
|
|
2017-11-20 16:54:26 +00:00
|
|
|
update: function (time, delta)
|
|
|
|
{
|
2017-11-27 03:45:46 +00:00
|
|
|
if (this.isPaused)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-11-21 02:04:05 +00:00
|
|
|
var correction = 1;
|
|
|
|
|
2017-11-21 16:54:54 +00:00
|
|
|
Engine.update(this.engine, delta, correction);
|
2017-11-21 02:04:05 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
postUpdate: function ()
|
|
|
|
{
|
2018-01-17 15:22:16 +00:00
|
|
|
if (!this.drawDebug)
|
2017-11-27 03:45:46 +00:00
|
|
|
{
|
2018-01-17 15:22:16 +00:00
|
|
|
return;
|
|
|
|
}
|
2017-11-27 03:45:46 +00:00
|
|
|
|
2018-01-17 15:22:16 +00:00
|
|
|
var graphics = this.debugGraphic;
|
|
|
|
var bodies = Composite.allBodies(this.localWorld);
|
2017-11-27 17:01:27 +00:00
|
|
|
|
2018-01-17 15:22:16 +00:00
|
|
|
graphics.clear();
|
|
|
|
graphics.lineStyle(1, this.defaults.bodyDebugColor);
|
2017-11-27 03:45:46 +00:00
|
|
|
|
2018-01-17 15:22:16 +00:00
|
|
|
for (var i = 0; i < bodies.length; i++)
|
|
|
|
{
|
|
|
|
var body = bodies[i];
|
2017-11-27 03:45:46 +00:00
|
|
|
|
2018-01-17 15:22:16 +00:00
|
|
|
if (!body.render.visible)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
2017-11-27 03:45:46 +00:00
|
|
|
|
2018-01-17 15:22:16 +00:00
|
|
|
var vertices = body.vertices;
|
2017-11-27 03:45:46 +00:00
|
|
|
|
2018-01-17 15:22:16 +00:00
|
|
|
graphics.moveTo(vertices[0].x, vertices[0].y);
|
2017-11-27 03:45:46 +00:00
|
|
|
|
2018-01-17 15:22:16 +00:00
|
|
|
for (var j = 1; j < vertices.length; j++)
|
|
|
|
{
|
|
|
|
graphics.lineTo(vertices[j].x, vertices[j].y);
|
2017-11-27 03:45:46 +00:00
|
|
|
}
|
2018-01-17 15:22:16 +00:00
|
|
|
|
|
|
|
graphics.lineTo(vertices[0].x, vertices[0].y);
|
|
|
|
|
|
|
|
graphics.strokePath();
|
2017-11-27 03:45:46 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
fromPath: function (path, points)
|
|
|
|
{
|
|
|
|
if (points === undefined) { points = []; }
|
|
|
|
|
|
|
|
var pathPattern = /L?\s*([\-\d\.e]+)[\s,]*([\-\d\.e]+)*/ig;
|
|
|
|
|
|
|
|
path.replace(pathPattern, function(match, x, y)
|
|
|
|
{
|
|
|
|
points.push({ x: parseFloat(x), y: parseFloat(y) });
|
|
|
|
});
|
|
|
|
|
|
|
|
return points;
|
2017-11-20 16:54:26 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
shutdown: function ()
|
|
|
|
{
|
2017-11-29 23:36:35 +00:00
|
|
|
MatterWorld.clear(this.localWorld, false);
|
|
|
|
Engine.clear(this.engine);
|
2017-11-20 16:54:26 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
destroy: function ()
|
|
|
|
{
|
2017-11-29 23:36:35 +00:00
|
|
|
this.shutdown();
|
2017-11-20 16:54:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
module.exports = World;
|