engine.world = scenes[sceneIndex].world;
is a good attempt, but even though this is a public property, I haven't seen setting it directly done before. It appears to be bypassing the API and corrupting the engine's state. Feel free to correct me if I'm wrong, and I'll update this if I find out more definitive information.
In the meantime, if your design supports it, I'd suggest an approach like the MJS demo page and give each scene its own engine, and possibly renderer and canvas as well (the renderer and runner are intended for demos, so you'd probably have a custom rendering solution that uses MJS headlessly). The demo resets state per scene whenever you change to a different one, but you can pause the scene and restart it as shown below using runner.enabled
, or if you're running headlessly, switching between different engine
objects specific to a scene in your Matter.Engine.update(engine);
call (or pausing/resuming separate animation loops with their own update
calls and engine
s).
const sceneEl = document.querySelector("#scenes");
const makeScene = () => {
const engine = Matter.Engine.create();
const el = document.createElement("div");
el.style.display = "none";
sceneEl.appendChild(el);
const runner = Matter.Runner.create();
const render = Matter.Render.create({
element: el,
engine,
options: {height: 180, width: 400, wireframes: false}
});
Matter.Runner.start(runner, engine);
runner.enabled = false;
const run = () => {
el.style.display = "block";
runner.enabled = true;
Matter.Render.run(render);
};
const stop = () => {
el.style.display = "none";
runner.enabled = false;
Matter.Render.stop(render);
};
const clearBodies = () =>
Matter.Composite.clear(engine.world)
;
const addBodies = () => {
const fillStyle = `hsl(${Math.random() * 360}, 80%, 30%)`;
Matter.Composite.add(engine.world, [
Matter.Bodies.rectangle(
200, 200, 400, 60, {
isStatic: true,
angle: 0,
},
),
...Array(50).fill().map(() =>
Matter.Bodies.rectangle(
Math.random() * 400, 0,
Math.random() * 30 + 10,
Math.random() * 30 + 10, {
frictionAir: 0.7,
render: {
fillStyle,
strokeStyle: "white",
lineWidth: 3
},
}
)
),
]);
};
addBodies();
return {addBodies, clearBodies, run, stop};
};
const scenes = [...Array(3)].map(makeScene);
document.querySelector("#current-scene")
.textContent = `Scene 1 of ${scenes.length}`
;
let currentScene = 0;
scenes[currentScene].run();
document
.querySelector("#randomize-scene")
.addEventListener("click", () => {
scenes[currentScene].clearBodies();
scenes[currentScene].addBodies();
})
;
document
.querySelector("#next-scene")
.addEventListener("click", () => {
scenes[currentScene].stop();
currentScene = (currentScene + 1) % scenes.length;
scenes[currentScene].run();
document.querySelector("#current-scene")
.textContent = `Scene ${1 + currentScene} of ${scenes.length}`
;
})
;
<script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.19.0/matter.min.js"></script>
<div>
<span id="current-scene">loading...</span>
<button id="next-scene">Next scene</button>
<button id="randomize-scene">Randomize scene</button>
</div>
<div id="scenes"></div>