1

So I`m making a game and decided to make switchable game scenes. I have one instance on Matter.Engine where I switch world param when to world parameter of current scene.

So in class "App" it looks something like this.

constructor() {
  App.Engine = Matter.Engine.create();
  Matter.Runner.run(App.Engine);
}
public static switchScene(sceneId: string): void {
        this._currentScene = this._scenes.find((scene) => scene.name == sceneId);
        App.Engine.world = this._currentScene.world;
}

And inside Scene class

this.world = Matter.World.create({} as IWorldDefinition);

CodePen example

PING_LORD
  • 11
  • 4
  • 1
    @ggorlen here is my [MVP](https://codepen.io/timuraztec/pen/abEdWRW) Try to change scene twice and you`ll see that cube drops through plate on first scene – PING_LORD Mar 17 '22 at 16:54

1 Answers1

1

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 engines).

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>
ggorlen
  • 44,755
  • 7
  • 76
  • 106