0
0
Fork 0
mirror of https://github.com/liabru/matter-js.git synced 2024-11-27 09:50:52 -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:
liabru 2023-08-13 14:11:28 +01:00
commit e4526a5138
8 changed files with 213 additions and 44 deletions

View file

@ -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);

View file

@ -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) { %>

View file

@ -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
View 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;
}

View file

@ -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": [

View file

@ -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;
if (pair.isActive && !pair.isSensor) {
overlapTotal += separation > 0 ? separation : 0;
overlapCount += 1;
for (j = 0; j < options.updates; j += 1) {
const time = j * runner.delta;
const callbackCount = frameCallbacks.length;
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;
}
};

View file

@ -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
})));

View file

@ -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
};