首页 > 解决方案 > 如何完全停止/重置/重新初始化 Matter.js canvas/world/engine/instance

问题描述

我在屏幕上有一个 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);
}

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

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

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

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

是我找到方法建议的地方World.clearEngine.clear它可以从当前画布中删除所有元素。

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

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

标签: javascriptmatter.js

解决方案


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

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

特别是RenderRunner类方法/属性清除。您必须停止它们,然后删除render自身并清除两者的其他属性renderrunner

需要注意的一件非常重要的事情是,我必须全局声明engineworldrenderrunner,然后在createMaze函数中分配它们。

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

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


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

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


推荐阅读