Merge pull request #1 from photonstorm/master

keeping up with phaser
This commit is contained in:
svipal 2019-12-18 23:11:02 +01:00 committed by GitHub
commit c1c4aedd2f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
57 changed files with 2853 additions and 710 deletions

View file

@ -1,6 +1,6 @@
# Change Log
## Version 3.21.1 - Senku - in development
## Version 3.22 - Senku - in development
### Matter Physics Updates
@ -12,25 +12,28 @@
* `showInternalEdges` - When rendering bodies, render the internal edges as well?
* `showConvexHulls` - When rendering polygon bodies, render the convex hull as well?
* `renderFill` - Render the bodies using a fill color.
* `renderStroke` - Render the bodies using a line stroke.
* `lineThickness` - If rendering with a stroke, the thickness of the line.
* `renderLine`- Render the bodies using a line stroke.
* `fillColor` - The color value of the fill when rendering dynamic bodies.
* `strokeColor` - The color value of the line stroke when rendering dynamic bodies.
* `fillOpacity` - The opacity of the fill when rendering dynamic bodies, a value between 0 and 1.
* `lineColor` - The color value of the line stroke when rendering dynamic bodies.
* `lineOpacity` - The opacity of the line when rendering dynamic bodies, a value between 0 and 1.
* `lineThickness` - If rendering lines, the thickness of the line.
* `staticFillColor` - The color value of the fill when rendering static bodies.
* `staticStrokeColor` - The color value of the line stroke when rendering static bodies.
* `staticBodySleepOpacity`7] - The amount to multiply the opacity of sleeping static bodies by.
* `staticLineColor` - The color value of the line stroke when rendering static bodies.
* `staticBodySleepOpacity` - The amount to multiply the opacity of sleeping static bodies by.
* `sleepFillColor` - The color value of the fill when rendering sleeping dynamic bodies.
* `sleepStrokeColor` - The color value of the line stroke when rendering sleeping dynamic bodies.
* `hullColor` - The color value of hulls when `showConvexHulls` is set.
* `sleepLineColor` - The color value of the line stroke when rendering sleeping dynamic bodies.
* `jointColor` - The color value of joints when `showJoint` is set.
* `jointLineOpacity` - The line opacity when rendering joints, a value between 0 and 1.
* `jointLineThickness` - The line thickness when rendering joints.
* `pinSize` - The size of the circles drawn when rendering pin constraints.
* `pinColor` - The color value of the circles drawn when rendering pin constraints.
* `springColor` - The color value of spring constraints.
* `anchorColor` - The color value of constraint anchors.
* `anchorSize` - The size of the circles drawn as the constraint anchors.
* The `debug` property in the Matter World Config is now a `MatterDebugConfig` option instead of a boolean.
* The following `MatterWorldConfig` options are now deprecated: `debugShowBody`, `debugShowStaticBody`, `debugBodyColor`, `debugBodyFillColor`, `debugStaticBodyColor`, `debugShowJoint`, `debugJointColor`, `debugWireframes`, `debugShowInternalEdges`, `debugShowConvexHulls`, `debugConvexHullColor` and `debugShowSleeping`. These can all be set via the new `MatterDebugConfig` object instead. They will be removed fully in a future version.
* `hullColor` - The color value of hulls when `showConvexHulls` is set.
* The `debug` property in the Matter World Config is now a `MatterDebugConfig` option instead of a boolean. However, if a boolean is given, it will use the default debug config values.
* The following `MatterWorldConfig` options have now been removed: `debugShowBody`, `debugShowStaticBody`, `debugBodyColor`, `debugBodyFillColor`, `debugStaticBodyColor`, `debugShowJoint`, `debugJointColor`, `debugWireframes`, `debugShowInternalEdges`, `debugShowConvexHulls`, `debugConvexHullColor` and `debugShowSleeping`. These can all be set via the new `MatterDebugConfig` object instead.
* The object `World.defaults` has been removed. Defaults are now access via `World.debugDefaults`.
* `World.renderBody` is a new method that will render a single Matter Body to the given Graphics object. This is used internally during debug rendering but is also public. This allows you to control which bodies are rendered and to which Graphics object, should you wish to use them in-game and not just during debugging.
* `World.renderConstraint` is a new method that will render a single Matter Constraint, such as a pin or a spring, to the given Graphics object. This is used internally during debug rendering but is also public. This allows you to control which constraints are rendered and to which Graphics object, should you wish to use them in-game and not just during debugging.
@ -38,21 +41,109 @@
* `World.renderBodies` has been rewritten to cache commonly-used values and avoid a situation when a single body would be rendered twice.
* The private method `World.renderConvexHulls` has been removed as it's no longer used internally.
* The private method `World.renderWireframes` has been removed as it's no longer used internally.
* The `Matter.Factory.worldConstraint` argument signature has changed. It now takes `x` and `y` arguments first, as the world position where the constraint will be created.
* Due to the rewrite of the debug rendering, it is now possible to render _just_ constraints, where-as before this was only possible if bodies were being rendered as well. Fix #4880 (thanks @roberto257)
* The method `World.fromPath` has been removed. This was never used internally and you can get the same results by calling `Vertices.fromPath`.
* The `World.setBounds` argument `thickness` now defaults to 64, not 128, to keep it matching the Matter World Config.
* `World.getAllBodies` is a new method that will return all bodies in the Matter World.
* `World.getAllConstraints` is a new method that will return all constraints in the Matter World.
* `World.getAllComposites` is a new method that will return all composites in the Matter World.
* `MatterPhysics.composite` is a new reference to the `Matter.Composite` module for easy access from within a Scene.
* `MatterPhysics.detector` is a new reference to the `Matter.Dectector` module for easy access from within a Scene.
* `MatterPhysics.grid` is a new reference to the `Matter.Grid` module for easy access from within a Scene.
* `MatterPhysics.pair` is a new reference to the `Matter.Pair` module for easy access from within a Scene.
* `MatterPhysics.pairs` is a new reference to the `Matter.Pairs` module for easy access from within a Scene.
* `MatterPhysics.query` is a new reference to the `Matter.Query` module for easy access from within a Scene.
* `MatterPhysics.resolver` is a new reference to the `Matter.Resolver` module for easy access from within a Scene.
* `MatterPhysics.sat` is a new reference to the `Matter.SAT` module for easy access from within a Scene.
* `MatterPhysics.constraint` is a new reference to the `Matter.Constraint` module for easy access from within a Scene.
* `MatterPhysics.composites` is a new reference to the `Matter.Composites` module for easy access from within a Scene.
* `MatterPhysics.axes` is a new reference to the `Matter.Axes` module for easy access from within a Scene.
* `MatterPhysics.bounds` is a new reference to the `Matter.Bounds` module for easy access from within a Scene.
* `MatterPhysics.svg` is a new reference to the `Matter.Svg` module for easy access from within a Scene.
* `MatterPhysics.vector` is a new reference to the `Matter.Vector` module for easy access from within a Scene.
* `MatterPhysics.vertices` is a new reference to the `Matter.Vertices` module for easy access from within a Scene.
* `BEFORE_ADD` is a new Event dispatched by `Matter.World` when a Body or Constraint is about to be added to the World.
* `AFTER_ADD` is a new Event dispatched by `Matter.World` when a Body or Constraint has been added to the World.
* `BEFORE_REMOVE` is a new Event dispatched by `Matter.World` when a Body or Constraint is about to be removed from the World.
* `AFTER_REMOVE` is a new Event dispatched by `Matter.World` when a Body or Constraint has been removed from the World.
* The `Body.render.fillStyle` property that existed on the Matter Body object has been removed and replaced with `fillColor`.
* The `Body.render.strokeStyle` property that existed on the Matter Body object has been removed and replaced with `lineColor`.
* `Body.render.lineOpacity` is a new property on the Matter Body object that allows for custom debug rendering.
* `Body.render.lineThickness` is a new property on the Matter Body object that allows for custom debug rendering.
* `Body.render.fillOpacity` is a new property on the Matter Body object that allows for custom debug rendering.
* `World.setCompositeRenderStyle` is a new method that lets you quickly set the render style values on the children of the given compposite.
* `World.setBodyRenderStyle` is a new method that lets you quickly set the render style values on the given Body.
* `World.setConstraintRenderStyle` is a new method that lets you quickly set the render style values on the given Constraint.
* You can now set `restingThresh` in the Matter Configuration file to adjust the Resolver property.
* You can now set `restingThreshTangent` in the Matter Configuration file to adjust the Resolver property.
* You can now set `positionDampen` in the Matter Configuration file to adjust the Resolver property.
* You can now set `positionWarming` in the Matter Configuration file to adjust the Resolver property.
* You can now set `frictionNormalMultiplier` in the Matter Configuration file to adjust the Resolver property.
* `MatterPhysics.containsPoint` is a new method that returns a boolean if any of the given bodies intersect with the given point.
* `MatterPhysics.intersectPoint` is a new method that checks which bodies intersect with the given point and returns them.
* `MatterPhysics.intersectRect` is a new method that checks which bodies intersect with the given rectangular area, and returns them. Optionally, it can check which bodies are outside of the area.
* `MatterPhysics.intersectRay` is a new method that checks which bodies intersect with the given ray segment and returns them. Optionally, you can set the width of the ray.
* `MatterPhysics.intersectBody` is a new method that checks which bodies intersect with the given body and returns them. If the bodies are set to not collide this can be used as an overlaps check.
* `MatterPhysics.overlap` is a new method that takes a target body and checks to see if it overlaps with any of the bodies given. If they do, optional `process` and `overlap` callbacks are invoked, passing the overlapping bodies to them, along with additional collision data.
* `MatterPhysics.setCollisionCategory` is a new method that will set the collision filter category to the value given, on all of the bodies given. This allows you to easily set the category on bodies that don't have a Phaser Matter Collision component.
* `MatterPhysics.setCollisionGroup` is a new method that will set the collision filter group to the value given, on all of the bodies given. This allows you to easily set the group on bodies that don't have a Phaser Matter Collision component.
* `MatterPhysics.setCollidesWith` is a new method that will set the collision filter mask to the value given, on all of the bodies given. This allows you to easily set the filter mask on bodies that don't have a Phaser Matter Collision component.
* `Matter.Body.centerOfMass` is a new property added to the Matter Body object that retains the center of mass coordinates when the Body is first created.
* `Matter.Body.render.sprite.xOffset` and `yOffset` are no longer set to anything when a Body is created. They are left as zero, or you can override them in the Body config, in which case the value is added to the sprite origin offset.
* `Matter.Transform.centerOffsetX` is a new read-only property available on all Matter Game Objects that returns the horizontal offset between the center of the frame and the center of mass. This can be used to allow for accurately mapping texture centers to the body center.
* `Matter.Transform.centerOffsetY` is a new read-only property available on all Matter Game Objects that returns the vertical offset between the center of the frame and the center of mass. This can be used to allow for accurately mapping texture centers to the body center.
* The `Matter.Mass.centerOfMass` component property now returns the pre-calculated Body `centerOfMass` property, which is much more accurate than the previous bounds offset value.
* `Matter.setExistingBody`, which is called interally whenever a Body is set on a Game Object, now uses the new `centerOffset` values to ensure that the texture frame is correctly centered based on the center of mass, not the Body bounds, allowing for much more accurate body to texture mapping with complex multi-part compound bodies.
* The `Matter.PhysicsEditorParser` has been updated so it no longer needs to set the render offsets, and instead uses the center of mass values.
* If the `Matter.Body` config doesn't contain a `position` property, it will now default to using `Vertices.centre(body.vertices)` as the position. In most cases, this is what you need, so it saves having to pass it in the config object.
* `Constraint.pointAWorld` is a new method added to Matter that returns the world-space position of `constraint.pointA`, accounting for `constraint.bodyA`.
* `Constraint.pointBWorld` is a new method added to Matter that returns the world-space position of `constraint.pointB`, accounting for `constraint.bodyB`.
* `Body.setCentre` is a new method added to Matter that allows you to set the center of mass of a Body (please note the English spelling of this function.)
* Bumped Matter Plugin versions to avoid console logs from Common.info and Common.warn.
* `Body.scale` is a new vector that holds the most recent scale values as passed to `Body.scale`.
* `Matter.Bodies.flagCoincidentParts` is a new function that will flags all internal edges (coincident parts) on an array of body parts. This was previously part of the `fromVertices` function, but has been made external for outside use.
* `PhysicsEditorParser.parseVertices` now uses `Bodies.flagCoincidentParts` to avoid duplicating code.
* `MatterGameObject` has a new optional boolean parameter `addToWorld` which lets you control if the Body should be added to the world or not. Useful for toggling off should you be merging pre-existing bodies with Game Objects.
* The `Matter.SetBody.setExistingBody` function, which all Matter Game Objects have, has a new parameter `addToWorld` which allows you to control when the body is added to the Matter world should you not require it immediately. It will also only add the body to the world if it doesn't already exist within it, or any of its composites.
* `PointerConstraint` has been recoded so that when pressed down, it only polls the World for a body hit test during the next game update. This stops it coming out of sync with the state of the world. Useage of the constraint remains the same as before.
* `Matter.getMatterBodies` is a new function that will return an array of Matter JS Bodies from the given input array, which can be Matter Game Objects, or any class that extends them.
* `Matter.World.has` is a new method that will take a Matter Body, or Game Object, and search the world for it. If found, it will return `true`.
* Matter now has the option to use the Runner that it ships with. The Matter Runner operates in two modes: fixed and variable. In the fixed mode, the Matter Engine updates at a fixed delta value every frame (which is what Phaser has used since the first version). In variable mode, the delta will be smoothed and capped each frame to keep the simulation constant, but at the cost of determininism. You can configure the runner by setting the `runner` property in the Matter Config object, both of which are fully covered with JSDocs. As of 3.22 the runner is now used by default in variable (non-fixed) mode. If you wish to return to the previous behavior, set `runner: { isFixed: true }`.
* `Body.onCollideCallback` is a new Matter Body property that can point to a callback to invoke when the body starts colliding.
* `Body.onCollideEndCallback` is a new Matter Body property that can point to a callback to invoke when the body stops colliding.
* `Body.onCollideActiveCallback` is a new Matter Body property that can point to a callback to invoke for the duration the body is colliding.
* `Body.onCollideWith` is a new Matter Body property that holds a mapping between bodies and collision callbacks.
* `MatterGameObject.setOnCollide` is a new method available on any Matter Game Object, that sets a callback that is invoked when the body collides with another.
* `MatterGameObject.setOnCollideEnd` is a new method available on any Matter Game Object, that sets a callback that is invoked when the body stops colliding.
* `MatterGameObject.setOnCollideActive` is a new method available on any Matter Game Object, that sets a callback which is invoked for the duration of the bodies collision with another.
* `MatterGameObject.setOnCollideWith` is a new method available on any Matter Game Object, that allows you to set a callback to be invoked whenever the body collides with another specific body, or array of bodies.
### New Features
* `TimeStep.smoothStep` is a new boolean property that controls if any delta smoothing takes place during the game step. Delta smoothing has been enabled in Phaser since the first version and helps avoid delta spikes and dips, especially after loss of focus. However, you can now easily toggle if this happens via this property and the corresponding `FPSConfig` property.
### Updates
* `Body.deltaXFinal` is a new method on Arcade Physics Bodies that will return the final change in the horizontal position of the body, as based on all the steps that took place this frame. This property is calculated during the `postUpdate` phase, so must be listened for accordingly (thanks Bambosh)
* `Body.deltaYFinal` is a new method on Arcade Physics Bodies that will return the final change in the vertical position of the body, as based on all the steps that took place this frame. This property is calculated during the `postUpdate` phase, so must be listened for accordingly (thanks Bambosh)
* `Body._tx` is a new internal private var, holding the Arcade Physics Body combined total delta x value.
* `Body._ty` is a new internal private var, holding the Arcade Physics Body combined total delta y value.
* `LineCurve.getUtoTmapping` has been updated to return `u` directly to avoid calculations as it's identical to `t` in a Line (thanks @rexrainbow)
* `Curve.getSpacedPoints` will now take an optional array as the 3rd parameter to store the points results in (thanks @rexrainbow)
### Bug Fixes
* BitmapText with a `maxWidth` set wouldn't update the text correctly if it was modified post-creation. You can now update the text and/or width independantly and it'll update correctly. Fix #4881 (thanks @oxguy3)
* Text objects will no longer add any white-space when word-wrapping if the last line is only one word long. Fix #4867 (thanks @gaamoo @rexrainbow)
* When `Game.destroy` is running, Scenes are now destroyed _before_ plugins, avoiding bugs when closing down plugins and deleting Render Textures. Fix #4849 #4876 (thanks @rexrainbow @siyuanqiao)
* The `Mesh` and `Quad` Game Objects have had the `GetBounds` component removed as it cannot operate on a Mesh as they don't have origins. Fix #4902 (thanks @samme)
* Setting `lineSpacing` in the Text Game Object style config would set the value but not apply it to the Text, leaving you to call `updateText` yourself. If set, it's now applied on instantiation. Fix #4901 (thanks @FantaZZ)
### Examples, Documentation and TypeScript
My thanks to the following for helping with the Phaser 3 Examples, Docs and TypeScript definitions, either by reporting errors, fixing them or helping author the docs:
@fselcukcan
@fselcukcan Bambosh @louisth @hexus @javigaralva @samme @BeLi4L
## Version 3.21.0 - Senku - 22nd November 2019

View file

