mirror of
https://github.com/liabru/matter-js.git
synced 2024-12-24 13:29:01 -05:00
Merge branch 'master' into performance-2
* master: updated benchmark tests added repeats and updates options to test tools added Example.stress4 added arrow key navigation of examples in development demo reduce canvas hit testing in demo when using matter-tools
This commit is contained in:
commit
e4526a5138
8 changed files with 213 additions and 44 deletions
|
@ -41,8 +41,10 @@ var demo = function(examples, isDev) {
|
|||
document.title = 'Matter.js Demo' + (isDev ? ' ・ Dev' : '');
|
||||
|
||||
if (isDev) {
|
||||
var buttonSource = demo.dom.buttonSource;
|
||||
var buttonCompare = buttonSource.cloneNode(true);
|
||||
// add compare button
|
||||
var buttonSource = demo.dom.buttonSource,
|
||||
buttonCompare = buttonSource.cloneNode(true);
|
||||
|
||||
buttonCompare.textContent = '⎄';
|
||||
buttonCompare.title = 'Compare';
|
||||
buttonCompare.href = '?compare';
|
||||
|
@ -52,11 +54,29 @@ var demo = function(examples, isDev) {
|
|||
window.location = '?compare#' + demo.example.id;
|
||||
event.preventDefault();
|
||||
});
|
||||
|
||||
buttonSource.parentNode.insertBefore(buttonCompare, buttonSource.nextSibling);
|
||||
|
||||
// always show debug info
|
||||
Matter.before('Render.create', function(renderOptions) {
|
||||
renderOptions.options.showDebug = true;
|
||||
});
|
||||
|
||||
// arrow key navigation of examples
|
||||
document.addEventListener('keyup', function(event) {
|
||||
var isBackKey = event.key === 'ArrowLeft' || event.key === 'ArrowUp',
|
||||
isForwardKey = event.key === 'ArrowRight' || event.key === 'ArrowDown';
|
||||
|
||||
if (isBackKey || isForwardKey) {
|
||||
var direction = isBackKey ? -1 : 1,
|
||||
currentExampleIndex = demo.examples.findIndex(function(example) {
|
||||
return example.id === demo.example.id;
|
||||
}),
|
||||
nextExample = demo.examples[(demo.examples.length + currentExampleIndex + direction) % demo.examples.length];
|
||||
|
||||
MatterTools.Demo.setExample(demo, nextExample);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
MatterTools.Demo.start(demo);
|
||||
|
|
|
@ -47,6 +47,14 @@
|
|||
opacity: 0.5;
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 1300px) {
|
||||
/* reduce hit testing when using matter-tools */
|
||||
.matter-demo canvas {
|
||||
position: relative;
|
||||
z-index: 20;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body><% for (var chunk in htmlWebpackPlugin.files.js) { %>
|
||||
|
|
|
@ -40,6 +40,7 @@ module.exports = {
|
|||
stress: require('./stress.js'),
|
||||
stress2: require('./stress2.js'),
|
||||
stress3: require('./stress3.js'),
|
||||
stress4: require('./stress4.js'),
|
||||
svg: require('./svg.js'),
|
||||
terrain: require('./terrain.js'),
|
||||
timescale: require('./timescale.js'),
|
||||
|
|
121
examples/stress4.js
Normal file
121
examples/stress4.js
Normal file
|
@ -0,0 +1,121 @@
|
|||
var Example = Example || {};
|
||||
|
||||
Example.stress4 = function() {
|
||||
var Engine = Matter.Engine,
|
||||
Events = Matter.Events,
|
||||
Render = Matter.Render,
|
||||
Runner = Matter.Runner,
|
||||
Composites = Matter.Composites,
|
||||
Common = Matter.Common,
|
||||
MouseConstraint = Matter.MouseConstraint,
|
||||
Mouse = Matter.Mouse,
|
||||
Composite = Matter.Composite,
|
||||
Bodies = Matter.Bodies;
|
||||
|
||||
// create engine
|
||||
var engine = Engine.create({
|
||||
positionIterations: 25,
|
||||
velocityIterations: 35
|
||||
});
|
||||
|
||||
var world = engine.world;
|
||||
|
||||
// create renderer
|
||||
var render = Render.create({
|
||||
element: document.body,
|
||||
engine: engine,
|
||||
options: {
|
||||
width: 800,
|
||||
height: 600,
|
||||
showStats: true,
|
||||
showPerformance: true
|
||||
}
|
||||
});
|
||||
|
||||
Render.run(render);
|
||||
|
||||
// create runner
|
||||
var runner = Runner.create({
|
||||
isFixed: true
|
||||
});
|
||||
|
||||
Runner.run(runner, engine);
|
||||
|
||||
// add bodies
|
||||
var stack = function(scale, columns, rows) {
|
||||
return Composites.stack(40, 40, columns, rows, 0, 0, function(x, y) {
|
||||
var sides = Math.round(Common.random(1, 8));
|
||||
|
||||
switch (Math.round(Common.random(0, 1))) {
|
||||
case 0:
|
||||
if (Common.random() < 0.8) {
|
||||
return Bodies.rectangle(x, y, Common.random(25, 50) * scale, Common.random(25, 50) * scale);
|
||||
} else {
|
||||
return Bodies.rectangle(x, y, Common.random(80, 120) * scale, Common.random(25, 30) * scale);
|
||||
}
|
||||
case 1:
|
||||
return Bodies.polygon(x, y, sides, Common.random(25, 50) * scale);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
Composite.add(world, [
|
||||
stack(0.2, 61, 15),
|
||||
stack(0.3, 31, 12),
|
||||
Bodies.rectangle(400, 0, 800, 50, { isStatic: true, render: { visible: false } }),
|
||||
Bodies.rectangle(400, 600, 800, 50, { isStatic: true, render: { visible: false } }),
|
||||
Bodies.rectangle(800, 300, 50, 600, { isStatic: true, render: { visible: false } }),
|
||||
Bodies.rectangle(0, 300, 50, 600, { isStatic: true, render: { visible: false } })
|
||||
]);
|
||||
|
||||
// scene animation
|
||||
engine.timing.timeScale = 0.9;
|
||||
engine.gravity.scale = 0.0007;
|
||||
|
||||
Events.on(engine, 'beforeUpdate', function() {
|
||||
engine.gravity.x = Math.cos(engine.timing.timestamp * 0.0005);
|
||||
engine.gravity.y = Math.sin(engine.timing.timestamp * 0.0005);
|
||||
});
|
||||
|
||||
// add mouse control
|
||||
var mouse = Mouse.create(render.canvas),
|
||||
mouseConstraint = MouseConstraint.create(engine, {
|
||||
mouse: mouse,
|
||||
constraint: {
|
||||
stiffness: 0.2,
|
||||
render: {
|
||||
visible: false
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Composite.add(world, mouseConstraint);
|
||||
|
||||
// keep the mouse in sync with rendering
|
||||
render.mouse = mouse;
|
||||
|
||||
// fit the render viewport to the scene
|
||||
Render.lookAt(render, {
|
||||
min: { x: 0, y: 0 },
|
||||
max: { x: 800, y: 600 }
|
||||
});
|
||||
|
||||
// context for MatterTools.Demo
|
||||
return {
|
||||
engine: engine,
|
||||
runner: runner,
|
||||
render: render,
|
||||
canvas: render.canvas,
|
||||
stop: function() {
|
||||
Matter.Render.stop(render);
|
||||
Matter.Runner.stop(runner);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
Example.stress4.title = 'Stress 4';
|
||||
Example.stress4.for = '>=0.14.2';
|
||||
|
||||
if (typeof module !== 'undefined') {
|
||||
module.exports = Example.stress4;
|
||||
}
|
|
@ -50,16 +50,16 @@
|
|||
"lint": "eslint 'src/**/*.js' 'demo/src/**/*.js' 'examples/*.js' 'webpack.*.js'",
|
||||
"doc": "yuidoc --config yuidoc.json --project-version $npm_package_version",
|
||||
"doc-watch": "nodemon --delay 3 --watch 'matter-doc-theme' --watch src -e 'js,html,css,handlebars' --exec 'npm run doc'",
|
||||
"benchmark": "EXAMPLES=stress3 npm run test-node",
|
||||
"benchmark": "npm run test-node -- --examples=stress3,stress4 --updates=300 --repeats=3",
|
||||
"test": "npm run test-node",
|
||||
"test-node": "npm run build-dev && node --expose-gc node_modules/.bin/jest --force-exit --no-cache --runInBand ./test/Examples.spec.js",
|
||||
"test-browser": "node --expose-gc node_modules/.bin/jest --force-exit --no-cache --runInBand ./test/Browser.spec.js",
|
||||
"test-all": "npm run test-node && npm run test-browser",
|
||||
"test-save": "SAVE=true npm run test-node",
|
||||
"test-save": "npm run test-node -- --save=true",
|
||||
"test-watch": "npm run test-node -- --watch",
|
||||
"changelog": "conventional-changelog -i CHANGELOG.md -s -r",
|
||||
"release": "npm version --no-git-tag-version",
|
||||
"preversion": "git checkout master && npm run lint && SAVE=true npm run test-all",
|
||||
"preversion": "git checkout master && npm run lint && npm run test-all -- --save=true",
|
||||
"version": "git checkout -b release/$npm_package_version && npm run build"
|
||||
},
|
||||
"files": [
|
||||
|
|
|
@ -13,50 +13,57 @@ const runExample = options => {
|
|||
frameCallbacks
|
||||
} = prepareEnvironment(options);
|
||||
|
||||
const Examples = requireUncached('../examples/index');
|
||||
const example = Examples[options.name]();
|
||||
|
||||
const engine = example.engine;
|
||||
const runner = example.runner;
|
||||
const render = example.render;
|
||||
|
||||
let totalMemory = 0;
|
||||
let totalDuration = 0;
|
||||
let overlapTotal = 0;
|
||||
let overlapCount = 0;
|
||||
let i;
|
||||
|
||||
if (global.gc) {
|
||||
global.gc();
|
||||
}
|
||||
let j;
|
||||
|
||||
try {
|
||||
for (i = 0; i < options.updates; i += 1) {
|
||||
const time = i * runner.delta;
|
||||
const callbackCount = frameCallbacks.length;
|
||||
let runner;
|
||||
let engine;
|
||||
let render;
|
||||
|
||||
for (let p = 0; p < callbackCount; p += 1) {
|
||||
totalMemory += process.memoryUsage().heapUsed;
|
||||
const callback = frameCallbacks.shift();
|
||||
const startTime = process.hrtime();
|
||||
|
||||
callback(time);
|
||||
|
||||
const duration = process.hrtime(startTime);
|
||||
totalMemory += process.memoryUsage().heapUsed;
|
||||
totalDuration += duration[0] * 1e9 + duration[1];
|
||||
for (i = 0; i < options.repeats; i += 1) {
|
||||
if (global.gc) {
|
||||
global.gc();
|
||||
}
|
||||
|
||||
const pairsList = engine.pairs.list;
|
||||
const pairsListLength = engine.pairs.list.length;
|
||||
const Examples = requireUncached('../examples/index');
|
||||
const example = Examples[options.name]();
|
||||
|
||||
for (let p = 0; p < pairsListLength; p += 1) {
|
||||
const pair = pairsList[p];
|
||||
const separation = pair.separation - pair.slop;
|
||||
runner = example.runner;
|
||||
engine = example.engine;
|
||||
render = example.render;
|
||||
|
||||
for (j = 0; j < options.updates; j += 1) {
|
||||
const time = j * runner.delta;
|
||||
const callbackCount = frameCallbacks.length;
|
||||
|
||||
if (pair.isActive && !pair.isSensor) {
|
||||
overlapTotal += separation > 0 ? separation : 0;
|
||||
overlapCount += 1;
|
||||
for (let p = 0; p < callbackCount; p += 1) {
|
||||
totalMemory += process.memoryUsage().heapUsed;
|
||||
const callback = frameCallbacks.shift();
|
||||
const startTime = process.hrtime();
|
||||
|
||||
callback(time);
|
||||
|
||||
const duration = process.hrtime(startTime);
|
||||
totalMemory += process.memoryUsage().heapUsed;
|
||||
totalDuration += duration[0] * 1e9 + duration[1];
|
||||
}
|
||||
|
||||
const pairsList = engine.pairs.list;
|
||||
const pairsListLength = engine.pairs.list.length;
|
||||
|
||||
for (let p = 0; p < pairsListLength; p += 1) {
|
||||
const pair = pairsList[p];
|
||||
const separation = pair.separation - pair.slop;
|
||||
|
||||
if (pair.isActive && !pair.isSensor) {
|
||||
overlapTotal += separation > 0 ? separation : 0;
|
||||
overlapCount += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -75,7 +82,7 @@ const runExample = options => {
|
|||
};
|
||||
|
||||
} catch (err) {
|
||||
err.message = `On example '${options.name}' update ${i}:\n\n ${err.message}`;
|
||||
err.message = `On example '${options.name}' update ${j}:\n\n ${err.message}`;
|
||||
throw err;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -10,7 +10,8 @@ const {
|
|||
comparisonReport,
|
||||
logReport,
|
||||
toMatchExtrinsics,
|
||||
toMatchIntrinsics
|
||||
toMatchIntrinsics,
|
||||
getArg
|
||||
} = require('./TestTools');
|
||||
|
||||
const Example = requireUncached('../examples/index');
|
||||
|
@ -18,9 +19,11 @@ const MatterBuild = requireUncached('../build/matter');
|
|||
const { versionSatisfies } = requireUncached('../src/core/Plugin');
|
||||
const Worker = require('jest-worker').default;
|
||||
|
||||
const specificExamples = process.env.EXAMPLES ? process.env.EXAMPLES.split(' ') : null;
|
||||
const testComparison = process.env.COMPARE === 'true';
|
||||
const saveComparison = process.env.SAVE === 'true';
|
||||
const testComparison = getArg('compare', null) === 'true';
|
||||
const saveComparison = getArg('save', null) === 'true';
|
||||
const specificExamples = getArg('examples', null, (val) => val.split(','));
|
||||
const repeats = getArg('repeats', 1, parseFloat);
|
||||
const updates = getArg('updates', 150, parseFloat);
|
||||
|
||||
const excludeExamples = ['svg', 'terrain'];
|
||||
const excludeJitter = ['stack', 'circleStack', 'restitution', 'staticFriction', 'friction', 'newtonsCradle', 'catapult'];
|
||||
|
@ -42,6 +45,7 @@ const captureExamples = async useDev => {
|
|||
name,
|
||||
useDev,
|
||||
updates: 2,
|
||||
repeats: 1,
|
||||
stableSort: true,
|
||||
jitter: excludeJitter.includes(name) ? 0 : 1e-10
|
||||
})));
|
||||
|
@ -50,6 +54,7 @@ const captureExamples = async useDev => {
|
|||
name,
|
||||
useDev,
|
||||
updates: 2,
|
||||
repeats: 1,
|
||||
stableSort: true,
|
||||
jitter: excludeJitter.includes(name) ? 0 : 1e-10
|
||||
})));
|
||||
|
@ -58,6 +63,7 @@ const captureExamples = async useDev => {
|
|||
name,
|
||||
useDev,
|
||||
updates: 2,
|
||||
repeats: 1,
|
||||
stableSort: false,
|
||||
jitter: excludeJitter.includes(name) ? 0 : 1e-10
|
||||
})));
|
||||
|
@ -72,7 +78,8 @@ const captureExamples = async useDev => {
|
|||
const completeRuns = await Promise.all(examples.map(name => singleThreadWorker.runExample({
|
||||
name,
|
||||
useDev,
|
||||
updates: 150,
|
||||
updates: updates,
|
||||
repeats: repeats,
|
||||
stableSort: false,
|
||||
jitter: excludeJitter.includes(name) ? 0 : 1e-10
|
||||
})));
|
||||
|
|
|
@ -254,6 +254,11 @@ const requireUncached = path => {
|
|||
return module;
|
||||
};
|
||||
|
||||
const getArg = (name, defaultValue=null, parser=(v) => v) => {
|
||||
const value = process.argv.find(arg => arg.startsWith(`--${name}=`));
|
||||
return value ? parser(value.split('=')[1]) : defaultValue;
|
||||
};
|
||||
|
||||
const toMatchExtrinsics = {
|
||||
toMatchExtrinsics(received, value) {
|
||||
const similaritys = extrinsicSimilarity(received, value, 'extrinsic');
|
||||
|
@ -286,6 +291,6 @@ const toMatchIntrinsics = {
|
|||
};
|
||||
|
||||
module.exports = {
|
||||
requireUncached, comparisonReport, logReport,
|
||||
requireUncached, comparisonReport, logReport, getArg,
|
||||
serialize, toMatchExtrinsics, toMatchIntrinsics
|
||||
};
|
Loading…
Reference in a new issue