diff --git a/src/core/Engine.js b/src/core/Engine.js
index a6a3014..856e2a5 100644
--- a/src/core/Engine.js
+++ b/src/core/Engine.js
@@ -1,6 +1,6 @@
/**
* The `Matter.Engine` module contains methods for creating and manipulating engines.
-* An engine is a controller that manages updating and rendering the simulation of the world.
+* An engine is a controller that manages updating the simulation of the world.
* See `Matter.Runner` for an optional game loop utility.
*
* See [Demo.js](https://github.com/liabru/matter-js/blob/master/demo/js/Demo.js)
@@ -13,9 +13,6 @@ var Engine = {};
(function() {
- var _fps = 60,
- _delta = 1000 / _fps;
-
/**
* Creates a new engine. The options parameter is an object that specifies any properties you wish to override the defaults.
* All properties have default values, and many are pre-calculated automatically based on other properties.
@@ -32,22 +29,14 @@ var Engine = {};
element = Common.isElement(element) ? element : null;
var defaults = {
- enabled: true,
positionIterations: 6,
velocityIterations: 4,
constraintIterations: 2,
enableSleeping: false,
events: [],
timing: {
- fps: _fps,
timestamp: 0,
- delta: _delta,
- correction: 1,
- deltaMin: 1000 / _fps,
- deltaMax: 1000 / (_fps * 0.5),
- timeScale: 1,
- isFixed: false,
- frameRequestId: 0
+ timeScale: 1
},
broadphase: {
controller: Grid
@@ -82,7 +71,13 @@ var Engine = {};
};
/**
- * Moves the simulation forward in time by `delta` ms.
+ * Moves the simulation forward in time by `delta` ms.
+ * The `correction` argument is an optional `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.
+ * The value of `correction` is defined as `delta / lastDelta`, i.e. the percentage change of `delta` over the last step.
+ * Therefore the value is always `1` (no correction) when `delta` constant (or when no correction is desired, which is the default).
+ * See the paper on Time Corrected Verlet for more information.
+ *
* Triggers `beforeUpdate` and `afterUpdate` events.
* Triggers `collisionStart`, `collisionActive` and `collisionEnd` events.
* @method update
@@ -101,11 +96,10 @@ var Engine = {};
// increment timestamp
timing.timestamp += delta * timing.timeScale;
- timing.correction = correction;
// create an event object
var event = {
- timestamp: engine.timing.timestamp
+ timestamp: timing.timestamp
};
Events.trigger(engine, 'beforeUpdate', event);
@@ -204,22 +198,6 @@ var Engine = {};
return engine;
};
-
- /**
- * Renders the world by calling its defined renderer `engine.render.controller`. Triggers `beforeRender` and `afterRender` events.
- * @method render
- * @param {engine} engine
- */
- Engine.render = function(engine) {
- // create an event object
- var event = {
- timestamp: engine.timing.timestamp
- };
-
- Events.trigger(engine, 'beforeRender', event);
- engine.render.controller.world(engine);
- Events.trigger(engine, 'afterRender', event);
- };
/**
* Merges two engines by keeping the configuration of `engineA` but replacing the world with the one from `engineB`.
@@ -329,38 +307,12 @@ var Engine = {};
* @param {engine} engine
*/
- /*
- *
- * Events Documentation
- *
- */
-
- /**
- * Fired at the start of a tick, before any updates to the engine or timing
- *
- * @event beforeTick
- * @param {} event An event object
- * @param {DOMHighResTimeStamp} event.timestamp The timestamp of the current tick
- * @param {} event.source The source object of the event
- * @param {} event.name The name of the event
- */
-
- /**
- * Fired after engine timing updated, but just before engine state updated
- *
- * @event tick
- * @param {} event An event object
- * @param {DOMHighResTimeStamp} event.timestamp The timestamp of the current tick
- * @param {} event.source The source object of the event
- * @param {} event.name The name of the event
- */
-
/**
* Fired just before an update
*
* @event beforeUpdate
* @param {} event An event object
- * @param {DOMHighResTimeStamp} event.timestamp The timestamp of the current tick
+ * @param {number} event.timestamp The engine.timing.timestamp of the event
* @param {} event.source The source object of the event
* @param {} event.name The name of the event
*/
@@ -370,37 +322,7 @@ var Engine = {};
*
* @event afterUpdate
* @param {} event An event object
- * @param {DOMHighResTimeStamp} event.timestamp The timestamp of the current tick
- * @param {} event.source The source object of the event
- * @param {} event.name The name of the event
- */
-
- /**
- * Fired just before rendering
- *
- * @event beforeRender
- * @param {} event An event object
- * @param {DOMHighResTimeStamp} event.timestamp The timestamp of the current tick
- * @param {} event.source The source object of the event
- * @param {} event.name The name of the event
- */
-
- /**
- * Fired after rendering
- *
- * @event afterRender
- * @param {} event An event object
- * @param {DOMHighResTimeStamp} event.timestamp The timestamp of the current tick
- * @param {} event.source The source object of the event
- * @param {} event.name The name of the event
- */
-
- /**
- * Fired after engine update and after rendering
- *
- * @event afterTick
- * @param {} event An event object
- * @param {DOMHighResTimeStamp} event.timestamp The timestamp of the current tick
+ * @param {number} event.timestamp The engine.timing.timestamp of the event
* @param {} event.source The source object of the event
* @param {} event.name The name of the event
*/
@@ -411,7 +333,7 @@ var Engine = {};
* @event collisionStart
* @param {} event An event object
* @param {} event.pairs List of affected pairs
- * @param {DOMHighResTimeStamp} event.timestamp The timestamp of the current tick
+ * @param {number} event.timestamp The engine.timing.timestamp of the event
* @param {} event.source The source object of the event
* @param {} event.name The name of the event
*/
@@ -422,7 +344,7 @@ var Engine = {};
* @event collisionActive
* @param {} event An event object
* @param {} event.pairs List of affected pairs
- * @param {DOMHighResTimeStamp} event.timestamp The timestamp of the current tick
+ * @param {number} event.timestamp The engine.timing.timestamp of the event
* @param {} event.source The source object of the event
* @param {} event.name The name of the event
*/
@@ -433,7 +355,7 @@ var Engine = {};
* @event collisionEnd
* @param {} event An event object
* @param {} event.pairs List of affected pairs
- * @param {DOMHighResTimeStamp} event.timestamp The timestamp of the current tick
+ * @param {number} event.timestamp The engine.timing.timestamp of the event
* @param {} event.source The source object of the event
* @param {} event.name The name of the event
*/
@@ -444,14 +366,6 @@ var Engine = {};
*
*/
- /**
- * A flag that specifies whether the engine is running or not.
- *
- * @property enabled
- * @type boolean
- * @default true
- */
-
/**
* An integer `Number` that specifies the number of position iterations to perform each update.
* The higher the value, the higher quality the simulation will be at the expense of performance.
@@ -509,46 +423,13 @@ var Engine = {};
/**
* A `Number` that specifies the current simulation-time in milliseconds starting from `0`.
- * It is incremented on every `Engine.update` by the `timing.delta`.
+ * It is incremented on every `Engine.update` by the given `delta` argument.
*
* @property timing.timestamp
* @type number
* @default 0
*/
- /**
- * A `Boolean` that specifies if the `Engine.run` game loop 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 timing.isFixed
- * @type boolean
- * @default false
- */
-
- /**
- * A `Number` that specifies the time step between updates in milliseconds.
- * If `engine.timing.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 timing.delta
- * @type number
- * @default 1000 / 60
- */
-
- /**
- * A `Number` that specifies the time correction factor to apply to the current timestep.
- * It is automatically handled when using `Engine.run`, but is also only optional even if you use your own game loop.
- * The value is defined as `delta / lastDelta`, i.e. the percentage change of `delta` between steps.
- * This value is always `1` (no correction) when frame rate is constant or `engine.timing.isFixed` is `true`.
- * If the framerate and hence `delta` are changing, then correction should be applied to the current update to account for the change.
- * See the paper on Time Corrected Verlet for more information.
- *
- * @property timing.correction
- * @type number
- * @default 1
- */
-
/**
* An instance of a `Render` controller. The default value is a `Matter.Render` instance created by `Engine.create`.
* One may also develop a custom renderer module based on `Matter.Render` and pass an instance of it to `Engine.create` via `options.render`.
diff --git a/src/core/Runner.js b/src/core/Runner.js
index 68465d6..ad4091c 100644
--- a/src/core/Runner.js
+++ b/src/core/Runner.js
@@ -35,15 +35,26 @@ var Runner = {};
*/
Runner.create = function(options) {
var defaults = {
+ fps: 60,
+ correction: 1,
deltaSampleSize: 60,
counterTimestamp: 0,
frameCounter: 0,
deltaHistory: [],
timePrev: null,
- timeScalePrev: 1
+ timeScalePrev: 1,
+ frameRequestId: null,
+ isFixed: false,
+ enabled: true
};
- return Common.extend(defaults, options);
+ var runner = Common.extend(defaults, options);
+
+ runner.delta = 1000 / runner.fps;
+ runner.deltaMin = 1000 / runner.fps;
+ runner.deltaMax = 1000 / (runner.fps * 0.5);
+
+ return runner;
};
/**
@@ -55,13 +66,13 @@ var Runner = {};
// create runner if engine is first argument
if (typeof runner.positionIterations !== 'undefined') {
engine = runner;
- runner = Runner.create(engine);
+ runner = Runner.create();
}
(function render(time){
- engine.timing.frameRequestId = _requestAnimationFrame(render);
+ runner.frameRequestId = _requestAnimationFrame(render);
- if (time && engine.enabled) {
+ if (time && runner.enabled) {
Runner.tick(runner, engine, time);
}
})();
@@ -86,17 +97,18 @@ var Runner = {};
// create an event object
var event = {
- timestamp: time
+ timestamp: timing.timestamp
};
- Events.trigger(engine, 'beforeTick', event);
+ Events.trigger(runner, 'beforeTick', event);
+ Events.trigger(engine, 'beforeTick', event); // @deprecated
- if (timing.isFixed) {
+ if (runner.isFixed) {
// fixed timestep
- delta = timing.delta;
+ delta = runner.delta;
} else {
// dynamic timestep based on wall clock between calls
- delta = (time - runner.timePrev) || timing.delta;
+ delta = (time - runner.timePrev) || runner.delta;
runner.timePrev = time;
// optimistically filter delta over a few frames, to improve stability
@@ -105,14 +117,14 @@ var Runner = {};
delta = Math.min.apply(null, runner.deltaHistory);
// limit delta
- delta = delta < timing.deltaMin ? timing.deltaMin : delta;
- delta = delta > timing.deltaMax ? timing.deltaMax : delta;
+ delta = delta < runner.deltaMin ? runner.deltaMin : delta;
+ delta = delta > runner.deltaMax ? runner.deltaMax : delta;
- // time runner.correction for delta
- correction = delta / timing.delta;
+ // correction for delta
+ correction = delta / runner.delta;
// update engine timing object
- timing.delta = delta;
+ runner.delta = delta;
}
// time correction for time scaling
@@ -127,12 +139,13 @@ var Runner = {};
// fps counter
runner.frameCounter += 1;
if (time - runner.counterTimestamp >= 1000) {
- timing.fps = runner.frameCounter * ((time - runner.counterTimestamp) / 1000);
+ runner.fps = runner.frameCounter * ((time - runner.counterTimestamp) / 1000);
runner.counterTimestamp = time;
runner.frameCounter = 0;
}
- Events.trigger(engine, 'tick', event);
+ Events.trigger(runner, 'tick', event);
+ Events.trigger(engine, 'tick', event); // @deprecated
// if world has been modified, clear the render scene graph
if (engine.world.isModified
@@ -143,24 +156,143 @@ var Runner = {};
}
// update
+ Events.trigger(runner, 'beforeUpdate', event);
Engine.update(engine, delta, correction);
+ Events.trigger(runner, 'afterUpdate', event);
// render
if (engine.render) {
- Engine.render(engine);
+ Events.trigger(runner, 'beforeRender', event);
+ Events.trigger(engine, 'beforeRender', event); // @deprecated
+
+ engine.render.controller.world(engine);
+
+ Events.trigger(runner, 'afterRender', event);
+ Events.trigger(engine, 'afterRender', event); // @deprecated
}
- Events.trigger(engine, 'afterTick', event);
+ Events.trigger(runner, 'afterTick', event);
+ Events.trigger(engine, 'afterTick', event); // @deprecated
};
/**
- * Ends execution of `Runner.run` on the given `engine`, by canceling the animation frame request event loop.
+ * Ends execution of `Runner.run` on the given `runner`, by canceling the animation frame request event loop.
* If you wish to only temporarily pause the engine, see `engine.enabled` instead.
* @method stop
- * @param {engine} engine
+ * @param {runner} runner
*/
- Runner.stop = function(engine) {
- _cancelAnimationFrame(engine.timing.frameRequestId);
+ Runner.stop = function(runner) {
+ _cancelAnimationFrame(runner.frameRequestId);
};
+ /*
+ *
+ * Events Documentation
+ *
+ */
+
+ /**
+ * Fired at the start of a tick, before any updates to the engine or timing
+ *
+ * @event beforeTick
+ * @param {} event An event object
+ * @param {number} event.timestamp The engine.timing.timestamp of the event
+ * @param {} event.source The source object of the event
+ * @param {} event.name The name of the event
+ */
+
+ /**
+ * Fired after engine timing updated, but just before update
+ *
+ * @event tick
+ * @param {} event An event object
+ * @param {number} event.timestamp The engine.timing.timestamp of the event
+ * @param {} event.source The source object of the event
+ * @param {} event.name The name of the event
+ */
+
+ /**
+ * Fired at the end of a tick, after engine update and after rendering
+ *
+ * @event afterTick
+ * @param {} event An event object
+ * @param {number} event.timestamp The engine.timing.timestamp of the event
+ * @param {} event.source The source object of the event
+ * @param {} event.name The name of the event
+ */
+
+ /**
+ * Fired before update
+ *
+ * @event beforeUpdate
+ * @param {} event An event object
+ * @param {number} event.timestamp The engine.timing.timestamp of the event
+ * @param {} event.source The source object of the event
+ * @param {} event.name The name of the event
+ */
+
+ /**
+ * Fired after update
+ *
+ * @event afterUpdate
+ * @param {} event An event object
+ * @param {number} event.timestamp The engine.timing.timestamp of the event
+ * @param {} event.source The source object of the event
+ * @param {} event.name The name of the event
+ */
+
+ /**
+ * Fired before rendering
+ *
+ * @event beforeRender
+ * @param {} event An event object
+ * @param {number} event.timestamp The engine.timing.timestamp of the event
+ * @param {} event.source The source object of the event
+ * @param {} event.name The name of the event
+ */
+
+ /**
+ * Fired after rendering
+ *
+ * @event afterRender
+ * @param {} event An event object
+ * @param {number} event.timestamp The engine.timing.timestamp of the event
+ * @param {} event.source The source object of the event
+ * @param {} event.name The name of the event
+ */
+
+ /*
+ *
+ * Properties Documentation
+ *
+ */
+
+ /**
+ * A flag that specifies whether the runner is running or not.
+ *
+ * @property enabled
+ * @type boolean
+ * @default true
+ */
+
+ /**
+ * A `Boolean` that specifies if the `Engine.run` game loop 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 isFixed
+ * @type boolean
+ * @default false
+ */
+
+ /**
+ * A `Number` that specifies the time step between updates in milliseconds.
+ * If `engine.timing.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 delta
+ * @type number
+ * @default 1000 / 60
+ */
+
})();