如何完全停止/重置/重新初始化 Matter.js canvas/world/engine/instance

R G*_*eet 3 javascript matter.js

我在屏幕上有一个 Matter.js 实例,例如游戏,并且希望在用户/玩家单击“新游戏”按钮时从头开始:

const { Engine, Render, Runner, World, Bodies, Mouse, MouseConstraint, Body, Events } = Matter;

    //movement setup
    const engine = Engine.create();
    const { world } = engine;

    let render;
    let runner;

const startGame = document.querySelector('#start');
startGame.addEventListener('click', event => {

    event.preventDefault();

    //hide 'choose difficulty' 
    const chooseDifficulty = document.querySelector('.options');
    chooseDifficulty.classList.add('hidden');

    //get selected difficulty
    const difficulty = document.querySelector('input[name=difficulty]:checked').value;

    //set number of horizontal/vertical cells based on difficulty selected
    switch(difficulty) {
        case 'easy':
            cellsHorizontal = 6;
            cellsVertical = 4;
            break;
        case 'medium':
            cellsHorizontal = 14;
            cellsVertical = 10;
            break;
        case 'hard':
            cellsHorizontal = 25;
            cellsVertical = 15;
            break;
    }

    createMaze();
});

const createMaze = () => {
        //show controls
        // document.querySelector('.controls').classList.remove('hidden');
        console.log(document.querySelector('.controls').scrollHeight)
        //set size of movement.js canvas/world
        const worldWidth = document.querySelector('.canvas').scrollWidth;
        const worldHeight = document.querySelector('.canvas').scrollHeight;

        console.log(document.querySelector('.canvas').scrollHeight)
        console.log(worldHeight);

        //length of one side of one cell
        const unitLengthX = worldWidth/cellsHorizontal;
        const unitLengthY = worldHeight/cellsVertical;

        //disable gravity & render the world
        engine.world.gravity.y = 0;
        world.gravity.x = 0;
        render = Render.create({
            element: document.querySelector('.canvas'),
            engine: engine,
            options: {
                width:worldWidth,
                height:worldHeight,
                wireframes:false
            }
        });

        Render.run(render);
        runner = Runner.create();
        Runner.run(runner, engine);

        //Outer edges
        const edges = [
            /*top*/Bodies.rectangle((worldWidth/2),0,worldWidth,5, {isStatic:true}),
            /*bottom*/Bodies.rectangle((worldWidth/2),worldHeight,worldWidth,5, {isStatic:true}),
            /*left*/Bodies.rectangle(0,(worldHeight/2),5,worldHeight, {isStatic:true}),
            /*right*/Bodies.rectangle(worldWidth,(worldHeight/2),5,worldHeight, {isStatic:true})
        ];

        World.add(world, edges);
}
Run Code Online (Sandbox Code Playgroud)

这会.canvas在页面上的 div内创建一个画布,该画布占据整个屏幕,外面有实心边缘,因此主体不能从任何方向掉落。

在这个例子中(这里不包括),我创建了一个随机迷宫,以一个矩形为目标,一个圆形使用 WASD 或箭头键移动,以及一个事件处理程序,用于这两者之间的碰撞,它之前弹出一个z-index 为 1 的隐藏 div 位于地图顶部,其中包含一个“重新开始”按钮,单击该按钮时,会将玩家带回难度选择,然后他们可以生成一个全新的迷宫。

这是“重新开始”按钮的代码,我想在提供选择难度和创建新迷宫的选项之前清除整个物质实例/画布/世界/引擎:

button.addEventListener('click', event => {
            event.preventDefault();
            World.clear(world);
            Engine.clear(engine);
            console.log('reset clicked');
            document.querySelector('.winner').classList.add('hidden');
            document.querySelector('.options').classList.remove('hidden');
        });
Run Code Online (Sandbox Code Playgroud)

在这里,我找到了World.clearEngine.clear方法建议,这有助于从当前画布中删除所有元素。

然而,我遇到的是,当玩家选择一个新难度并单击“开始”按钮时,world会在现有的旧画布旁边/下方创建一个全新的画布,现在是空的画布。

如何摆脱旧画布以完全重新初始化?

R G*_*eet 5

我想文档假设开发人员可以将文档中的两个和两个放在一起以解决这个问题,但是我花了几个小时才找到/弄清楚我需要将一篇文章与最初引用的文章结合起来才能得到这个对于“重新开始”按钮事件:

button.addEventListener('click', event => {
            event.preventDefault();
            World.clear(world);
            Engine.clear(engine);
            Render.stop(render);
            Runner.stop(runner);
            render.canvas.remove();
            render.canvas = null;
            render.context = null;
            render.textures = {};
            console.log('reset clicked');
            document.querySelector('.winner').classList.add('hidden');
            document.querySelector('.options').classList.remove('hidden');
        });
Run Code Online (Sandbox Code Playgroud)

特别是RenderRunner类方法/属性清除。你必须停止他们两个,然后取出render本身并清除两个其他属性renderrunner

需要注意的一个非常重要的事情是,我不得不宣布engineworldrender,和runner全球范围内,然后在将它们分配createMaze功能。

同样重要的是,正如我在另一篇文章中发现的(现在找不到它的位置),如果您不停止Runner,则每次重新创建画布时运行器/动画都会变得更快。

该函数最初在加载时运行,然后在使用“重新开始”按钮清除世界/画布后再次运行,因此这些变量需要是全局的。


我必须诚实并承认 1) 我是新手,在初始化/重新初始化方面知识渊博/实践不足,以及 2) 我在阅读文档方面不是最好/最彻底的,所以这在某处可能很明显我只是没有花时间去找到它。

老实说,我一直相信没有人会完全阅读有关他们使用的所有内容的文档,对吗?也许我刚刚看到太多“成为开发人员意味着整天从 stackoverflow 粘贴”的模因。