@ -77,7 +77,7 @@ Extra special thanks to the following companies who's support makes Phaser possi
* [Y8 Games](https://www.y8.com)
* [Poki](https://developers.poki.com/)
![Sponsors](https://phaser.io/images/github/sponsors-2019-08.png "Awesome Sponsors")
![Sponsors](https://phaser.io/images/github/sponsors-2019-12.png "Awesome Sponsors")
![Phaser Newsletter](https://phaser.io/images/github/div-newsletter.png "Phaser Newsletter")

View file

@ -671,12 +671,12 @@ var Game = new Class({
*/
runDestroy: function ()
{
this.scene.destroy();
this.events.emit(Events.DESTROY);
this.events.removeAllListeners();
this.scene.destroy();
if (this.renderer)
{
this.renderer.destroy();

View file

@ -15,14 +15,26 @@ var RequestAnimationFrame = require('../dom/RequestAnimationFrame');
// target: 60,
// forceSetTimeOut: false,
// deltaHistory: 10,
// panicMax: 120
// panicMax: 120,
// smoothStep: true
// }
// http://www.testufo.com/#test=animation-time-graph
/**
* @classdesc
* [description]
* The core runner class that Phaser uses to handle the game loop. It can use either Request Animation Frame,
* or SetTimeout, based on browser support and config settings, to create a continuous loop within the browser.
*
* Each time the loop fires, `TimeStep.step` is called and this is then passed onto the core Game update loop,
* it is the core heartbeat of your game. It will fire as often as Request Animation Frame is capable of handling
* on the target device.
*
* Note that there are lots of situations where a browser will stop updating your game. Such as if the player
* switches tabs, or covers up the browser window with another application. In these cases, the 'heartbeat'
* of your game will pause, and only resume when focus is returned to it by the player. There is no way to avoid
* this situation, all you can do is use the visibility events the browser, and Phaser, provide to detect when
* it has happened and then gracefully recover.
*
* @class TimeStep
* @memberof Phaser.Core
@ -49,7 +61,7 @@ var TimeStep = new Class({
this.game = game;
/**
* [description]
* The Request Animation Frame DOM Event handler.
*
* @name Phaser.Core.TimeStep#raf
* @type {Phaser.DOM.RequestAnimationFrame}
@ -141,7 +153,8 @@ var TimeStep = new Class({
this.actualFps = this.targetFps;
/**
* [description]
* The time at which the next fps rate update will take place.
* When an fps update happens, the `framesThisSecond` value is reset.
*
* @name Phaser.Core.TimeStep#nextFpsUpdate
* @type {integer}
@ -338,6 +351,22 @@ var TimeStep = new Class({
* @since 3.18.0
*/
this.now = 0;
/**
* Apply smoothing to the delta value used within Phasers internal calculations?
*
* This can be changed in the Game Config via the `fps.smoothStep` property. The default is `true`.
*
* Smoothing helps settle down the delta values after browser tab switches, or other situations
* which could cause significant delta spikes or dips. By default it has been enabled in Phaser 3
* since the first version, but is now exposed under this property (and the corresponding game config
* `smoothStep` value), to allow you to easily disable it, should you require.
*
* @name Phaser.Core.TimeStep#smoothStep
* @type {boolean}
* @since 3.22.0
*/
this.smoothStep = GetValue(config, 'smoothStep', true);
},
/**
@ -461,7 +490,7 @@ var TimeStep = new Class({
step: function ()
{
// Because the timestamp passed in from raf represents the beginning of the main thread frame that were currently in,
// not the actual time now. As we want to compare this time value against Event timeStamps and the like, we need a
// not the actual time now, and as we want to compare this time value against Event timeStamps and the like, we need a
// more accurate one:
var time = window.performance.now();
@ -485,55 +514,59 @@ var TimeStep = new Class({
// delta time (time is in ms)
var dt = before;
// Delta Average
var avg = before;
// When a browser switches tab, then comes back again, it takes around 10 frames before
// the delta time settles down so we employ a 'cooling down' period before we start
// trusting the delta values again, to avoid spikes flooding through our delta average
if (this._coolDown > 0 || !this.inFocus)
if (this.smoothStep)
{
this._coolDown--;
dt = Math.min(dt, this._target);
if (this._coolDown > 0 || !this.inFocus)
{
this._coolDown--;
dt = Math.min(dt, this._target);
}
if (dt > this._min)
{
// Probably super bad start time or browser tab context loss,
// so use the last 'sane' dt value
dt = history[idx];
// Clamp delta to min (in case history has become corrupted somehow)
dt = Math.min(dt, this._min);
}
// Smooth out the delta over the previous X frames
// add the delta to the smoothing array
history[idx] = dt;
// adjusts the delta history array index based on the smoothing count
// this stops the array growing beyond the size of deltaSmoothingMax
this.deltaIndex++;
if (this.deltaIndex > max)
{
this.deltaIndex = 0;
}
// Loop the history array, adding the delta values together
avg = 0;
for (var i = 0; i < max; i++)
{
avg += history[i];
}
// Then divide by the array length to get the average delta
avg /= max;
}
if (dt > this._min)
{
// Probably super bad start time or browser tab context loss,
// so use the last 'sane' dt value
dt = history[idx];
// Clamp delta to min (in case history has become corrupted somehow)
dt = Math.min(dt, this._min);
}
// Smooth out the delta over the previous X frames
// add the delta to the smoothing array
history[idx] = dt;
// adjusts the delta history array index based on the smoothing count
// this stops the array growing beyond the size of deltaSmoothingMax
this.deltaIndex++;
if (this.deltaIndex > max)
{
this.deltaIndex = 0;
}
// Delta Average
var avg = 0;
// Loop the history array, adding the delta values together
for (var i = 0; i < max; i++)
{
avg += history[i];
}
// Then divide by the array length to get the average delta
avg /= max;
// Set as the world delta value
this.delta = avg;
@ -667,7 +700,7 @@ var TimeStep = new Class({
* @method Phaser.Core.TimeStep#stop
* @since 3.0.0
*
* @return {Phaser.Core.TimeStep} The TimeStep object.
* @return {this} The TimeStep object.
*/
stop: function ()
{

View file

@ -7,4 +7,5 @@
* @property {boolean} [forceSetTimeOut=false] - Use setTimeout instead of requestAnimationFrame to run the game loop.
* @property {integer} [deltaHistory=10] - Calculate the average frame delta from this many consecutive frame intervals.
* @property {integer} [panicMax=120] - The amount of frames the time step counts before we trust the delta values again.
* @property {boolean} [smoothStep=true] - Apply delta smoothing during the game update to help avoid spikes?
*/

View file

@ -353,24 +353,37 @@ var Curve = new Class({
* @method Phaser.Curves.Curve#getSpacedPoints
* @since 3.0.0
*
* @param {integer} [divisions] - [description]
* @param {integer} [divisions] - The number of evenly spaced points from the curve to return. If falsy, step param will be used to calculate the number of points.
* @param {number} [step] - Step between points. Used to calculate the number of points to return when divisions is falsy. Ignored if divisions is positive.
* @param {(array|Phaser.Math.Vector2[])} [out] - An optional array to store the points in.
*
* @return {Phaser.Math.Vector2[]} [description]
*/
getSpacedPoints: function (divisions)
getSpacedPoints: function (divisions, stepRate, out)
{
if (divisions === undefined) { divisions = this.defaultDivisions; }
if (out === undefined) { out = []; }
var points = [];
// If divisions is a falsey value (false, null, 0, undefined, etc) then we calculate it based on the stepRate instead.
if (!divisions)
{
if (!stepRate)
{
divisions = this.defaultDivisions;
}
else
{
divisions = this.getLength() / stepRate;
}
}
for (var d = 0; d <= divisions; d++)
{
var t = this.getUtoTmapping(d / divisions, null, divisions);
points.push(this.getPoint(t));
out.push(this.getPoint(t));
}
return points;
return out;
},
/**

View file

@ -194,6 +194,41 @@ var LineCurve = new Class({
return tangent.normalize();
},
// Override default Curve.getUtoTmapping
/**
* [description]
*
* @method Phaser.Curves.Line#getUtoTmapping
* @since 3.0.0
*
* @param {number} u - [description]
* @param {integer} distance - [description]
* @param {integer} [divisions] - [description]
*
* @return {number} [description]
*/
getUtoTmapping: function (u, distance, divisions)
{
var t;
if (distance)
{
var arcLengths = this.getLengths(divisions);
var lineLength = arcLengths[arcLengths.length - 1];
// Cannot overshoot the curve
var targetLineLength = Math.min(distance, lineLength);
t = targetLineLength / lineLength;
}
else
{
t = u;
}
return t;
},
// Override default Curve.draw because this is better than calling getPoints on a line!
/**

View file

@ -63,7 +63,7 @@ var GameObjectCreator = new Class({
/**
* A reference to the Scene Update List.
*
* @name Phaser.GameObjects.GameObjectCreator#updateList;
* @name Phaser.GameObjects.GameObjectCreator#updateList
* @type {Phaser.GameObjects.UpdateList}
* @protected
* @since 3.0.0

View file

@ -62,7 +62,7 @@ var GameObjectFactory = new Class({
/**
* A reference to the Scene Update List.
*
* @name Phaser.GameObjects.GameObjectFactory#updateList;
* @name Phaser.GameObjects.GameObjectFactory#updateList
* @type {Phaser.GameObjects.UpdateList}
* @protected
* @since 3.0.0
@ -105,7 +105,7 @@ var GameObjectFactory = new Class({
/**
* Adds an existing Game Object to this Scene.
*
*
* If the Game Object renders, it will be added to the Display List.
* If it has a `preUpdate` method, it will be added to the Update List.
*
@ -167,8 +167,19 @@ var GameObjectFactory = new Class({
});
// Static method called directly by the Game Object factory functions
/**
* Static method called directly by the Game Object factory functions.
* With this method you can register a custom GameObject factory in the GameObjectFactory,
* providing a name (`factoryType`) and the constructor (`factoryFunction`) in order
* to be called when you call to Phaser.Scene.add[ factoryType ] method.
*
* @method Phaser.GameObjects.GameObjectFactory.register
* @static
* @since 3.0.0
*
* @param {string} factoryType - The key of the factory that you will use to call to Phaser.Scene.add[ factoryType ] method.
* @param {function} factoryFunction - The constructor function to be called when you invoke to the Phaser.Scene.add method.
*/
GameObjectFactory.register = function (factoryType, factoryFunction)
{
if (!GameObjectFactory.prototype.hasOwnProperty(factoryType))
@ -177,6 +188,17 @@ GameObjectFactory.register = function (factoryType, factoryFunction)
}
};
/**
* Static method called directly by the Game Object factory functions.
* With this method you can remove a custom GameObject factory registered in the GameObjectFactory,
* providing a its `factoryType`.
*
* @method Phaser.GameObjects.GameObjectFactory.remove
* @static
* @since 3.0.0
*
* @param {string} factoryType - The key of the factory that you want to remove from the GameObjectFactory.
*/
GameObjectFactory.remove = function (factoryType)
{
if (GameObjectFactory.prototype.hasOwnProperty(factoryType))

View file

@ -20,8 +20,8 @@ var ParseXMLBitmapFont = require('./ParseXMLBitmapFont');
* @param {string} textureKey - The key of the BitmapFont's texture.
* @param {string} frameKey - The key of the BitmapFont texture's frame.
* @param {string} xmlKey - The key of the XML data of the font to parse.
* @param {integer} xSpacing - The x-axis spacing to add between each letter.
* @param {integer} ySpacing - The y-axis spacing to add to the line height.
* @param {integer} [xSpacing] - The x-axis spacing to add between each letter.
* @param {integer} [ySpacing] - The y-axis spacing to add to the line height.
*
* @return {boolean} Whether the parsing was successful or not.
*/

View file

@ -15,7 +15,7 @@ var Render = require('./BitmapTextRender');
/**
* @classdesc
* BitmapText objects work by taking a texture file and an XML or JSON file that describes the font structure.
*
*
* During rendering for each letter of the text is rendered to the display, proportionally spaced out and aligned to
* match the font structure.
*
@ -185,7 +185,7 @@ var BitmapText = new Class({
/**
* Internal cache var holding the maxWidth.
*
*
* @name Phaser.GameObjects.BitmapText#_maxWidth
* @type {number}
* @private
@ -431,7 +431,7 @@ var BitmapText = new Class({
* If no whitespace was found then no wrapping will take place and consequently the `maxWidth` value will not be honored.
*
* Disable maxWidth by setting the value to 0.
*
*
* You can set the whitespace character to be searched for by setting the `wordWrapCharCode` parameter or property.
*
* @method Phaser.GameObjects.BitmapText#setMaxWidth
@ -690,8 +690,7 @@ BitmapText.ALIGN_RIGHT = 2;
*
* Adds the parsed Bitmap Font data to the cache with the `fontName` key.
*
* @name Phaser.GameObjects.BitmapText.ParseFromAtlas
* @type {function}
* @method Phaser.GameObjects.BitmapText.ParseFromAtlas
* @since 3.0.0
*
* @param {Phaser.Scene} scene - The Scene to parse the Bitmap Font for.
@ -709,8 +708,7 @@ BitmapText.ParseFromAtlas = ParseFromAtlas;
/**
* Parse an XML font to Bitmap Font data for the Bitmap Font cache.
*
* @name Phaser.GameObjects.BitmapText.ParseXMLBitmapFont
* @type {function}
* @method Phaser.GameObjects.BitmapText.ParseXMLBitmapFont
* @since 3.17.0
*
* @param {XMLDocument} xml - The XML Document to parse the font from.

View file

@ -23,7 +23,7 @@ var Transform = {
/**
* Private internal value. Holds the horizontal scale value.
*
*
* @name Phaser.GameObjects.Components.Transform#_scaleX
* @type {number}
* @private
@ -34,7 +34,7 @@ var Transform = {
/**
* Private internal value. Holds the vertical scale value.
*
*
* @name Phaser.GameObjects.Components.Transform#_scaleY
* @type {number}
* @private
@ -45,7 +45,7 @@ var Transform = {
/**
* Private internal value. Holds the rotation value in radians.
*
*
* @name Phaser.GameObjects.Components.Transform#_rotation
* @type {number}
* @private
@ -76,7 +76,9 @@ var Transform = {
/**
* The z position of this Game Object.
* Note: Do not use this value to set the z-index, instead see the `depth` property.
*
* Note: The z position does not control the rendering order of 2D Game Objects. Use
* {@link Phaser.GameObjects.Components.Depth#depth} instead.
*
* @name Phaser.GameObjects.Components.Transform#z
* @type {number}
@ -98,7 +100,7 @@ var Transform = {
/**
* This is a special setter that allows you to set both the horizontal and vertical scale of this Game Object
* to the same value, at the same time. When reading this value the result returned is `(scaleX + scaleY) / 2`.
*
*
* Use of this property implies you wish the horizontal and vertical scales to be equal to each other. If this
* isn't the case, use the `scaleX` or `scaleY` properties instead.
*
@ -195,7 +197,7 @@ var Transform = {
/**
* The angle of this Game Object as expressed in degrees.
*
*
* Phaser uses a right-hand clockwise rotation system, where 0 is right, 90 is down, 180/-180 is left
* and -90 is up.
*
@ -222,7 +224,7 @@ var Transform = {
/**
* The angle of this Game Object in radians.
*
*
* Phaser uses a right-hand clockwise rotation system, where 0 is right, 90 is down, 180/-180 is left
* and -90 is up.
*
@ -278,7 +280,7 @@ var Transform = {
/**
* Sets the position of this Game Object to be a random position within the confines of
* the given area.
*
*
* If no area is specified a random position between 0 x 0 and the game width x height is used instead.
*
* The position does not factor in the size of this Game Object, meaning that only the origin is
@ -408,6 +410,9 @@ var Transform = {
/**
* Sets the z position of this Game Object.
*
* Note: The z position does not control the rendering order of 2D Game Objects. Use
* {@link Phaser.GameObjects.Components.Depth#setDepth} instead.
*
* @method Phaser.GameObjects.Components.Transform#setZ
* @since 3.0.0
*
@ -499,7 +504,7 @@ var Transform = {
/**
* Gets the sum total rotation of all of this Game Objects parent Containers.
*
*
* The returned value is in radians and will be zero if this Game Object has no parent container.
*
* @method Phaser.GameObjects.Components.Transform#getParentRotation

View file

@ -23,7 +23,6 @@ var NOOP = require('../../utils/NOOP');
*
* @extends Phaser.GameObjects.Components.BlendMode
* @extends Phaser.GameObjects.Components.Depth
* @extends Phaser.GameObjects.Components.GetBounds
* @extends Phaser.GameObjects.Components.Mask
* @extends Phaser.GameObjects.Components.Pipeline
* @extends Phaser.GameObjects.Components.Size
@ -49,7 +48,6 @@ var Mesh = new Class({
Mixins: [
Components.BlendMode,
Components.Depth,
Components.GetBounds,
Components.Mask,
Components.Pipeline,
Components.Size,

View file

@ -285,7 +285,7 @@ var Text = new Class({
if (style && style.lineSpacing)
{
this.lineSpacing = style.lineSpacing;
this.setLineSpacing(style.lineSpacing);
}
scene.sys.game.events.on(GameEvents.CONTEXT_RESTORED, function ()
@ -508,16 +508,20 @@ var Text = new Class({
{
var result = '';
var lines = text.split(this.splitRegExp);
var lastLineIndex = lines.length - 1;
var whiteSpaceWidth = context.measureText(' ').width;
for (var i = 0; i < lines.length; i++)
for (var i = 0; i <= lastLineIndex; i++)
{
var spaceLeft = wordWrapWidth;
var words = lines[i].split(' ');
var lastWordIndex = words.length - 1;
for (var j = 0; j < words.length; j++)
for (var j = 0; j <= lastWordIndex; j++)
{
var wordWidth = context.measureText(words[j]).width;
var wordWidthWithSpace = wordWidth + context.measureText(' ').width;
var word = words[j];
var wordWidth = context.measureText(word).width;
var wordWidthWithSpace = wordWidth + whiteSpaceWidth;
if (wordWidthWithSpace > spaceLeft)
{
@ -526,24 +530,24 @@ var Text = new Class({
if (j > 0)
{
result += '\n';
spaceLeft = wordWrapWidth;
}
}
result += words[j] + ' ';
spaceLeft = wordWrapWidth - wordWidthWithSpace;
result += word;
if (j < lastWordIndex)
{
result += ' ';
spaceLeft -= wordWidthWithSpace;
}
else
{
spaceLeft -= wordWidthWithSpace;
result += words[j];
if (j < (words.length - 1))
{
result += ' ';
}
spaceLeft -= wordWidth;
}
}
if (i < lines.length - 1)
if (i < lastLineIndex)
{
result += '\n';
}

View file

@ -22,11 +22,10 @@ var InputPluginCache = {};
* Plugin is the object to instantiate to create the plugin
* Mapping is what the plugin is injected into the Scene.Systems as (i.e. input)
*
* @name Phaser.Input.InputPluginCache.register
* @type {function}
* @function Phaser.Input.InputPluginCache.register
* @static
* @since 3.10.0
*
*
* @param {string} key - A reference used to get this plugin from the plugin cache.
* @param {function} plugin - The plugin to be stored. Should be the core object, not instantiated.
* @param {string} mapping - If this plugin is to be injected into the Input Plugin, this is the property key used.
@ -41,11 +40,10 @@ InputPluginCache.register = function (key, plugin, mapping, settingsKey, configK
/**
* Returns the input plugin object from the cache based on the given key.
*
* @name Phaser.Input.InputPluginCache.getCore
* @type {function}
* @function Phaser.Input.InputPluginCache.getCore
* @static
* @since 3.10.0
*
*
* @param {string} key - The key of the input plugin to get.
*
* @return {Phaser.Types.Input.InputPluginContainer} The input plugin object.
@ -58,11 +56,10 @@ InputPluginCache.getPlugin = function (key)
/**
* Installs all of the registered Input Plugins into the given target.
*
* @name Phaser.Input.InputPluginCache.install
* @type {function}
* @function Phaser.Input.InputPluginCache.install
* @static
* @since 3.10.0
*
*
* @param {Phaser.Input.InputPlugin} target - The target InputPlugin to install the plugins into.
*/
InputPluginCache.install = function (target)
@ -88,11 +85,10 @@ InputPluginCache.install = function (target)
/**
* Removes an input plugin based on the given key.
*
* @name Phaser.Input.InputPluginCache.remove
* @type {function}
* @function Phaser.Input.InputPluginCache.remove
* @static
* @since 3.10.0
*
*
* @param {string} key - The key of the input plugin to remove.
*/
InputPluginCache.remove = function (key)

View file

@ -5,15 +5,19 @@
*/
/**
* Calculate the speed required to cover a distance in the time given.
* Calculate a per-ms speed from a distance and time (given in seconds).
*
* @function Phaser.Math.GetSpeed
* @since 3.0.0
*
* @param {number} distance - The distance to travel in pixels.
* @param {integer} time - The time, in ms, to cover the distance in.
* @param {number} distance - The distance.
* @param {integer} time - The time, in seconds.
*
* @return {number} The amount you will need to increment the position by each step in order to cover the distance in the time given.
* @return {number} The speed, in distance per ms.
*
* @example
* // 400px over 1 second is 0.4 px/ms
* Phaser.Math.GetSpeed(400, 1) // -> 0.4
*/
var GetSpeed = function (distance, time)
{

View file

@ -347,10 +347,14 @@ var RandomDataGenerator = new Class({
*
* @method Phaser.Math.RandomDataGenerator#pick
* @since 3.0.0
*
* @generic T
* @genericUse {T[]} - [array]
* @genericUse {T} - [$return]
*
* @param {array} array - The array to pick a random element from.
* @param {T[]} array - The array to pick a random element from.
*
* @return {*} A random member of the array.
* @return {T} A random member of the array.
*/
pick: function (array)
{
@ -376,9 +380,13 @@ var RandomDataGenerator = new Class({
* @method Phaser.Math.RandomDataGenerator#weightedPick
* @since 3.0.0
*
* @param {array} array - The array to pick a random element from.
* @generic T
* @genericUse {T[]} - [array]
* @genericUse {T} - [$return]
*
* @return {*} A random member of the array.
* @param {T[]} array - The array to pick a random element from.
*
* @return {T} A random member of the array.
*/
weightedPick: function (array)
{
@ -468,9 +476,12 @@ var RandomDataGenerator = new Class({
* @method Phaser.Math.RandomDataGenerator#shuffle
* @since 3.7.0
*
* @param {array} [array] - The array to be shuffled.
* @generic T
* @genericUse {T[]} - [array,$return]
*
* @return {array} The shuffled array.
* @param {T[]} [array] - The array to be shuffled.
*
* @return {T[]} The shuffled array.
*/
shuffle: function (array)
{

View file

@ -286,7 +286,9 @@ var Body = new Class({
this.velocity = new Vector2();
/**
* The Body's calculated velocity, in pixels per second, at the last step.
* The Body's change in position (due to velocity) at the last step, in pixels.
*
* The size of this value depends on the simulation's step rate.
*
* @name Phaser.Physics.Arcade.Body#newVelocity
* @type {Phaser.Math.Vector2}
@ -443,23 +445,24 @@ var Body = new Class({
this.maxVelocity = new Vector2(10000, 10000);
/**
* The maximum speed this Body is allowed to reach.
* The maximum speed this Body is allowed to reach, in pixels per second.
*
* If not negative it limits the scalar value of speed.
*
* Any negative value means no maximum is being applied.
* Any negative value means no maximum is being applied (the default).
*
* @name Phaser.Physics.Arcade.Body#maxSpeed
* @type {number}
* @default -1
* @since 3.16.0
*/
this.maxSpeed = -1;
/**
* If this Body is `immovable` and in motion, `friction` is the proportion of this Body's motion received by the riding Body on each axis, relative to 1.
* The default value (1, 0) moves the riding Body horizontally in equal proportion to this Body and vertically not at all.
* The horizontal component (x) is applied only when two colliding Bodies are separated vertically.
* The vertical component (y) is applied only when two colliding Bodies are separated horizontally.
* The default value (1, 0) moves the riding Body horizontally in equal proportion to this Body and vertically not at all.
*
* @name Phaser.Physics.Arcade.Body#friction
* @type {Phaser.Math.Vector2}
@ -641,7 +644,7 @@ var Body = new Class({
this.overlapR = 0;
/**
* Whether this Body is overlapped with another and both are not moving.
* Whether this Body is overlapped with another and both are not moving, on at least one axis.
*
* @name Phaser.Physics.Arcade.Body#embedded
* @type {boolean}
@ -671,29 +674,39 @@ var Body = new Class({
this.checkCollision = { none: false, up: true, down: true, left: true, right: true };
/**
* Whether this Body is colliding with another and in which direction.
* Whether this Body is colliding with a Body or Static Body and in which direction.
* In a collision where both bodies have zero velocity, `embedded` will be set instead.
*
* @name Phaser.Physics.Arcade.Body#touching
* @type {Phaser.Types.Physics.Arcade.ArcadeBodyCollision}
* @since 3.0.0
*
* @see Phaser.Physics.Arcade.Body#blocked
* @see Phaser.Physics.Arcade.Body#embedded
*/
this.touching = { none: true, up: false, down: false, left: false, right: false };
/**
* Whether this Body was colliding with another during the last step, and in which direction.
* This Body's `touching` value during the previous step.
*
* @name Phaser.Physics.Arcade.Body#wasTouching
* @type {Phaser.Types.Physics.Arcade.ArcadeBodyCollision}
* @since 3.0.0
*
* @see Phaser.Physics.Arcade.Body#touching
*/
this.wasTouching = { none: true, up: false, down: false, left: false, right: false };
/**
* Whether this Body is colliding with a tile or the world boundary.
* Whether this Body is colliding with a Static Body, a tile, or the world boundary.
* In a collision with a Static Body, if this Body has zero velocity then `embedded` will be set instead.
*
* @name Phaser.Physics.Arcade.Body#blocked
* @type {Phaser.Types.Physics.Arcade.ArcadeBodyCollision}
* @since 3.0.0
*
* @see Phaser.Physics.Arcade.Body#embedded
* @see Phaser.Physics.Arcade.Body#touching
*/
this.blocked = { none: true, up: false, down: false, left: false, right: false };
@ -761,6 +774,28 @@ var Body = new Class({
*/
this._dy = 0;
/**
* The final calculated change in the Body's horizontal position as of `postUpdate`.
*
* @name Phaser.Physics.Arcade.Body#_tx
* @type {number}
* @private
* @default 0
* @since 3.22.0
*/
this._tx = 0;
/**
* The final calculated change in the Body's vertical position as of `postUpdate`.
*
* @name Phaser.Physics.Arcade.Body#_ty
* @type {number}
* @private
* @default 0
* @since 3.22.0
*/
this._ty = 0;
/**
* Stores the Game Object's bounds.
*
@ -1050,6 +1085,9 @@ var Body = new Class({
{
this.gameObject.angle += this.deltaZ();
}
this._tx = dx;
this._ty = dy;
},
/**
@ -1423,6 +1461,9 @@ var Body = new Class({
/**
* The change in this Body's horizontal position from the previous step.
* This value is set during the Body's update phase.
*
* As a Body can update multiple times per step this may not hold the final
* delta value for the Body. In this case, please see the `deltaXFinal` method.
*
* @method Phaser.Physics.Arcade.Body#deltaX
* @since 3.0.0
@ -1437,6 +1478,9 @@ var Body = new Class({
/**
* The change in this Body's vertical position from the previous step.
* This value is set during the Body's update phase.
*
* As a Body can update multiple times per step this may not hold the final
* delta value for the Body. In this case, please see the `deltaYFinal` method.
*
* @method Phaser.Physics.Arcade.Body#deltaY
* @since 3.0.0
@ -1448,6 +1492,48 @@ var Body = new Class({
return this._dy;
},
/**
* The change in this Body's horizontal position from the previous game update.
*
* This value is set during the `postUpdate` phase and takes into account the
* `deltaMax` and final position of the Body.
*
* Because this value is not calculated until `postUpdate`, you must listen for it
* during a Scene `POST_UPDATE` or `RENDER` event, and not in `update`, as it will
* not be calculated by that point. If you _do_ use these values in `update` they
* will represent the delta from the _previous_ game frame.
*
* @method Phaser.Physics.Arcade.Body#deltaXFinal
* @since 3.22.0
*
* @return {number} The final delta x value.
*/
deltaXFinal: function ()
{
return this._tx;
},
/**
* The change in this Body's vertical position from the previous game update.
*
* This value is set during the `postUpdate` phase and takes into account the
* `deltaMax` and final position of the Body.
*
* Because this value is not calculated until `postUpdate`, you must listen for it
* during a Scene `POST_UPDATE` or `RENDER` event, and not in `update`, as it will
* not be calculated by that point. If you _do_ use these values in `update` they
* will represent the delta from the _previous_ game frame.
*
* @method Phaser.Physics.Arcade.Body#deltaYFinal
* @since 3.22.0
*
* @return {number} The final delta y value.
*/
deltaYFinal: function ()
{
return this._ty;
},
/**
* The change in this Body's rotation from the previous step, in degrees.
*

View file

@ -450,8 +450,7 @@ var StaticBody = new Class({
},
/**
* Updates this Static Body so that its position and dimensions are updated
* based on the current Game Object it is bound to.
* Syncs the Body's position and size with its parent Game Object.
*
* @method Phaser.Physics.Arcade.StaticBody#updateFromGameObject
* @since 3.1.0
@ -630,7 +629,6 @@ var StaticBody = new Class({
/**
* Resets this Body to the given coordinates. Also positions its parent Game Object to the same coordinates.
* Similar to `updateFromGameObject`, but doesn't modify the Body's dimensions.
*
* @method Phaser.Physics.Arcade.StaticBody#reset
* @since 3.0.0

View file

@ -15,7 +15,6 @@ var MatterSprite = require('./MatterSprite');
var MatterTileBody = require('./MatterTileBody');
var PointerConstraint = require('./PointerConstraint');
var Vertices = require('./lib/geometry/Vertices');
var Vector = require('./lib/geometry/Vector');
/**
* @classdesc
@ -186,6 +185,69 @@ var Factory = new Class({
return body;
},
/**
* **This function is still in development**
*
* Creates a body using the supplied body data, as provided by a JSON file.
*
* @method Phaser.Physics.Matter.Factory#fromJSON
* @since 3.22.0
*
* @param {number} x - The X coordinate of the body.
* @param {number} y - The Y coordinate of the body.
* @param {object} data - The body data object as parsed from the JSON body format.
* @param {object} [options] - Optional Matter body configuration object, as passed to `Body.create`.
* @param {boolean} [addToWorld=true] - Should the newly created body be immediately added to the World?
*
* @return {MatterJS.Body} A Matter JS Body.
*/
fromJSON: function (x, y, data, options, addToWorld)
{
if (options === undefined) { options = {}; }
if (addToWorld === undefined) { addToWorld = true; }
var body;
var vertexSets = data.verts;
if (vertexSets.length === 1)
{
// Just a single Body
options.vertices = vertexSets[0];
body = Body.create(options);
Bodies.flagCoincidentParts(body.parts);
}
else
{
var parts = [];
for (var i = 0; i < vertexSets.length; i++)
{
var part = Body.create({
vertices: vertexSets[i]
});
parts.push(part);
}
Bodies.flagCoincidentParts(parts);
options.parts = parts;
body = Body.create(options);
}
Body.setPosition(body, { x: x, y: y });
if (addToWorld)
{
this.world.add(body);
}
return body;
},
/**
* Create a new composite containing Matter Image objects created in a grid arrangement.
* This function uses the body bounds to prevent overlaps.
@ -475,8 +537,6 @@ var Factory = new Class({
* @method Phaser.Physics.Matter.Factory#worldConstraint
* @since 3.0.0
*
* @param {number} x - The x position in the world to create the constraint at.
* @param {number} y - The y position in the world to create the constraint at.
* @param {MatterJS.Body} body - The Matter `Body` that this constraint is attached to.
* @param {number} [length] - A number that specifies the target resting length of the constraint. If not given it is calculated automatically in `Constraint.create` from initial positions of the `constraint.bodyA` and `constraint.bodyB`.
* @param {number} [stiffness=1] - A Number that specifies the stiffness of the constraint, i.e. the rate at which it returns to its resting `constraint.length`. A value of `1` means the constraint should be very stiff. A value of `0.2` means the constraint acts as a soft spring.
@ -484,12 +544,11 @@ var Factory = new Class({
*
* @return {MatterJS.Constraint} A Matter JS Constraint.
*/
worldConstraint: function (x, y, body, length, stiffness, options)
worldConstraint: function (body, length, stiffness, options)
{
if (stiffness === undefined) { stiffness = 1; }
if (options === undefined) { options = {}; }
options.pointA = Vector.create(x, y);
options.bodyB = (body.type === 'body') ? body : body.body;
if (!isNaN(length))
@ -619,13 +678,14 @@ var Factory = new Class({
* @since 3.3.0
*
* @param {Phaser.GameObjects.GameObject} gameObject - The Game Object to inject the Matter Body in to.
* @param {(object|MatterJS.Body)} options - A Matter Body configuration object, or an instance of a Matter Body.
* @param {(object|MatterJS.Body)} [options] - A Matter Body configuration object, or an instance of a Matter Body.
* @param {boolean} [addToWorld=true] - Add this Matter Body to the World?
*
* @return {Phaser.GameObjects.GameObject} The Game Object that had the Matter Body injected into it.
*/
gameObject: function (gameObject, options)
gameObject: function (gameObject, options, addToWorld)
{
return MatterGameObject(this.world, gameObject, options);
return MatterGameObject(this.world, gameObject, options, addToWorld);
},
/**

View file

@ -31,13 +31,15 @@ function hasGetterOrSetter (def)
*
* @param {Phaser.Physics.Matter.World} world - The Matter world to add the body to.
* @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that will have the Matter body applied to it.
* @param {(object|MatterJS.Body)} options - A Matter Body configuration object, or an instance of a Matter Body.
* @param {(object|MatterJS.Body)} [options] - A Matter Body configuration object, or an instance of a Matter Body.
* @param {boolean} [addToWorld=true] - Should the newly created body be immediately added to the World?
*
* @return {Phaser.GameObjects.GameObject} The Game Object that was created with the Matter body.
*/
var MatterGameObject = function (world, gameObject, options)
var MatterGameObject = function (world, gameObject, options, addToWorld)
{
if (options === undefined) { options = {}; }
if (addToWorld === undefined) { addToWorld = true; }
var x = gameObject.x;
var y = gameObject.y;
@ -92,7 +94,7 @@ var MatterGameObject = function (world, gameObject, options)
if (options.hasOwnProperty('type') && options.type === 'body')
{
gameObject.setExistingBody(options, true);
gameObject.setExistingBody(options, addToWorld);
}
else
{
@ -102,6 +104,8 @@ var MatterGameObject = function (world, gameObject, options)
{
shape = 'rectangle';
}
options.addToWorld = addToWorld;
gameObject.setBody(shape, options);
}

View file

@ -4,32 +4,93 @@
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
var Body = require('./lib/body/Body');
var Axes = require('./lib/geometry/Axes');
var Bodies = require('./lib/factory/Bodies');
var Body = require('./lib/body/Body');
var Bounds = require('./lib/geometry/Bounds');
var Class = require('../../utils/Class');
var Composite = require('./lib/body/Composite');
var Composites = require('./lib/factory/Composites');
var Constraint = require('./lib/constraint/Constraint');
var Detector = require('./lib/collision/Detector');
var Factory = require('./Factory');
var GetFastValue = require('../../utils/object/GetFastValue');
var GetValue = require('../../utils/object/GetValue');
var Grid = require('./lib/collision/Grid');
var MatterAttractors = require('./lib/plugins/MatterAttractors');
var MatterCollisionEvents = require('./lib/plugins/MatterCollisionEvents');
var MatterLib = require('./lib/core/Matter');
var MatterWrap = require('./lib/plugins/MatterWrap');
var Merge = require('../../utils/object/Merge');
var Pair = require('./lib/collision/Pair');
var Pairs = require('./lib/collision/Pairs');
var Plugin = require('./lib/core/Plugin');
var PluginCache = require('../../plugins/PluginCache');
var Query = require('./lib/collision/Query');
var Resolver = require('./lib/collision/Resolver');
var SAT = require('./lib/collision/SAT');
var SceneEvents = require('../../scene/events');
var World = require('./World');
var Svg = require('./lib/geometry/Svg');
var Vector = require('./lib/geometry/Vector');
var Vertices = require('./lib/geometry/Vertices');
var World = require('./World');
/**
* @classdesc
* [description]
* The Phaser Matter plugin provides the ability to use the Matter JS Physics Engine within your Phaser games.
*
* Unlike Arcade Physics, the other physics system provided with Phaser, Matter JS is a full-body physics system.
* It features:
*
* * Rigid bodies
* * Compound bodies
* * Composite bodies
* * Concave and convex hulls
* * Physical properties (mass, area, density etc.)
* * Restitution (elastic and inelastic collisions)
* * Collisions (broad-phase, mid-phase and narrow-phase)
* * Stable stacking and resting
* * Conservation of momentum
* * Friction and resistance
* * Constraints
* * Gravity
* * Sleeping and static bodies
* * Rounded corners (chamfering)
* * Views (translate, zoom)
* * Collision queries (raycasting, region tests)
* * Time scaling (slow-mo, speed-up)
*
* Configuration of Matter is handled via the Matter World Config object, which can be passed in either the
* Phaser Game Config, or Phaser Scene Config. Here is a basic example:
*
* ```js
* physics: {
* default: 'matter',
* matter: {
* enableSleeping: true,
* gravity: {
* y: 0
* },
* debug: {
* showBody: true,
* showStaticBody: true
* }
* }
* }
* ```
*
* This class acts as an interface between a Phaser Scene and a single instance of the Matter Engine.
*
* Use it to access the most common Matter features and helper functions.
*
* You can find details, documentation and examples on the Matter JS website: https://brm.io/matter-js/
*
* @class MatterPhysics
* @memberof Phaser.Physics.Matter
* @constructor
* @since 3.0.0
*
* @param {Phaser.Scene} scene - [description]
* @param {Phaser.Scene} scene - The Phaser Scene that owns this Matter Physics instance.
*/
var MatterPhysics = new Class({
@ -38,7 +99,7 @@ var MatterPhysics = new Class({
function MatterPhysics (scene)
{
/**
* [description]
* The Phaser Scene that owns this Matter Physics instance
*
* @name Phaser.Physics.Matter.MatterPhysics#scene
* @type {Phaser.Scene}
@ -47,7 +108,7 @@ var MatterPhysics = new Class({
this.scene = scene;
/**
* [description]
* A reference to the Scene Systems that belong to the Scene owning this Matter Physics instance.
*
* @name Phaser.Physics.Matter.MatterPhysics#systems
* @type {Phaser.Scenes.Systems}
@ -56,16 +117,17 @@ var MatterPhysics = new Class({
this.systems = scene.sys;
/**
* [description]
* The parsed Matter Configuration object.
*
* @name Phaser.Physics.Matter.MatterPhysics#config
* @type {object}
* @type {Phaser.Types.Physics.Matter.MatterWorldConfig}
* @since 3.0.0
*/
this.config = this.getConfig();
/**
* [description]
* An instance of the Matter World class. This class is responsible for the updating of the
* Matter Physics world, as well as handling debug drawing functions.
*
* @name Phaser.Physics.Matter.MatterPhysics#world
* @type {Phaser.Physics.Matter.World}
@ -74,7 +136,12 @@ var MatterPhysics = new Class({
this.world;
/**
* [description]
* An instance of the Matter Factory. This class provides lots of functions for creatying a
* wide variety of physics objects and adds them automatically to the Matter World.
*
* You can use this class to cut-down on the amount of code required in your game, however,
* use of the Factory is entirely optional and should be seen as a development aid. It's
* perfectly possible to create and add components to the Matter world without using it.
*
* @name Phaser.Physics.Matter.MatterPhysics#add
* @type {Phaser.Physics.Matter.Factory}
@ -82,8 +149,222 @@ var MatterPhysics = new Class({
*/
this.add;
// Body
/**
* A reference to the `Matter.Vertices` module which contains methods for creating and manipulating sets of vertices.
* A reference to the `Matter.Body` module.
*
* The `Matter.Body` module contains methods for creating and manipulating body models.
* A `Matter.Body` is a rigid body that can be simulated by a `Matter.Engine`.
* Factories for commonly used body configurations (such as rectangles, circles and other polygons) can be found in the `Bodies` module.
*
* @name Phaser.Physics.Matter.MatterPhysics#body
* @type {MatterJS.Body}
* @since 3.18.0
*/
this.body = Body;
/**
* A reference to the `Matter.Composite` module.
*
* The `Matter.Composite` module contains methods for creating and manipulating composite bodies.
* A composite body is a collection of `Matter.Body`, `Matter.Constraint` and other `Matter.Composite`, therefore composites form a tree structure.
* It is important to use the functions in this module to modify composites, rather than directly modifying their properties.
* Note that the `Matter.World` object is also a type of `Matter.Composite` and as such all composite methods here can also operate on a `Matter.World`.
*
* @name Phaser.Physics.Matter.MatterPhysics#composite
* @type {MatterJS.Composite}
* @since 3.22.0
*/
this.composite = Composite;
// Collision:
/**
* A reference to the `Matter.Detector` module.
*
* The `Matter.Detector` module contains methods for detecting collisions given a set of pairs.
*
* @name Phaser.Physics.Matter.MatterPhysics#detector
* @type {MatterJS.Detector}
* @since 3.22.0
*/
this.detector = Detector;
/**
* A reference to the `Matter.Grid` module.
*
* The `Matter.Grid` module contains methods for creating and manipulating collision broadphase grid structures.
*
* @name Phaser.Physics.Matter.MatterPhysics#grid
* @type {MatterJS.Grid}
* @since 3.22.0
*/
this.grid = Grid;
/**
* A reference to the `Matter.Pair` module.
*
* The `Matter.Pair` module contains methods for creating and manipulating collision pairs.
*
* @name Phaser.Physics.Matter.MatterPhysics#pair
* @type {MatterJS.Pair}
* @since 3.22.0
*/
this.pair = Pair;
/**
* A reference to the `Matter.Pairs` module.
*
* The `Matter.Pairs` module contains methods for creating and manipulating collision pair sets.
*
* @name Phaser.Physics.Matter.MatterPhysics#pairs
* @type {MatterJS.Pairs}
* @since 3.22.0
*/
this.pairs = Pairs;
/**
* A reference to the `Matter.Query` module.
*
* The `Matter.Query` module contains methods for performing collision queries.
*
* @name Phaser.Physics.Matter.MatterPhysics#query
* @type {MatterJS.Query}
* @since 3.22.0
*/
this.query = Query;
/**
* A reference to the `Matter.Resolver` module.
*
* The `Matter.Resolver` module contains methods for resolving collision pairs.
*
* @name Phaser.Physics.Matter.MatterPhysics#resolver
* @type {MatterJS.Resolver}
* @since 3.22.0
*/
this.resolver = Resolver;
/**
* A reference to the `Matter.SAT` module.
*
* The `Matter.SAT` module contains methods for detecting collisions using the Separating Axis Theorem.
*
* @name Phaser.Physics.Matter.MatterPhysics#sat
* @type {MatterJS.SAT}
* @since 3.22.0
*/
this.sat = SAT;
// Constraint
/**
* A reference to the `Matter.Constraint` module.
*
* The `Matter.Constraint` module contains methods for creating and manipulating constraints.
* Constraints are used for specifying that a fixed distance must be maintained between two bodies (or a body and a fixed world-space position).
* The stiffness of constraints can be modified to create springs or elastic.
*
* @name Phaser.Physics.Matter.MatterPhysics#constraint
* @type {MatterJS.Constraint}
* @since 3.22.0
*/
this.constraint = Constraint;
// Factory
/**
* A reference to the `Matter.Bodies` module.
*
* The `Matter.Bodies` module contains factory methods for creating rigid body models
* with commonly used body configurations (such as rectangles, circles and other polygons).
*
* @name Phaser.Physics.Matter.MatterPhysics#bodies
* @type {MatterJS.Bodies}
* @since 3.18.0
*/
this.bodies = Bodies;
/**
* A reference to the `Matter.Composites` module.
*
* The `Matter.Composites` module contains factory methods for creating composite bodies
* with commonly used configurations (such as stacks and chains).
*
* @name Phaser.Physics.Matter.MatterPhysics#composites
* @type {MatterJS.Composites}
* @since 3.22.0
*/
this.composites = Composites;
// Geometry
/**
* A reference to the `Matter.Axes` module.
*
* The `Matter.Axes` module contains methods for creating and manipulating sets of axes.
*
* @name Phaser.Physics.Matter.MatterPhysics#axes
* @type {MatterJS.Axes}
* @since 3.22.0
*/
this.axes = Axes;
/**
* A reference to the `Matter.Bounds` module.
*
* The `Matter.Bounds` module contains methods for creating and manipulating axis-aligned bounding boxes (AABB).
*
* @name Phaser.Physics.Matter.MatterPhysics#bounds
* @type {MatterJS.Bounds}
* @since 3.22.0
*/
this.bounds = Bounds;
/**
* A reference to the `Matter.Svg` module.
*
* The `Matter.Svg` module contains methods for converting SVG images into an array of vector points.
*
* To use this module you also need the SVGPathSeg polyfill: https://github.com/progers/pathseg
*
* @name Phaser.Physics.Matter.MatterPhysics#svg
* @type {MatterJS.Svg}
* @since 3.22.0
*/
this.svg = Svg;
/**
* A reference to the `Matter.Vector` module.
*
* The `Matter.Vector` module contains methods for creating and manipulating vectors.
* Vectors are the basis of all the geometry related operations in the engine.
* A `Matter.Vector` object is of the form `{ x: 0, y: 0 }`.
*
* @name Phaser.Physics.Matter.MatterPhysics#vector
* @type {MatterJS.Vector}
* @since 3.22.0
*/
this.vector = Vector;
/**
* A reference to the `Matter.Vertices` module.
*
* The `Matter.Vertices` module contains methods for creating and manipulating sets of vertices.
* A set of vertices is an array of `Matter.Vector` with additional indexing properties inserted by `Vertices.create`.
* A `Matter.Body` maintains a set of vertices to represent the shape of the object (its convex hull).
*
* @name Phaser.Physics.Matter.MatterPhysics#vertices
* @type {MatterJS.Vertices}
* @since 3.22.0
*/
this.vertices = Vertices;
/**
* A reference to the `Matter.Vertices` module.
*
* The `Matter.Vertices` module contains methods for creating and manipulating sets of vertices.
* A set of vertices is an array of `Matter.Vector` with additional indexing properties inserted by `Vertices.create`.
* A `Matter.Body` maintains a set of vertices to represent the shape of the object (its convex hull).
*
@ -93,38 +374,29 @@ var MatterPhysics = new Class({
*/
this.verts = Vertices;
/**
* A reference to the `Matter.Body` module which contains methods for creating and manipulating body models.
*
* @name Phaser.Physics.Matter.MatterPhysics#body
* @type {MatterJS.Body}
* @since 3.18.0
*/
this.body = Body;
/**
* A reference to the `Matter.Bodies` module which contains methods for creating bodies.
*
* @name Phaser.Physics.Matter.MatterPhysics#bodies
* @type {MatterJS.Bodies}
* @since 3.18.0
*/
this.bodies = Bodies;
// Matter plugins
if (GetValue(this.config, 'plugins.collisionevents', true))
{
this.enableCollisionEventsPlugin();
}
if (GetValue(this.config, 'plugins.attractors', false))
{
Plugin.register(MatterAttractors);
Plugin.use(MatterLib, MatterAttractors);
this.enableAttractorPlugin();
}
if (GetValue(this.config, 'plugins.wrap', false))
{
Plugin.register(MatterWrap);
Plugin.use(MatterLib, MatterWrap);
this.enableWrapPlugin();
}
Resolver._restingThresh = GetValue(this.config, 'restingThresh', 4);
Resolver._restingThreshTangent = GetValue(this.config, 'restingThreshTangent', 6);
Resolver._positionDampen = GetValue(this.config, 'positionDampen', 0.9);
Resolver._positionWarming = GetValue(this.config, 'positionWarming', 0.8);
Resolver._frictionNormalMultiplier = GetValue(this.config, 'frictionNormalMultiplier', 5);
scene.sys.events.once(SceneEvents.BOOT, this.boot, this);
scene.sys.events.on(SceneEvents.START, this.start, this);
},
@ -170,12 +442,12 @@ var MatterPhysics = new Class({
},
/**
* [description]
* This internal method is called when this class starts and retrieves the final Matter World Config.
*
* @method Phaser.Physics.Matter.MatterPhysics#getConfig
* @since 3.0.0
*
* @return {object} [description]
* @return {Phaser.Types.Physics.Matter.MatterWorldConfig} The Matter World Config.
*/
getConfig: function ()
{
@ -191,12 +463,20 @@ var MatterPhysics = new Class({
},
/**
* [description]
* Enables the Matter Attractors Plugin.
*
* The attractors plugin that makes it easy to apply continual forces on bodies.
* It's possible to simulate effects such as wind, gravity and magnetism.
*
* https://github.com/liabru/matter-attractors
*
* This method is called automatically if `plugins.attractors` is set in the Matter World Config.
* However, you can also call it directly from within your game.
*
* @method Phaser.Physics.Matter.MatterPhysics#enableAttractorPlugin
* @since 3.0.0
*
* @return {Phaser.Physics.Matter.MatterPhysics} This Matter Physics instance.
* @return {this} This Matter Physics instance.
*/
enableAttractorPlugin: function ()
{
@ -207,12 +487,21 @@ var MatterPhysics = new Class({
},
/**
* [description]
* Enables the Matter Wrap Plugin.
*
* The coordinate wrapping plugin that automatically wraps the position of bodies such that they always stay
* within the given bounds. Upon crossing a boundary the body will appear on the opposite side of the bounds,
* while maintaining its velocity.
*
* https://github.com/liabru/matter-wrap
*
* This method is called automatically if `plugins.wrap` is set in the Matter World Config.
* However, you can also call it directly from within your game.
*
* @method Phaser.Physics.Matter.MatterPhysics#enableWrapPlugin
* @since 3.0.0
*
* @return {Phaser.Physics.Matter.MatterPhysics} This Matter Physics instance.
* @return {this} This Matter Physics instance.
*/
enableWrapPlugin: function ()
{
@ -223,9 +512,51 @@ var MatterPhysics = new Class({
},
/**
* [description]
* Enables the Matter Collision Events Plugin.
*
* Note that this plugin is enabled by default. So you should only ever need to call this
* method if you have specifically disabled the plugin in your Matter World Config.
* You can disable it by setting `plugins.collisionevents: false` in your Matter World Config.
*
* This plugin triggers three new events on Matter.Body:
*
* 1. `onCollide`
* 2. `onCollideEnd`
* 3. `onCollideActive`
*
* These events correspond to the Matter.js events `collisionStart`, `collisionActive` and `collisionEnd`, respectively.
* You can listen to these events via Matter.Events or they will also be emitted from the Matter World.
*
* This plugin also extends Matter.Body with three convenience functions:
*
* `Matter.Body.setOnCollide(callback)`
* `Matter.Body.setOnCollideEnd(callback)`
* `Matter.Body.setOnCollideActive(callback)`
*
* You can register event callbacks by providing a function of type (pair: Matter.Pair) => void
*
* https://github.com/dxu/matter-collision-events
*
* @method Phaser.Physics.Matter.MatterPhysics#enableCollisionEventsPlugin
* @since 3.22.0
*
* @return {this} This Matter Physics instance.
*/
enableCollisionEventsPlugin: function ()
{
Plugin.register(MatterCollisionEvents);
Plugin.use(MatterLib, MatterCollisionEvents);
return this;
},
/**
* Pauses the Matter World instance and sets `enabled` to `false`.
*
* A paused world will not run any simulations for the duration it is paused.
*
* @method Phaser.Physics.Matter.MatterPhysics#pause
* @fires Phaser.Physics.Matter.Events#PAUSE
* @since 3.0.0
*
* @return {Phaser.Physics.Matter.World} The Matter World object.
@ -236,7 +567,7 @@ var MatterPhysics = new Class({
},
/**
* [description]
* Resumes this Matter World instance from a paused state and sets `enabled` to `true`.
*
* @method Phaser.Physics.Matter.MatterPhysics#resume
* @since 3.0.0
@ -255,7 +586,7 @@ var MatterPhysics = new Class({
* @method Phaser.Physics.Matter.MatterPhysics#set60Hz
* @since 3.4.0
*
* @return {Phaser.Physics.Matter.MatterPhysics} This Matter Physics instance.
* @return {this} This Matter Physics instance.
*/
set60Hz: function ()
{
@ -272,7 +603,7 @@ var MatterPhysics = new Class({
* @method Phaser.Physics.Matter.MatterPhysics#set30Hz
* @since 3.4.0
*
* @return {Phaser.Physics.Matter.MatterPhysics} This Matter Physics instance.
* @return {this} This Matter Physics instance.
*/
set30Hz: function ()
{
@ -306,14 +637,416 @@ var MatterPhysics = new Class({
* @method Phaser.Physics.Matter.MatterPhysics#step
* @since 3.4.0
*
* @param {number} [delta=16.666] - [description]
* @param {number} [correction=1] - [description]
* @param {number} [delta=16.666] - The delta value.
* @param {number} [correction=1] - Optional delta correction value.
*/
step: function (delta, correction)
{
this.world.step(delta, correction);
},
/**
* Checks if the vertices of the given body, or an array of bodies, contains the given point, or not.
*
* You can pass in either a single body, or an array of bodies to be checked. This method will
* return `true` if _any_ of the bodies in the array contain the point. See the `intersectPoint` method if you need
* to get a list of intersecting bodies.
*
* The point should be transformed into the Matter World coordinate system in advance. This happens by
* default with Input Pointers, but if you wish to use points from another system you may need to
* transform them before passing them.
*
* @method Phaser.Physics.Matter.MatterPhysics#containsPoint
* @since 3.22.0
*
* @param {(MatterJS.Body|MatterJS.Body[])} body - The body, or an array of bodies, to check against the point.
* @param {number} x - The horizontal coordinate of the point.
* @param {number} y - The vertical coordinate of the point.
*
* @return {boolean} `true` if the point is within one of the bodies given, otherwise `false`.
*/
containsPoint: function (body, x, y)
{
body = this.getMatterBodies(body);
var position = Vector.create(x, y);
var result = Query.point(body, position);
return (result.length > 0) ? true : false;
},
/**
* Checks the given coordinates to see if any vertices of the given bodies contain it.
*
* If no bodies are provided it will search all bodies in the Matter World, including within Composites.
*
* The coordinates should be transformed into the Matter World coordinate system in advance. This happens by
* default with Input Pointers, but if you wish to use coordinates from another system you may need to
* transform them before passing them.
*
* @method Phaser.Physics.Matter.MatterPhysics#intersectPoint
* @since 3.22.0
*
* @param {number} x - The horizontal coordinate of the point.
* @param {number} y - The vertical coordinate of the point.
* @param {MatterJS.Body[]} [bodies] - An array of bodies to check. If not provided it will search all bodies in the world.
*
* @return {MatterJS.Body[]} An array of bodies which contain the given point.
*/
intersectPoint: function (x, y, bodies)
{
bodies = this.getMatterBodies(bodies);
var position = Vector.create(x, y);
var output = [];
var result = Query.point(bodies, position);
result.forEach(function (body)
{
if (output.indexOf(body) === -1)
{
output.push(body);
}
});
return output;
},
/**
* Checks the given rectangular area to see if any vertices of the given bodies intersect with it.
* Or, if the `outside` parameter is set to `true`, it checks to see which bodies do not
* intersect with it.
*
* If no bodies are provided it will search all bodies in the Matter World, including within Composites.
*
* @method Phaser.Physics.Matter.MatterPhysics#intersectRect
* @since 3.22.0
*
* @param {number} x - The horizontal coordinate of the top-left of the area.
* @param {number} y - The vertical coordinate of the top-left of the area.
* @param {number} width - The width of the area.
* @param {number} height - The height of the area.
* @param {boolean} [outside=false] - If `false` it checks for vertices inside the area, if `true` it checks for vertices outside the area.
* @param {MatterJS.Body[]} [bodies] - An array of bodies to check. If not provided it will search all bodies in the world.
*
* @return {MatterJS.Body[]} An array of bodies that intersect with the given area.
*/
intersectRect: function (x, y, width, height, outside, bodies)
{
if (outside === undefined) { outside = false; }
bodies = this.getMatterBodies(bodies);
var bounds = {
min: { x: x, y: y },
max: { x: x + width, y: y + height }
};
var output = [];
var result = Query.region(bodies, bounds, outside);
result.forEach(function (body)
{
if (output.indexOf(body) === -1)
{
output.push(body);
}
});
return output;
},
/**
* Checks the given ray segment to see if any vertices of the given bodies intersect with it.
*
* If no bodies are provided it will search all bodies in the Matter World.
*
* The width of the ray can be specified via the `rayWidth` parameter.
*
* @method Phaser.Physics.Matter.MatterPhysics#intersectRay
* @since 3.22.0
*
* @param {number} x1 - The horizontal coordinate of the start of the ray segment.
* @param {number} y1 - The vertical coordinate of the start of the ray segment.
* @param {number} x2 - The horizontal coordinate of the end of the ray segment.
* @param {number} y2 - The vertical coordinate of the end of the ray segment.
* @param {number} [rayWidth=1] - The width of the ray segment.
* @param {MatterJS.Body[]} [bodies] - An array of bodies to check. If not provided it will search all bodies in the world.
*
* @return {MatterJS.Body[]} An array of bodies whos vertices intersect with the ray segment.
*/
intersectRay: function (x1, y1, x2, y2, rayWidth, bodies)
{
if (rayWidth === undefined) { rayWidth = 1; }
bodies = this.getMatterBodies(bodies);
var result = [];
var collisions = Query.ray(bodies, Vector.create(x1, y1), Vector.create(x2, y2), rayWidth);
for (var i = 0; i < collisions.length; i++)
{
result.push(collisions[i].body);
}
return result;
},
/**
* Checks the given Matter Body to see if it intersects with any of the given bodies.
*
* If no bodies are provided it will check against all bodies in the Matter World.
*
* @method Phaser.Physics.Matter.MatterPhysics#intersectBody
* @since 3.22.0
*
* @param {MatterJS.Body} body - The target body.
* @param {MatterJS.Body[]} [bodies] - An array of bodies to check the target body against. If not provided it will search all bodies in the world.
*
* @return {MatterJS.Body[]} An array of bodies whos vertices intersect with target body.
*/
intersectBody: function (body, bodies)
{
bodies = this.getMatterBodies(bodies);
var result = [];
var collisions = Query.collides(body, bodies);
for (var i = 0; i < collisions.length; i++)
{
var pair = collisions[i];
if (pair.bodyA === body)
{
result.push(pair.bodyB);
}
else
{
result.push(pair.bodyA);
}
}
return result;
},
/**
* Checks to see if the target body, or an array of target bodies, intersects with any of the given bodies.
*
* If intersection occurs this method will return `true` and, if provided, invoke the callbacks.
*
* If no bodies are provided for the second parameter the target will check again all bodies in the Matter World.
*
* Note that bodies can only overlap if they are in non-colliding collision groups or categories.
*
* If you provide a `processCallback` then the two bodies that overlap are sent to it. This callback
* must return a boolean and is used to allow you to perform additional processing tests before a final
* outcome is decided. If it returns `true` then the bodies are finally passed to the `overlapCallback`, if set.
*
* If you provide an `overlapCallback` then the matching pairs of overlapping bodies will be sent to it.
*
* Both callbacks have the following signature: `function (bodyA, bodyB, collisionInfo)` where `bodyA` is always
* the target body. The `collisionInfo` object contains additional data, such as the angle and depth of penetration.
*
* @method Phaser.Physics.Matter.MatterPhysics#overlap
* @since 3.22.0
*
* @param {(MatterJS.Body|MatterJS.Body[])} target - The target body, or array of target bodies, to check.
* @param {MatterJS.Body[]} [bodies] - The second body, or array of bodies, to check. If falsey it will check against all bodies in the world.
* @param {ArcadePhysicsCallback} [overlapCallback] - An optional callback function that is called if the bodies overlap.
* @param {ArcadePhysicsCallback} [processCallback] - An optional callback function that lets you perform additional checks against the two bodies if they overlap. If this is set then `overlapCallback` will only be invoked if this callback returns `true`.
* @param {*} [callbackContext] - The context, or scope, in which to run the callbacks.
*
* @return {boolean} `true` if the target body intersects with _any_ of the bodies given, otherwise `false`.
*/
overlap: function (target, bodies, overlapCallback, processCallback, callbackContext)
{
if (overlapCallback === undefined) { overlapCallback = null; }
if (processCallback === undefined) { processCallback = null; }
if (callbackContext === undefined) { callbackContext = overlapCallback; }
if (!Array.isArray(target))
{
target = [ target ];
}
target = this.getMatterBodies(target);
bodies = this.getMatterBodies(bodies);
var match = false;
for (var i = 0; i < target.length; i++)
{
var entry = target[i];
var collisions = Query.collides(entry, bodies);
for (var c = 0; c < collisions.length; c++)
{
var info = collisions[c];
var bodyB = (info.bodyA.id === entry.id) ? info.bodyB : info.bodyA;
if (!processCallback || processCallback.call(callbackContext, entry, bodyB, info))
{
match = true;
if (overlapCallback)
{
overlapCallback.call(callbackContext, entry, bodyB, info);
}
else if (!processCallback)
{
// If there are no callbacks we don't need to test every body, just exit when the first is found
return true;
}
}
}
}
return match;
},
/**
* Sets the collision filter category of all given Matter Bodies to the given value.
*
* This number must be a power of two between 2^0 (= 1) and 2^31.
*
* Bodies with different collision groups (see {@link #setCollisionGroup}) will only collide if their collision
* categories are included in their collision masks (see {@link #setCollidesWith}).
*
* @method Phaser.Physics.Matter.MatterPhysics#setCollisionCategory
* @since 3.22.0
*
* @param {MatterJS.Body[]} bodies - An array of bodies to update. If falsey it will use all bodies in the world.
* @param {number} value - Unique category bitfield.
*
* @return {this} This Matter Physics instance.
*/
setCollisionCategory: function (bodies, value)
{
bodies = this.getMatterBodies(bodies);
bodies.forEach(function (body)
{
body.collisionFilter.category = value;
});
return this;
},
/**
* Sets the collision filter group of all given Matter Bodies to the given value.
*
* If the group value is zero, or if two Matter Bodies have different group values,
* they will collide according to the usual collision filter rules (see {@link #setCollisionCategory} and {@link #setCollisionGroup}).
*
* If two Matter Bodies have the same positive group value, they will always collide;
* if they have the same negative group value they will never collide.
*
* @method Phaser.Physics.Matter.MatterPhysics#setCollisionGroup
* @since 3.22.0
*
* @param {MatterJS.Body[]} bodies - An array of bodies to update. If falsey it will use all bodies in the world.
* @param {number} value - Unique group index.
*
* @return {this} This Matter Physics instance.
*/
setCollisionGroup: function (bodies, value)
{
bodies = this.getMatterBodies(bodies);
bodies.forEach(function (body)
{
body.collisionFilter.group = value;
});
return this;
},
/**
* Sets the collision filter mask of all given Matter Bodies to the given value.
*
* Two Matter Bodies with different collision groups will only collide if each one includes the others
* category in its mask based on a bitwise AND operation: `(categoryA & maskB) !== 0` and
* `(categoryB & maskA) !== 0` are both true.
*
* @method Phaser.Physics.Matter.MatterPhysics#setCollidesWith
* @since 3.22.0
*
* @param {MatterJS.Body[]} bodies - An array of bodies to update. If falsey it will use all bodies in the world.
* @param {(number|number[])} categories - A unique category bitfield, or an array of them.
*
* @return {this} This Matter Physics instance.
*/
setCollidesWith: function (bodies, categories)
{
bodies = this.getMatterBodies(bodies);
var flags = 0;
if (!Array.isArray(categories))
{
flags = categories;
}
else
{
for (var i = 0; i < categories.length; i++)
{
flags |= categories[i];
}
}
bodies.forEach(function (body)
{
body.collisionFilter.mask = flags;
});
return this;
},
/**
* Takes an array and returns a new array made from all of the Matter Bodies found in the original array.
*
* For example, passing in Matter Game Objects, such as a bunch of Matter Sprites, to this method, would
* return an array containing all of their native Matter Body objects.
*
* If the `bodies` argument is falsey, it will return all bodies in the world.
*
* @method Phaser.Physics.Matter.MatterPhysics#getMatterBodies
* @since 3.22.0
*
* @param {array} [bodies] - An array of objects to extract the bodies from. If falsey, it will return all bodis in the world.
*
* @return {MatterJS.Body[]} An array of native Matter Body objects.
*/
getMatterBodies: function (bodies)
{
if (!bodies)
{
return this.world.getAllBodies();
}
if (!Array.isArray(bodies))
{
bodies = [ bodies ];
}
var output = [];
for (var i = 0; i < bodies.length; i++)
{
var body = (bodies[i].hasOwnProperty('body')) ? bodies[i].body : bodies[i];
output.push(body);
}
return output;
},
/**
* The Scene that owns this plugin is shutting down.
* We need to kill and reset all internal properties as well as stop listening to Scene events.

View file

@ -6,10 +6,8 @@
var Bodies = require('./lib/factory/Bodies');
var Body = require('./lib/body/Body');
var Bounds = require('./lib/geometry/Bounds');
var Common = require('./lib/core/Common');
var GetFastValue = require('../../utils/object/GetFastValue');
var Vector = require('./lib/geometry/Vector');
var Vertices = require('./lib/geometry/Vertices');
/**
@ -58,14 +56,11 @@ var PhysicsEditorParser = {
var body = Body.create(matterConfig);
Body.setParts(body, fixtures);
body.render.sprite.xOffset = body.position.x / w;
body.render.sprite.yOffset = body.position.y / h;
Body.setPosition(body, { x: x, y: y });
return body;
},
/**
* Parses an element of the "fixtures" list exported by PhysicsEditor
*
@ -113,12 +108,11 @@ var PhysicsEditorParser = {
*/
parseVertices: function (vertexSets, options)
{
var i, j, k, v, z;
var parts = [];
options = options || {};
for (v = 0; v < vertexSets.length; v += 1)
for (var v = 0; v < vertexSets.length; v++)
{
parts.push(Body.create(Common.extend({
position: Vertices.centre(vertexSets[v]),
@ -127,44 +121,7 @@ var PhysicsEditorParser = {
}
// flag coincident part edges
var coincidentMaxDist = 5;
for (i = 0; i < parts.length; i++)
{
var partA = parts[i];
for (j = i + 1; j < parts.length; j++)
{
var partB = parts[j];
if (Bounds.overlaps(partA.bounds, partB.bounds))
{
var pav = partA.vertices,
pbv = partB.vertices;
// iterate vertices of both parts
for (k = 0; k < partA.vertices.length; k++)
{
for (z = 0; z < partB.vertices.length; z++)
{
// find distances between the vertices
var da = Vector.magnitudeSquared(Vector.sub(pav[(k + 1) % pav.length], pbv[z])),
db = Vector.magnitudeSquared(Vector.sub(pav[k], pbv[(z + 1) % pbv.length]));
// if both vertices are very close, consider the edge concident (internal)
if (da < coincidentMaxDist && db < coincidentMaxDist)
{
pav[k].isInternal = true;
pbv[z].isInternal = true;
}
}
}
}
}
}
return parts;
return Bodies.flagCoincidentParts(parts);
}
};

View file

@ -49,7 +49,6 @@ var PointerConstraint = new Class({
label: 'Pointer Constraint',
pointA: { x: 0, y: 0 },
pointB: { x: 0, y: 0 },
damping: 0,
length: 0.01,
stiffness: 0.1,
angularStiffness: 1,
@ -144,7 +143,7 @@ var PointerConstraint = new Class({
* The native Matter Constraint that is used to attach to bodies.
*
* @name Phaser.Physics.Matter.PointerConstraint#constraint
* @type {object}
* @type {MatterJS.Constraint}
* @since 3.0.0
*/
this.constraint = Constraint.create(Merge(options, defaults));
@ -152,17 +151,17 @@ var PointerConstraint = new Class({
this.world.on(Events.BEFORE_UPDATE, this.update, this);
scene.sys.input.on(InputEvents.POINTER_DOWN, this.onDown, this);
scene.sys.input.on(InputEvents.POINTER_UP, this.onUp, this);
},
/**
* A Pointer has been pressed down onto the Scene.
*
* If this Constraint doesn't have an active Pointer then a hit test is
* run against all active bodies in the world. If one is found it is bound
* to this constraint and the drag begins.
* If this Constraint doesn't have an active Pointer then a hit test is set to
* run against all active bodies in the world during the _next_ call to `update`.
* If a body is found, it is bound to this constraint and the drag begins.
*
* @method Phaser.Physics.Matter.PointerConstraint#onDown
* @fires Phaser.Physics.Matter.Events#DRAG_START
* @since 3.0.0
*
* @param {Phaser.Input.Pointer} pointer - A reference to the Pointer that was pressed.
@ -171,12 +170,24 @@ var PointerConstraint = new Class({
{
if (!this.pointer)
{
if (this.getBody(pointer))
{
this.pointer = pointer;
this.pointer = pointer;
this.camera = pointer.camera;
}
},
this.camera = pointer.camera;
}
/**
* A Pointer has been released from the Scene. If it was the one this constraint was using, it's cleared.
*
* @method Phaser.Physics.Matter.PointerConstraint#onUp
* @since 3.22.0
*
* @param {Phaser.Input.Pointer} pointer - A reference to the Pointer that was pressed.
*/
onUp: function (pointer)
{
if (pointer === this.pointer)
{
this.pointer = null;
}
},
@ -186,6 +197,7 @@ var PointerConstraint = new Class({
* body.
*
* @method Phaser.Physics.Matter.PointerConstraint#getBody
* @fires Phaser.Physics.Matter.Events#DRAG_START
* @since 3.16.2
*
* @return {boolean} `true` if a body was found and set, otherwise `false`.
@ -195,7 +207,7 @@ var PointerConstraint = new Class({
var pos = this.position;
var constraint = this.constraint;
pointer.camera.getWorldPoint(pointer.x, pointer.y, pos);
this.camera.getWorldPoint(pointer.x, pointer.y, pos);
var bodies = Composite.allBodies(this.world.localWorld);
@ -209,7 +221,7 @@ var PointerConstraint = new Class({
{
if (this.hitTestBody(body, pos))
{
this.world.emit(Events.DRAG_START, this.body, this.part, this);
this.world.emit(Events.DRAG_START, body, this.part, this);
return true;
}
@ -235,23 +247,20 @@ var PointerConstraint = new Class({
hitTestBody: function (body, position)
{
var constraint = this.constraint;
var partsLength = body.parts.length;
var start = (body.parts.length > 1) ? 1 : 0;
var start = (partsLength > 1) ? 1 : 0;
for (var i = start; i < body.parts.length; i++)
for (var i = start; i < partsLength; i++)
{
var part = body.parts[i];
if (Vertices.contains(part.vertices, position))
{
constraint.pointA = position;
constraint.pointB = { x: position.x - body.position.x, y: position.y - body.position.y };
constraint.bodyB = body;
constraint.pointA.x = position.x;
constraint.pointA.y = position.y;
constraint.pointB.x = position.x - body.position.x;
constraint.pointB.y = position.y - body.position.y;
constraint.angleB = body.angle;
Sleeping.set(body, false);
@ -275,33 +284,47 @@ var PointerConstraint = new Class({
*/
update: function ()
{
var body = this.body;
var pointer = this.pointer;
var body = this.body;
if (!this.active || !pointer || !body)
if (!this.active || !pointer)
{
if (body)
{
this.stopDrag();
}
return;
}
if (pointer.isDown)
if (!pointer.isDown && body)
{
this.stopDrag();
return;
}
else if (pointer.isDown)
{
if (!body && !this.getBody(pointer))
{
return;
}
body = this.body;
var pos = this.position;
var constraint = this.constraint;
this.camera.getWorldPoint(pointer.x, pointer.y, pos);
Sleeping.set(body, false);
// Drag update
constraint.pointA.x = pos.x;
constraint.pointA.y = pos.y;
Sleeping.set(body, false);
this.world.emit(Events.DRAG, body, this);
}
else
{
// Pointer has been released since the last world step
this.stopDrag();
}
},
/**
@ -320,15 +343,16 @@ var PointerConstraint = new Class({
var body = this.body;
var constraint = this.constraint;
constraint.bodyB = null;
constraint.pointB = null;
this.pointer = null;
this.body = null;
this.part = null;
if (body)
{
this.world.emit(Events.DRAG_END, body, this);
this.pointer = null;
this.body = null;
this.part = null;
constraint.bodyB = null;
}
},
@ -350,6 +374,7 @@ var PointerConstraint = new Class({
this.world.off(Events.BEFORE_UPDATE, this.update);
this.scene.sys.input.off(InputEvents.POINTER_DOWN, this.onDown, this);
this.scene.sys.input.off(InputEvents.POINTER_UP, this.onUp, this);
}
});

File diff suppressed because it is too large Load diff

View file

@ -13,7 +13,9 @@
var Collision = {
/**
* Sets the collision category of this Game Object's Matter Body. This number must be a power of two between 2^0 (= 1) and 2^31. Two bodies with different collision groups (see {@link #setCollisionGroup}) will only collide if their collision categories are included in their collision masks (see {@link #setCollidesWith}).
* Sets the collision category of this Game Object's Matter Body. This number must be a power of two between 2^0 (= 1) and 2^31.
* Two bodies with different collision groups (see {@link #setCollisionGroup}) will only collide if their collision
* categories are included in their collision masks (see {@link #setCollidesWith}).
*
* @method Phaser.Physics.Matter.Components.Collision#setCollisionCategory
* @since 3.0.0
@ -30,7 +32,10 @@ var Collision = {
},
/**
* Sets the collision group of this Game Object's Matter Body. If this is zero or two Matter Bodies have different values, they will collide according to the usual rules (see {@link #setCollisionCategory} and {@link #setCollisionGroup}). If two Matter Bodies have the same positive value, they will always collide; if they have the same negative value, they will never collide.
* Sets the collision group of this Game Object's Matter Body. If this is zero or two Matter Bodies have different values,
* they will collide according to the usual rules (see {@link #setCollisionCategory} and {@link #setCollisionGroup}).
* If two Matter Bodies have the same positive value, they will always collide; if they have the same negative value,
* they will never collide.
*
* @method Phaser.Physics.Matter.Components.Collision#setCollisionGroup
* @since 3.0.0
@ -47,7 +52,9 @@ var Collision = {
},
/**
* Sets the collision mask for this Game Object's Matter Body. Two Matter Bodies with different collision groups will only collide if each one includes the other's category in its mask based on a bitwise AND, i.e. `(categoryA & maskB) !== 0` and `(categoryB & maskA) !== 0` are both true.
* Sets the collision mask for this Game Object's Matter Body. Two Matter Bodies with different collision groups will only
* collide if each one includes the other's category in its mask based on a bitwise AND, i.e. `(categoryA & maskB) !== 0`
* and `(categoryB & maskA) !== 0` are both true.
*
* @method Phaser.Physics.Matter.Components.Collision#setCollidesWith
* @since 3.0.0
@ -74,6 +81,97 @@ var Collision = {
this.body.collisionFilter.mask = flags;
return this;
},
/**
* The callback is sent a `Phaser.Types.Physics.Matter.MatterCollisionData` object.
*
* This does not change the bodies collision category, group or filter. Those must be set in addition
* to the callback.
*
* @method Phaser.Physics.Matter.Components.Collision#setOnCollide
* @since 3.22.0
*
* @param {function} callback - The callback to invoke when this body starts colliding with another.
*
* @return {Phaser.GameObjects.GameObject} This Game Object.
*/
setOnCollide: function (callback)
{
this.body.onCollideCallback = callback;
return this;
},
/**
* The callback is sent a `Phaser.Types.Physics.Matter.MatterCollisionData` object.
*
* This does not change the bodies collision category, group or filter. Those must be set in addition
* to the callback.
*
* @method Phaser.Physics.Matter.Components.Collision#setOnCollideEnd
* @since 3.22.0
*
* @param {function} callback - The callback to invoke when this body stops colliding with another.
*
* @return {Phaser.GameObjects.GameObject} This Game Object.
*/
setOnCollideEnd: function (callback)
{
this.body.onCollideEndCallback = callback;
return this;
},
/**
* The callback is sent a `Phaser.Types.Physics.Matter.MatterCollisionData` object.
*
* This does not change the bodies collision category, group or filter. Those must be set in addition
* to the callback.
*
* @method Phaser.Physics.Matter.Components.Collision#setOnCollideActive
* @since 3.22.0
*
* @param {function} callback - The callback to invoke for the duration of this body colliding with another.
*
* @return {Phaser.GameObjects.GameObject} This Game Object.
*/
setOnCollideActive: function (callback)
{
this.body.onCollideActiveCallback = callback;
return this;
},
/**
* The callback is sent a reference to the other body, along with a `Phaser.Types.Physics.Matter.MatterCollisionData` object.
*
* This does not change the bodies collision category, group or filter. Those must be set in addition
* to the callback.
*
* @method Phaser.Physics.Matter.Components.Collision#setOnCollideWith
* @since 3.22.0
*
* @param {(MatterJS.Body|MatterJS.Body[])} body - The body, or an array of bodies, to test for collisions with.
* @param {function} callback - The callback to invoke when this body collides with the given body or bodies.
*
* @return {Phaser.GameObjects.GameObject} This Game Object.
*/
setOnCollideWith: function (body, callback)
{
if (!Array.isArray(body))
{
body = [ body ];
}
for (var i = 0; i < body.length; i++)
{
var src = (body[i].hasOwnProperty('body')) ? body[i].body : body[i];
this.body.setOnCollideWith(src, callback);
}
return this;
}

View file

@ -55,6 +55,8 @@ var Force = {
/**
* Apply thrust to the forward position of the body.
*
* Use very small values, such as 0.1, depending on the mass and required speed.
*
* @method Phaser.Physics.Matter.Components.Force#thrust
* @since 3.0.0
@ -76,6 +78,8 @@ var Force = {
/**
* Apply thrust to the left position of the body.
*
* Use very small values, such as 0.1, depending on the mass and required speed.
*
* @method Phaser.Physics.Matter.Components.Force#thrustLeft
* @since 3.0.0
@ -97,6 +101,8 @@ var Force = {
/**
* Apply thrust to the right position of the body.
*
* Use very small values, such as 0.1, depending on the mass and required speed.
*
* @method Phaser.Physics.Matter.Components.Force#thrustRight
* @since 3.0.0
@ -118,6 +124,8 @@ var Force = {
/**
* Apply thrust to the back position of the body.
*
* Use very small values, such as 0.1, depending on the mass and required speed.
*
* @method Phaser.Physics.Matter.Components.Force#thrustBack
* @since 3.0.0

View file

@ -51,6 +51,10 @@ var Mass = {
/**
* The body's center of mass.
*
* Calling this creates a new `Vector2 each time to avoid mutation.
*
* If you only need to read the value and won't change it, you can get it from `GameObject.body.centerOfMass`.
*
* @name Phaser.Physics.Matter.Components.Mass#centerOfMass
* @type {Phaser.Math.Vector2}
@ -63,7 +67,7 @@ var Mass = {
get: function ()
{
return new Vector2(this.body.render.sprite.xOffset * this.width, this.body.render.sprite.yOffset * this.height);
return new Vector2(this.body.centerOfMass.x, this.body.centerOfMass.y);
}
}

View file

@ -95,20 +95,17 @@ var SetBody = {
* @since 3.0.0
*
* @param {MatterJS.Body} body - [description]
* @param {boolean} [addToWorld=true] - [description]
* @param {boolean} [addToWorld=true] - Should the newly created body be immediately added to the World?
*
* @return {Phaser.GameObjects.GameObject} This Game Object.
*/
setExistingBody: function (body, addToWorld)
{
if (addToWorld === undefined)
{
addToWorld = true;
}
if (addToWorld === undefined) { addToWorld = true; }
if (this.body)
{
this.world.remove(this.body);
this.world.remove(this.body, true);
}
this.body = body;
@ -122,18 +119,25 @@ var SetBody = {
body.destroy = function destroy ()
{
_this.world.remove(_this.body);
_this.world.remove(_this.body, true);
_this.body.gameObject = null;
};
if (addToWorld)
{
if (this.world.has(body))
{
// Because it could be part of another Composite
this.world.remove(body, true);
}
// Only add the body if it's not already in the world
this.world.add(body);
}
if (this._originComponent)
{
this.setOrigin(body.render.sprite.xOffset, body.render.sprite.yOffset);
this.setOrigin(this.centerOffsetX, this.centerOffsetY);
}
return this;

View file

@ -187,6 +187,58 @@ var Transform = {
}
},
/**
* Returns the center x offset of the Body this Game Object is using.
*
* This is calculated by taking the difference between the center of the frame and the center of
* the physics body. If set, the `body.render.sprite.xOffset` value is then added to it.
*
* Use this when setting the Origin of a Physics Game Object post-creation, i.e.:
*
* `setOrigin(originX + centerOffsetX, originY + centerOffsetY)`
*
* @name Phaser.Physics.Matter.Components.Transform#centerOffsetX
* @type {number}
* @readonly
* @since 3.22.0
*/
centerOffsetX: {
get: function ()
{
return this.body.centerOfMass.x;
// var body = this.body;
// return body.render.sprite.xOffset + ((body.centerOfMass.x - (this.width / 2)) / this.width);
}
},
/**
* Returns the center y offset of the Body this Game Object is using.
*
* This is calculated by taking the difference between the center of the frame and the center of
* the physics body. If set, the `body.render.sprite.yOffset` value is then added to it.
*
* Use this when setting the Origin of a Physics Game Object post-creation, i.e.:
*
* `setOrigin(originX + centerOffsetX, originY + centerOffsetY)`
*
* @name Phaser.Physics.Matter.Components.Transform#centerOffsetY
* @type {number}
* @readonly
* @since 3.22.0
*/
centerOffsetY: {
get: function ()
{
return this.body.centerOfMass.y;
// var body = this.body;
// return body.render.sprite.yOffset + ((body.centerOfMass.y - (this.height / 2)) / this.height);
}
},
/**
* Sets the position of the physics body along x and y axes. Both the parameters to this function are optional and if not passed any they default to 0.
*

View file

@ -0,0 +1,28 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2019 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* @typedef {object} Phaser.Physics.Matter.Events.AfterAddEvent
*
* @property {any[]} object - An array of the object(s) that have been added. May be a single body, constraint, composite or a mixture of these.
* @property {any} source - The source object of the event.
* @property {string} name - The name of the event.
*/
/**
* The Matter Physics After Add Event.
*
* This event is dispatched by a Matter Physics World instance at the end of the process when a new Body
* or Constraint has just been added to the world.
*
* Listen to it from a Scene using: `this.matter.world.on('afteradd', listener)`.
*
* @event Phaser.Physics.Matter.Events#AFTER_ADD
* @since 3.22.0
*
* @param {Phaser.Physics.Matter.Events.AfterAddEvent} event - The Add Event object.
*/
module.exports = 'afteradd';

View file

@ -0,0 +1,28 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2019 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* @typedef {object} Phaser.Physics.Matter.Events.AfterRemoveEvent
*
* @property {any[]} object - An array of the object(s) that were removed. May be a single body, constraint, composite or a mixture of these.
* @property {any} source - The source object of the event.
* @property {string} name - The name of the event.
*/
/**
* The Matter Physics After Remove Event.
*
* This event is dispatched by a Matter Physics World instance at the end of the process when a
* Body or Constraint was removed from the world.
*
* Listen to it from a Scene using: `this.matter.world.on('afterremove', listener)`.
*
* @event Phaser.Physics.Matter.Events#AFTER_REMOVE
* @since 3.22.0
*
* @param {Phaser.Physics.Matter.Events.AfterRemoveEvent} event - The Remove Event object.
*/
module.exports = 'afterremove';

View file

@ -0,0 +1,28 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2019 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* @typedef {object} Phaser.Physics.Matter.Events.BeforeAddEvent
*
* @property {any[]} object - An array of the object(s) to be added. May be a single body, constraint, composite or a mixture of these.
* @property {any} source - The source object of the event.
* @property {string} name - The name of the event.
*/
/**
* The Matter Physics Before Add Event.
*
* This event is dispatched by a Matter Physics World instance at the start of the process when a new Body
* or Constraint is being added to the world.
*
* Listen to it from a Scene using: `this.matter.world.on('beforeadd', listener)`.
*
* @event Phaser.Physics.Matter.Events#BEFORE_ADD
* @since 3.22.0
*
* @param {Phaser.Physics.Matter.Events.BeforeAddEvent} event - The Add Event object.
*/
module.exports = 'beforeadd';

View file

@ -0,0 +1,28 @@
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2019 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
/**
* @typedef {object} Phaser.Physics.Matter.Events.BeforeRemoveEvent
*
* @property {any[]} object - An array of the object(s) to be removed. May be a single body, constraint, composite or a mixture of these.
* @property {any} source - The source object of the event.
* @property {string} name - The name of the event.
*/
/**
* The Matter Physics Before Remove Event.
*
* This event is dispatched by a Matter Physics World instance at the start of the process when a
* Body or Constraint is being removed from the world.
*
* Listen to it from a Scene using: `this.matter.world.on('beforeremove', listener)`.
*
* @event Phaser.Physics.Matter.Events#BEFORE_REMOVE
* @since 3.22.0
*
* @param {Phaser.Physics.Matter.Events.BeforeRemoveEvent} event - The Remove Event object.
*/
module.exports = 'beforeremove';

View file

@ -7,7 +7,7 @@
/**
* @typedef {object} Phaser.Physics.Matter.Events.CollisionActiveEvent
*
* @property {array} pairs - A list of all affected pairs in the collision.
* @property {Phaser.Types.Physics.Matter.MatterCollisionData[]} pairs - A list of all affected pairs in the collision.
* @property {number} timestamp - The Matter Engine `timing.timestamp` value for the event.
* @property {any} source - The source object of the event.
* @property {string} name - The name of the event.

View file

@ -7,7 +7,7 @@
/**
* @typedef {object} Phaser.Physics.Matter.Events.CollisionEndEvent
*
* @property {array} pairs - A list of all affected pairs in the collision.
* @property {Phaser.Types.Physics.Matter.MatterCollisionData[]} pairs - A list of all affected pairs in the collision.
* @property {number} timestamp - The Matter Engine `timing.timestamp` value for the event.
* @property {any} source - The source object of the event.
* @property {string} name - The name of the event.

View file

@ -7,7 +7,7 @@
/**
* @typedef {object} Phaser.Physics.Matter.Events.CollisionStartEvent
*
* @property {array} pairs - A list of all affected pairs in the collision.
* @property {Phaser.Types.Physics.Matter.MatterCollisionData[]} pairs - A list of all affected pairs in the collision.
* @property {number} timestamp - The Matter Engine `timing.timestamp` value for the event.
* @property {any} source - The source object of the event.
* @property {string} name - The name of the event.

View file

@ -10,7 +10,11 @@
module.exports = {
AFTER_ADD: require('./AFTER_ADD_EVENT'),
AFTER_REMOVE: require('./AFTER_REMOVE_EVENT'),
AFTER_UPDATE: require('./AFTER_UPDATE_EVENT'),
BEFORE_ADD: require('./BEFORE_ADD_EVENT'),
BEFORE_REMOVE: require('./BEFORE_REMOVE_EVENT'),
BEFORE_UPDATE: require('./BEFORE_UPDATE_EVENT'),
COLLISION_ACTIVE: require('./COLLISION_ACTIVE_EVENT'),
COLLISION_END: require('./COLLISION_END_EVENT'),

View file

@ -40,11 +40,10 @@ var Axes = require('../geometry/Axes');
id: Common.nextId(),
type: 'body',
label: 'Body',
gameObject: null,
parts: [],
plugin: {},
angle: 0,
vertices: Vertices.fromPath('L 0 0 L 40 0 L 40 40 L 0 40'),
vertices: null, // Phaser change: no point calling fromPath if they pass in vertices anyway
position: { x: 0, y: 0 },
force: { x: 0, y: 0 },
torque: 0,
@ -59,8 +58,6 @@ var Axes = require('../geometry/Axes');
isSensor: false,
isStatic: false,
isSleeping: false,
ignoreGravity: false,
ignorePointer: false,
motion: 0,
sleepThreshold: 60,
density: 0.001,
@ -75,18 +72,6 @@ var Axes = require('../geometry/Axes');
},
slop: 0.05,
timeScale: 1,
render: {
visible: true,
opacity: 1,
sprite: {
xScale: 1,
yScale: 1,
xOffset: 0,
yOffset: 0
},
lineWidth: 0
},
events: null,
bounds: null,
chamfer: null,
@ -94,19 +79,63 @@ var Axes = require('../geometry/Axes');
positionPrev: null,
anglePrev: 0,
parent: null,
axes: null,
area: 0,
mass: 0,
inertia: 0,
_original: null
_original: null,
render: {
visible: true,
opacity: 1,
sprite: {
xOffset: 0,
yOffset: 0
},
fillColor: null, // custom Phaser property
fillOpacity: null, // custom Phaser property
lineColor: null, // custom Phaser property
lineOpacity: null, // custom Phaser property
lineThickness: null // custom Phaser property
},
gameObject: null, // custom Phaser property
scale: { x: 1, y: 1 }, // custom Phaser property
centerOfMass: { x: 0, y: 0 }, // custom Phaser property
ignoreGravity: false, // custom Phaser property
ignorePointer: false, // custom Phaser property
onCollideCallback: null, // custom Phaser property
onCollideEndCallback: null, // custom Phaser property
onCollideActiveCallback: null, // custom Phaser property
onCollideWith: {} // custom Phaser property
};
if (!options.hasOwnProperty('position') && options.hasOwnProperty('vertices'))
{
options.position = Vertices.centre(options.vertices);
}
else if (!options.hasOwnProperty('vertices'))
{
defaults.vertices = Vertices.fromPath('L 0 0 L 40 0 L 40 40 L 0 40');
}
var body = Common.extend(defaults, options);
_initProperties(body, options);
// Helper function
body.setOnCollideWith = function (body, callback)
{
if (callback)
{
this.onCollideWith[body.id] = callback;
}
else
{
delete this.onCollideWith[body.id];
}
return this;
}
return body;
};
@ -170,13 +199,8 @@ var Axes = require('../geometry/Axes');
inertia: options.inertia || body.inertia
});
// render properties
var defaultFillStyle = (body.isStatic ? '#2e2b44' : Common.choose(['#006BA6', '#0496FF', '#FFBC42', '#D81159', '#8F2D56'])),
defaultStrokeStyle = '#000';
body.render.fillStyle = body.render.fillStyle || defaultFillStyle;
body.render.strokeStyle = body.render.strokeStyle || defaultStrokeStyle;
body.render.sprite.xOffset += -(body.bounds.min.x - body.position.x) / (body.bounds.max.x - body.bounds.min.x);
body.render.sprite.yOffset += -(body.bounds.min.y - body.position.y) / (body.bounds.max.y - body.bounds.min.y);
body.centerOfMass.x = -(body.bounds.min.x - body.position.x) / (body.bounds.max.x - body.bounds.min.x);
body.centerOfMass.y = -(body.bounds.min.y - body.position.y) / (body.bounds.max.y - body.bounds.min.y);
};
/**
@ -197,8 +221,7 @@ var Axes = require('../geometry/Axes');
}
for (property in settings) {
if (!settings.hasOwnProperty(property))
if (!Object.prototype.hasOwnProperty.call(settings, property))
continue;
value = settings[property];
@ -237,9 +260,11 @@ var Axes = require('../geometry/Axes');
case 'parts':
Body.setParts(body, value);
break;
case 'centre':
Body.setCentre(body, value);
break;
default:
body[property] = value;
}
}
};
@ -320,7 +345,7 @@ var Axes = require('../geometry/Axes');
};
/**
* Sets the moment of inertia (i.e. second moment of area) of the body of the body.
* Sets the moment of inertia (i.e. second moment of area) of the body.
* Inverse inertia is automatically updated to reflect the change. Mass is not changed.
* @method setInertia
* @param {body} body
@ -365,6 +390,7 @@ var Axes = require('../geometry/Axes');
// update geometry
Vertices.translate(body.vertices, body.position);
Bounds.update(body.bounds, body.vertices, body.velocity);
};
@ -419,18 +445,50 @@ var Axes = require('../geometry/Axes');
// sum the properties of all compound parts of the parent body
var total = Body._totalProperties(body);
// Phaser addition
var cx = total.centre.x;
var cy = total.centre.y;
body.centerOfMass.x = cx;
body.centerOfMass.y = cy;
body.area = total.area;
body.parent = body;
body.position.x = total.centre.x;
body.position.y = total.centre.y;
body.positionPrev.x = total.centre.x;
body.positionPrev.y = total.centre.y;
body.position.x = cx;
body.position.y = cy;
body.positionPrev.x = cx;
body.positionPrev.y = cy;
Body.setMass(body, total.mass);
Body.setInertia(body, total.inertia);
Body.setPosition(body, total.centre);
};
/**
* Set the centre of mass of the body.
* The `centre` is a vector in world-space unless `relative` is set, in which case it is a translation.
* The centre of mass is the point the body rotates about and can be used to simulate non-uniform density.
* This is equal to moving `body.position` but not the `body.vertices`.
* Invalid if the `centre` falls outside the body's convex hull.
* @method setCentre
* @param {body} body
* @param {vector} centre
* @param {bool} relative
*/
Body.setCentre = function(body, centre, relative) {
if (!relative) {
body.positionPrev.x = centre.x - (body.position.x - body.positionPrev.x);
body.positionPrev.y = centre.y - (body.position.y - body.positionPrev.y);
body.position.x = centre.x;
body.position.y = centre.y;
} else {
body.positionPrev.x += centre.x;
body.positionPrev.y += centre.y;
body.position.x += centre.x;
body.position.y += centre.y;
}
};
/**
* Sets the position of the body instantly. Velocity, angle, force etc. are unchanged.
* @method setPosition
@ -468,7 +526,6 @@ var Axes = require('../geometry/Axes');
Axes.rotate(part.axes, delta);
Bounds.update(part.bounds, part.vertices, body.velocity);
if (i > 0) {
part.angle += body.angularVelocity;
Vector.rotateAbout(part.position, delta, body.position, part.position);
}
}
@ -552,6 +609,9 @@ var Axes = require('../geometry/Axes');
for (var i = 0; i < body.parts.length; i++) {
var part = body.parts[i];
part.scale.x = scaleX;
part.scale.y = scaleY;
// scale vertices
Vertices.scale(part.vertices, scaleX, scaleY, point);
@ -821,6 +881,14 @@ var Axes = require('../geometry/Axes');
* @default { x: 0, y: 0 }
*/
/**
* A `Vector` that holds the current scale values as set by `Body.setScale`.
*
* @property scale
* @type vector
* @default { x: 1, y: 1 }
*/
/**
* A `Vector` that specifies the force to apply in the current step. It is zeroed after every `Body.update`. See also `Body.applyForce`.
*
@ -1117,29 +1185,6 @@ var Axes = require('../geometry/Axes');
* @type object
*/
/**
* An `String` that defines the path to the image to use as the sprite texture, if any.
*
* @property render.sprite.texture
* @type string
*/
/**
* A `Number` that defines the scaling in the x-axis for the sprite, if any.
*
* @property render.sprite.xScale
* @type number
* @default 1
*/
/**
* A `Number` that defines the scaling in the y-axis for the sprite, if any.
*
* @property render.sprite.yScale
* @type number
* @default 1
*/
/**
* A `Number` that defines the offset in the x-axis for the sprite (normalised by texture width).
*
@ -1157,30 +1202,38 @@ var Axes = require('../geometry/Axes');
*/
/**
* A `Number` that defines the line width to use when rendering the body outline (if a sprite is not defined).
* A value of `0` means no outline will be rendered.
* A hex color value that defines the fill color to use when rendering the body.
*
* @property render.lineWidth
* @property render.fillColor
* @type number
* @default 0
*/
/**
* A `String` that defines the fill style to use when rendering the body (if a sprite is not defined).
* It is the same as when using a canvas, so it accepts CSS style property values.
* A value that defines the fill opqcity to use when rendering the body.
*
* @property render.fillStyle
* @type string
* @default a random colour
* @property render.fillOpacity
* @type number
*/
/**
* A hex color value that defines the line color to use when rendering the body.
*
* @property render.lineColor
* @type number
*/
/**
* A `String` that defines the stroke style to use when rendering the body outline (if a sprite is not defined).
* It is the same as when using a canvas, so it accepts CSS style property values.
* A value that defines the line opqcity to use when rendering the body.
*
* @property render.strokeStyle
* @type string
* @default a random colour
* @property render.lineOpacity
* @type number
*/
/**
* A `Number` that defines the line width to use when rendering the body outline.
*
* @property render.lineThickness
* @type number
*/
/**
@ -1208,4 +1261,81 @@ var Axes = require('../geometry/Axes');
* @type bounds
*/
/**
* A reference to the Phaser Game Object this body belongs to, if any.
*
* @property gameObject
* @type Phaser.GameObjects.GameObject
*/
/**
* The scale of the Body when Body.setScale was called. Not used internally by Matter.
*
* @property scale
* @type vector
* @default { x: 1, y: 1 }
*/
/**
* The center of mass of the Body.
*
* @property centerOfMass
* @type vector
* @default { x: 0, y: 0 }
*/
/**
* Will this Body ignore World gravity during the Engine update?
*
* @property ignoreGravity
* @type boolean
* @default false
*/
/**
* Will this Body ignore Phaser Pointer input events?
*
* @property ignorePointer
* @type boolean
* @default false
*/
/**
* A callback that is invoked when this Body starts colliding with any other Body.
*
* You can register callbacks by providing a function of type `( pair: Matter.Pair) => void`.
*
* @property onCollideCallback
* @type function
* @default null
*/
/**
* A callback that is invoked when this Body stops colliding with any other Body.
*
* You can register callbacks by providing a function of type `( pair: Matter.Pair) => void`.
*
* @property onCollideEndCallback
* @type function
* @default null
*/
/**
* A callback that is invoked for the duration that this Body is colliding with any other Body.
*
* You can register callbacks by providing a function of type `( pair: Matter.Pair) => void`.
*
* @property onCollideActiveCallback
* @type function
* @default null
*/
/**
* A collision callback dictionary used by the `Body.setOnCollideWith` function.
*
* @property onCollideWith
* @type object
* @default null
*/
})();

View file

@ -440,8 +440,8 @@ var Body = require('./Body');
*/
Composite.rebase = function(composite) {
var objects = Composite.allBodies(composite)
.concat(Composite.allConstraints(composite))
.concat(Composite.allComposites(composite));
.concat(Composite.allConstraints(composite))
.concat(Composite.allComposites(composite));
for (var i = 0; i < objects.length; i++) {
objects[i].id = Common.nextId();

View file

@ -272,7 +272,7 @@ var Common = require('../core/Common');
*/
Grid._bucketRemoveBody = function(grid, bucket, body) {
// remove from bucket
bucket.splice(Common.indexOf(bucket, body), 1);
bucket.splice(bucket.indexOf(body), 1);
// update pair counts
for (var i = 0; i < bucket.length; i++) {

View file

@ -30,6 +30,12 @@ var Vertices = require('../geometry/Vertices');
for (var i = 0; i < bodies.length; i++) {
var bodyA = bodies[i];
// Phaser addition - skip same body checks
if (body === bodyA)
{
continue;
}
if (Bounds.overlaps(bodyA.bounds, body.bounds)) {
for (var j = bodyA.parts.length === 1 ? 0 : 1; j < bodyA.parts.length; j++) {

View file

@ -66,11 +66,14 @@ var Common = require('../core/Common');
// render
var render = {
visible: true,
lineWidth: 2,
strokeStyle: '#ffffff',
type: 'line',
anchors: true,
custom: false
lineColor: null, // custom Phaser property
lineOpacity: null, // custom Phaser property
lineThickness: null, // custom Phaser property
pinSize: null, // custom Phaser property
anchorColor: null, // custom Phaser property
anchorSize: null // custom Phaser property
};
if (constraint.length === 0 && constraint.stiffness > 0.1) {
@ -80,12 +83,6 @@ var Common = require('../core/Common');
render.type = 'spring';
}
// If the constraint has a render options set, we'll treat it as a custom override
if (constraint.hasOwnProperty('render'))
{
render.custom = true;
}
constraint.render = Common.extend(render, constraint.render);
return constraint;
@ -307,6 +304,32 @@ var Common = require('../core/Common');
}
};
/**
* Returns the world-space position of `constraint.pointA`, accounting for `constraint.bodyA`.
* @method pointAWorld
* @param {constraint} constraint
* @returns {vector} the world-space position
*/
Constraint.pointAWorld = function(constraint) {
return {
x: (constraint.bodyA ? constraint.bodyA.position.x : 0) + constraint.pointA.x,
y: (constraint.bodyA ? constraint.bodyA.position.y : 0) + constraint.pointA.y
};
};
/**
* Returns the world-space position of `constraint.pointB`, accounting for `constraint.bodyB`.
* @method pointBWorld
* @param {constraint} constraint
* @returns {vector} the world-space position
*/
Constraint.pointBWorld = function(constraint) {
return {
x: (constraint.bodyB ? constraint.bodyB.position.x : 0) + constraint.pointB.x,
y: (constraint.bodyB ? constraint.bodyB.position.y : 0) + constraint.pointB.y
};
};
/*
*
* Properties Documentation

View file

@ -257,7 +257,7 @@ module.exports = Common;
* @return {number} the current timestamp
*/
Common.now = function() {
if (window.performance) {
if (typeof window !== 'undefined' && window.performance) {
if (window.performance.now) {
return window.performance.now();
} else if (window.performance.webkitNow) {
@ -535,23 +535,4 @@ module.exports = Common;
func
));
};
/**
* Used to require external libraries outside of the bundle.
* It first looks for the `globalName` on the environment's global namespace.
* If the global is not found, it will fall back to using the standard `require` using the `moduleName`.
* @private
* @method _requireGlobal
* @param {string} globalName The global module name
* @param {string} moduleName The fallback CommonJS module name
* @return {} The loaded module
*/
Common._requireGlobal = function(globalName, moduleName) {
var obj = (typeof window !== 'undefined' ? window[globalName] : typeof global !== 'undefined' ? global[globalName] : null);
// Breaks webpack :(
// return obj || require(moduleName);
return obj;
};
})();

View file

@ -62,26 +62,6 @@ var Body = require('../body/Body');
var engine = Common.extend(defaults, options);
// @deprecated
if (element || engine.render) {
var renderDefaults = {
element: element,
controller: Render
};
engine.render = Common.extend(renderDefaults, engine.render);
}
// @deprecated
if (engine.render && engine.render.controller) {
engine.render = engine.render.controller.create(engine.render);
}
// @deprecated
if (engine.render) {
engine.render.engine = engine;
}
engine.world = options.world || World.create(engine.world);
engine.pairs = Pairs.create();
engine.broadphase = engine.broadphase.controller.create(engine.broadphase);

View file

@ -46,7 +46,7 @@ var decomp = require('../../poly-decomp');
if (options.chamfer) {
var chamfer = options.chamfer;
rectangle.vertices = Vertices.chamfer(rectangle.vertices, chamfer.radius,
chamfer.quality, chamfer.qualityMin, chamfer.qualityMax);
chamfer.quality, chamfer.qualityMin, chamfer.qualityMax);
delete options.chamfer;
}
@ -92,7 +92,7 @@ var decomp = require('../../poly-decomp');
if (options.chamfer) {
var chamfer = options.chamfer;
trapezoid.vertices = Vertices.chamfer(trapezoid.vertices, chamfer.radius,
chamfer.quality, chamfer.qualityMin, chamfer.qualityMax);
chamfer.quality, chamfer.qualityMin, chamfer.qualityMax);
delete options.chamfer;
}
@ -169,7 +169,7 @@ var decomp = require('../../poly-decomp');
if (options.chamfer) {
var chamfer = options.chamfer;
polygon.vertices = Vertices.chamfer(polygon.vertices, chamfer.radius,
chamfer.quality, chamfer.qualityMin, chamfer.qualityMax);
chamfer.quality, chamfer.qualityMin, chamfer.qualityMax);
delete options.chamfer;
}
@ -283,38 +283,9 @@ var decomp = require('../../poly-decomp');
parts[i] = Body.create(Common.extend(parts[i], options));
}
// flag internal edges (coincident part edges)
if (flagInternal) {
var coincident_max_dist = 5;
for (i = 0; i < parts.length; i++) {
var partA = parts[i];
for (j = i + 1; j < parts.length; j++) {
var partB = parts[j];
if (Bounds.overlaps(partA.bounds, partB.bounds)) {
var pav = partA.vertices,
pbv = partB.vertices;
// iterate vertices of both parts
for (k = 0; k < partA.vertices.length; k++) {
for (z = 0; z < partB.vertices.length; z++) {
// find distances between the vertices
var da = Vector.magnitudeSquared(Vector.sub(pav[(k + 1) % pav.length], pbv[z])),
db = Vector.magnitudeSquared(Vector.sub(pav[k], pbv[(z + 1) % pbv.length]));
// if both vertices are very close, consider the edge concident (internal)
if (da < coincident_max_dist && db < coincident_max_dist) {
pav[k].isInternal = true;
pbv[z].isInternal = true;
}
}
}
}
}
}
if (flagInternal)
{
Bodies.flagCoincidentParts(parts, 5);
}
if (parts.length > 1) {
@ -328,4 +299,54 @@ var decomp = require('../../poly-decomp');
}
};
/**
* Takes an array of Body objects and flags all internal edges (coincident parts) based on the maxDistance
* value. The array is changed in-place and returned, so you can pass this function a `Body.parts` property.
*
* @method flagCoincidentParts
* @param {body[]} parts - The Body parts, or array of bodies, to flag.
* @param {number} [maxDistance=5]
* @return {body[]} The modified `parts` parameter.
*/
Bodies.flagCoincidentParts = function (parts, maxDistance)
{
if (maxDistance === undefined) { maxDistance = 5; }
for (var i = 0; i < parts.length; i++)
{
var partA = parts[i];
for (var j = i + 1; j < parts.length; j++)
{
var partB = parts[j];
if (Bounds.overlaps(partA.bounds, partB.bounds))
{
var pav = partA.vertices;
var pbv = partB.vertices;
// iterate vertices of both parts
for (var k = 0; k < partA.vertices.length; k++)
{
for (var z = 0; z < partB.vertices.length; z++)
{
// find distances between the vertices
var da = Vector.magnitudeSquared(Vector.sub(pav[(k + 1) % pav.length], pbv[z]));
var db = Vector.magnitudeSquared(Vector.sub(pav[k], pbv[(z + 1) % pbv.length]));
// if both vertices are very close, consider the edge concident (internal)
if (da < maxDistance && db < maxDistance)
{
pav[k].isInternal = true;
pbv[z].isInternal = true;
}
}
}
}
}
}
return parts;
};
})();

View file

@ -217,7 +217,7 @@ var Bodies = require('./Bodies');
for (var i = 0; i < number; i++) {
var separation = 1.9,
circle = Bodies.circle(xx + i * (size * separation), yy + length, size,
{ inertia: Infinity, restitution: 1, friction: 0, frictionAir: 0.0001, slop: 1 }),
{ inertia: Infinity, restitution: 1, friction: 0, frictionAir: 0.0001, slop: 1 }),
constraint = Constraint.create({ pointA: { x: xx + i * (size * separation), y: yy }, bodyB: circle });
Composite.addBody(newtonsCradle, circle);

View file

@ -45,7 +45,8 @@ var Common = require('../core/Common');
index: i,
body: body,
isInternal: false,
contact: null
contact: null,
offset: null
};
vertex.contact = {
@ -70,7 +71,7 @@ var Common = require('../core/Common');
* @return {vertices} vertices
*/
Vertices.fromPath = function(path, body) {
var pathPattern = /L?\s*([\-\d\.e]+)[\s,]*([\-\d\.e]+)*/ig,
var pathPattern = /L?\s*([-\d.e]+)[\s,]*([-\d.e]+)*/ig,
points = [];
path.replace(pathPattern, function(match, x, y) {

View file

@ -9,7 +9,7 @@ var MatterAttractors = {
// plugin meta
name: 'matter-attractors', // PLUGIN_NAME
version: '0.1.7', // PLUGIN_VERSION
for: 'matter-js@^0.13.1',
for: 'matter-js@^0.14.2',
silent: true, // no console log please
// installs the plugin where `base` is `Matter`

View file

@ -0,0 +1,127 @@
/**
* @author @dxu https://github.com/dxu/matter-collision-events
* @author Richard Davey <rich@photonstorm.com>
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
var MatterCollisionEvents = {
name: 'matter-collision-events',
version: '0.1.6',
for: 'matter-js@^0.14.2',
silent: true,
install: function (matter)
{
matter.after('Engine.create', function ()
{
matter.Events.on(this, 'collisionStart', function (event)
{
event.pairs.map(function (pair)
{
var bodyA = pair.bodyA;
var bodyB = pair.bodyB;
if (bodyA.gameObject)
{
bodyA.gameObject.emit('collide', bodyA, bodyB, pair);
}
if (bodyB.gameObject)
{
bodyB.gameObject.emit('collide', bodyB, bodyA, pair);
}
matter.Events.trigger(bodyA, 'onCollide', { pair: pair });
matter.Events.trigger(bodyB, 'onCollide', { pair: pair });
if (bodyA.onCollideCallback)
{
bodyA.onCollideCallback(pair);
}
if (bodyB.onCollideCallback)
{
bodyB.onCollideCallback(pair);
}
if (bodyA.onCollideWith[bodyB.id])
{
bodyA.onCollideWith[bodyB.id](bodyB, pair);
}
if (bodyB.onCollideWith[bodyA.id])
{
bodyB.onCollideWith[bodyA.id](bodyA, pair);
}
});
});
matter.Events.on(this, 'collisionActive', function (event)
{
event.pairs.map(function (pair)
{
var bodyA = pair.bodyA;
var bodyB = pair.bodyB;
if (bodyA.gameObject)
{
bodyA.gameObject.emit('collideActive', bodyA, bodyB, pair);
}
if (bodyB.gameObject)
{
bodyB.gameObject.emit('collideActive', bodyB, bodyA, pair);
}
matter.Events.trigger(bodyA, 'onCollideActive', { pair: pair });
matter.Events.trigger(bodyB, 'onCollideActive', { pair: pair });
if (bodyA.onCollideActiveCallback)
{
bodyA.onCollideActiveCallback(pair);
}
if (bodyB.onCollideActiveCallback)
{
bodyB.onCollideActiveCallback(pair);
}
});
});
matter.Events.on(this, 'collisionEnd', function (event)
{
event.pairs.map(function (pair)
{
var bodyA = pair.bodyA;
var bodyB = pair.bodyB;
if (bodyA.gameObject)
{
bodyA.gameObject.emit('collideEnd', bodyA, bodyB, pair);
}
if (bodyB.gameObject)
{
bodyB.gameObject.emit('collideEnd', bodyB, bodyA, pair);
}
matter.Events.trigger(bodyA, 'onCollideEnd', { pair: pair });
matter.Events.trigger(bodyB, 'onCollideEnd', { pair: pair });
if (bodyA.onCollideEndCallback)
{
bodyA.onCollideEndCallback(pair);
}
if (bodyB.onCollideEndCallback)
{
bodyB.onCollideEndCallback(pair);
}
});
});
});
}
};
module.exports = MatterCollisionEvents;

View file

@ -9,7 +9,7 @@ var MatterWrap = {
// plugin meta
name: 'matter-wrap', // PLUGIN_NAME
version: '0.1.4', // PLUGIN_VERSION
for: 'matter-js@^0.13.1',
for: 'matter-js@^0.14.2',
silent: true, // no console log please
// installs the plugin where `base` is `Matter`

View file

@ -0,0 +1,22 @@
/**
* @typedef {object} Phaser.Types.Physics.Matter.MatterCollisionData
* @since 3.22.0
*
* @property {boolean} collided - Have the pair collided or not?
* @property {MatterJS.Body} bodyA - A reference to the first body involved in the collision.
* @property {MatterJS.Body} bodyB - A reference to the second body involved in the collision.
* @property {MatterJS.Body} axisBody - A reference to the dominant axis body.
* @property {number} axisNumber - The index of the dominant collision axis vector (edge normal)
* @property {number} depth - The depth of the collision on the minimum overlap.
* @property {MatterJS.Body} parentA - A reference to the parent of Body A, or to Body A itself if it has no parent.
* @property {MatterJS.Body} parentB - A reference to the parent of Body B, or to Body B itself if it has no parent.
* @property {vector} normal - The collision normal, facing away from Body A.
* @property {vector} tangent - The tangent of the collision normal.
* @property {vector} penetration - The penetration distances between the two bodies.
* @property {vector[]} supports - An array of support points, either exactly one or two points.
* @property {number} inverseMass - The resulting inverse mass from the collision.
* @property {number} friction - The resulting friction from the collision.
* @property {number} frictionStatic - The resulting static friction from the collision.
* @property {number} restitution - The resulting restitution from the collision.
* @property {number} slop - The resulting slop from the collision.
*/

View file

@ -0,0 +1,21 @@
/**
* @typedef {object} Phaser.Types.Physics.Matter.MatterCollisionPair
* @since 3.22.0
*
* @property {string} id - The unique auto-generated collision pair id. A combination of the body A and B IDs.
* @property {MatterJS.Body} bodyA - A reference to the first body involved in the collision.
* @property {MatterJS.Body} bodyB - A reference to the second body involved in the collision.
* @property {array} activeContacts - An array containing all of the active contacts between bodies A and B.
* @property {number} separation - The amount of separation that occured between bodies A and B.
* @property {boolean} isActive - Is the collision still active or not?
* @property {boolean} confirmedActive - Has Matter determined the collision are being active yet?
* @property {boolean} isSensor - Is either body A or B a sensor?
* @property {number} timeCreated - The timestamp when the collision pair was created.
* @property {number} timeUpdated - The timestamp when the collision pair was most recently updated.
* @property {Phaser.Types.Physics.Matter.MatterCollisionData} collision - The collision data object.
* @property {number} inverseMass - The resulting inverse mass from the collision.
* @property {number} friction - The resulting friction from the collision.
* @property {number} frictionStatic - The resulting static friction from the collision.
* @property {number} restitution - The resulting restitution from the collision.
* @property {number} slop - The resulting slop from the collision.
*/

View file

@ -8,22 +8,25 @@
* @property {boolean} [showJoint=true] - Render all world constraints to the Graphics object?
* @property {boolean} [showInternalEdges=false] - When rendering bodies, render the internal edges as well?
* @property {boolean} [showConvexHulls=false] - When rendering polygon bodies, render the convex hull as well?
* @property {boolean} [renderFill=true] - Render the bodies using a fill color.
* @property {boolean} [renderStroke=true] - Render the bodies using a line stroke.
* @property {number} [lineThickness=1] - If rendering with a stroke, the thickness of the line.
* @property {boolean} [renderFill=false] - Render the bodies using a fill color.
* @property {boolean} [renderLine=true] - Render the bodies using a line stroke.
* @property {number} [fillColor=0x106909] - The color value of the fill when rendering dynamic bodies.
* @property {number} [strokeColor=0x28de19] - The color value of the line stroke when rendering dynamic bodies.
* @property {number} [fillOpacity=1] - The opacity of the fill when rendering dynamic bodies, a value between 0 and 1.
* @property {number} [lineColor=0x28de19] - The color value of the line stroke when rendering dynamic bodies.
* @property {number} [lineOpacity=1] - The opacity of the line when rendering dynamic bodies, a value between 0 and 1.
* @property {number} [lineThickness=1] - If rendering lines, the thickness of the line.
* @property {number} [staticFillColor=0x0d177b] - The color value of the fill when rendering static bodies.
* @property {number} [staticStrokeColor=0x1327e4] - The color value of the line stroke when rendering static bodies.
* @property {number} [staticLineColor=0x1327e4] - The color value of the line stroke when rendering static bodies.
* @property {number} [staticBodySleepOpacity=0.7] - The amount to multiply the opacity of sleeping static bodies by.
* @property {number} [sleepFillColor=0x464646] - The color value of the fill when rendering sleeping dynamic bodies.
* @property {number} [sleepStrokeColor=0x999a99] - The color value of the line stroke when rendering sleeping dynamic bodies.
* @property {number} [hullColor=0xd703d0] - The color value of hulls when `showConvexHulls` is set.
* @property {number} [sleepLineColor=0x999a99] - The color value of the line stroke when rendering sleeping dynamic bodies.
* @property {number} [jointColor=0xe0e042] - The color value of joints when `showJoint` is set.
* @property {number} [jointLineOpacity=1] - The line opacity when rendering joints, a value between 0 and 1.
* @property {number} [jointLineThickness=2] - The line thickness when rendering joints.
* @property {number} [pinSize=4] - The size of the circles drawn when rendering pin constraints.
* @property {number} [pinColor=0x42e0e0] - The color value of the circles drawn when rendering pin constraints.
* @property {number} [springColor=0xe042e0] - The color value of spring constraints.
* @property {number} [anchorColor=0xefefef] - The color value of constraint anchors.
* @property {number} [anchorSize=6] - The size of the circles drawn as the constraint anchors.
* @property {number} [hullColor=0xd703d0] - The color value of hulls when `showConvexHulls` is set.
*/

View file

@ -0,0 +1,12 @@
/**
* @typedef {object} Phaser.Types.Physics.Matter.MatterRunnerConfig
* @since 3.22.0
*
* @property {boolean} [isFixed=false] - A boolean that specifies if the runner should use a fixed timestep (otherwise it is variable). If timing is fixed, then the apparent simulation speed will change depending on the frame rate (but behaviour will be deterministic). If the timing is variable, then the apparent simulation speed will be constant (approximately, but at the cost of determininism).
* @property {number} [fps=60] - A number that specifies the frame rate in seconds. If you don't specify this, but do specify `delta`, those values set the fps rate.
* @property {number} [correction=1] - A number that specifies the time correction factor to apply to the update. This can help improve the accuracy of the simulation in cases where delta is changing between updates.
* @property {number} [deltaSampleSize=60] - The size of the delta smoothing array when `isFixed` is `false`.
* @property {number} [delta=16.666] - A number that specifies the time step between updates in milliseconds. If you set the `fps` property, this value is set based on that. If `isFixed` is set to `true`, then `delta` is fixed. If it is `false`, then `delta` can dynamically change to maintain the correct apparent simulation speed.
* @property {number} [deltaMin=16.666] - A number that specifies the minimum time step between updates in milliseconds.
* @property {number} [deltaMax=33.333] - A number that specifies the maximum time step between updates in milliseconds.
*/

View file

@ -19,21 +19,18 @@
* @property {boolean} [enableSleeping=false] - A flag that specifies whether the engine should allow sleeping via the `Matter.Sleeping` module. Sleeping can improve stability and performance, but often at the expense of accuracy.
* @property {number} [timing.timestamp=0] - A `Number` that specifies the current simulation-time in milliseconds starting from `0`. It is incremented on every `Engine.update` by the given `delta` argument.
* @property {number} [timing.timeScale=1] - A `Number` that specifies the global scaling factor of time for all bodies. A value of `0` freezes the simulation. A value of `0.1` gives a slow-motion effect. A value of `1.2` gives a speed-up effect.
* @property {boolean} [plugins.attractors=false] - Should the Matter Attractor Plugin be enabled? An attractors plugin that makes it easy to apply continual forces on bodies. It's possible to simulate effects such as wind, gravity and magnetism.
* @property {boolean} [plugins.wrap=false] - Should the Matter Wrap Plugin be enabled? A coordinate wrapping plugin that automatically wraps the position of bodies such that they always stay within the given bounds. Upon crossing a boundary the body will appear on the opposite side of the bounds, while maintaining its velocity.
* @property {boolean} [plugins.collisionevents=true] - Should the Matter Collision Events Plugin be enabled?
* @property {boolean} [enabled=true] - Toggles if the world is enabled or not.
* @property {number} [correction=1] - An optional Number that specifies the time correction factor to apply to the update.
* @property {function} [getDelta] - This function is called every time the core game loop steps, which is bound to the Request Animation Frame frequency unless otherwise modified.
* @property {boolean} [autoUpdate=true] - Automatically call Engine.update every time the game steps.
* @property {(boolean|Phaser.Types.Physics.Matter.MatterDebugConfig)} [debug=false] - Sets if Matter will render to the debug Graphic overlay. As of Phaser 3.22 it should be a `MatterDebugConfig` object instead of a boolean.
* @property {boolean} [debugShowBody=true] - Should dynamic bodies be drawn to the debug graphic? Deprecated in Phaser 3.22: use a `MatterDebugConfig` object instead.
* @property {boolean} [debugShowStaticBody=true] - Should static bodies be drawn to the debug graphic? Deprecated in Phaser 3.22: use a `MatterDebugConfig` object instead.
* @property {number} [debugBodyColor=0xff00ff] - The color that dynamic body debug outlines are drawn in. Deprecated in Phaser 3.22: use a `MatterDebugConfig` object instead.
* @property {number} [debugBodyFillColor=0xe3a7e3] - The color that dynamic body debug fills are drawn in. Deprecated in Phaser 3.22: use a `MatterDebugConfig` object instead.
* @property {number} [debugStaticBodyColor=0x0000ff] - The color that static body debug outlines are drawn in. Deprecated in Phaser 3.22: use a `MatterDebugConfig` object instead.
* @property {boolean} [debugShowJoint=true] - Render joints to the debug graphic. Deprecated in Phaser 3.22: use a `MatterDebugConfig` object instead.
* @property {number} [debugJointColor=0x000000] - The color that the debug joints are drawn in. Deprecated in Phaser 3.22: use a `MatterDebugConfig` object instead.
* @property {boolean} [debugWireframes=true] - Render the debug output as wireframes. Deprecated in Phaser 3.22: use a `MatterDebugConfig` object instead.
* @property {boolean} [debugShowInternalEdges=false] - Render internal edges to the debug. Deprecated in Phaser 3.22: use a `MatterDebugConfig` object instead.
* @property {boolean} [debugShowConvexHulls=false] - Render convex hulls to the debug. Deprecated in Phaser 3.22: use a `MatterDebugConfig` object instead.
* @property {number} [debugConvexHullColor=0xaaaaaa] - The color that the debug convex hulls are drawn in, if enabled. Deprecated in Phaser 3.22: use a `MatterDebugConfig` object instead.
* @property {boolean} [debugShowSleeping=false] - Render sleeping bodies the debug. Deprecated in Phaser 3.22: use a `MatterDebugConfig` object instead.
* @property {number} [restingThresh=4] - Sets the Resolver resting threshold property.
* @property {number} [restingThreshTangent=6] - Sets the Resolver resting threshold tangent property.
* @property {number} [positionDampen=0.9] - Sets the Resolver position dampen property.
* @property {number} [positionWarming=0.8] - Sets the Resolver position warming property.
* @property {number} [frictionNormalMultiplier=5] - Sets the Resolver friction normal multiplier property.
* @property {(boolean|Phaser.Types.Physics.Matter.MatterDebugConfig)} [debug=false] - Controls the Matter Debug Rendering options. If a boolean it will use the default values, otherwise, specify a Debug Config object.
* @property {Phaser.Types.Physics.Matter.MatterRunnerConfig} [runner] - Sets the Matter Runner options.
*/

View file

@ -12,9 +12,12 @@
* @function Phaser.Utils.Array.Shuffle
* @since 3.0.0
*
* @param {array} array - The array to shuffle. This array is modified in place.
* @generic T
* @genericUse {T[]} - [array,$return]
*
* @return {array} The shuffled array.
* @param {T[]} array - The array to shuffle. This array is modified in place.
*
* @return {T[]} The shuffled array.
*/
var Shuffle = function (array)
{