javascript - 如何完全停止/重置/重新初始化 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.clear
,Engine.clear
它可以从当前画布中删除所有元素。
然而我遇到的是,当玩家选择一个新的难度并点击“开始”按钮时,一个全新的画布world
被创建在现有的画布旁边/下面,现在是空的旧画布。
如何摆脱旧画布以完全重新初始化?
解决方案
我猜文档假设开发人员可以将文档中的两个和两个放在一起以弄清楚这一点,但是我花了几个小时才找到/弄清楚我需要将另一篇文章与最初引用的文章结合起来以获得这个对于“重新开始”按钮事件:
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');
});
特别是Render
和Runner
类方法/属性清除。您必须停止它们,然后删除render
自身并清除两者的其他属性render
和runner
。
需要注意的一件非常重要的事情是,我必须全局声明engine
、world
、render
和runner
,然后在createMaze
函数中分配它们。
同样重要的是,正如我在另一篇文章中发现的那样(找不到现在的位置),如果您不停止Runner
,则每次重新创建画布时,跑步者/动画都会变得更快。
该函数最初在加载时运行,然后在使用“重新开始”按钮清除世界/画布后再次运行,因此这些变量需要是全局的。
老实说,我必须承认 1)我是新手,在初始化/重新初始化方面不是知识渊博/实践过,2)我在阅读文档方面不是最好/最彻底的,所以这可能在某处很明显我只是没有花时间找到它。
老实说,我一直相信没有人会完全阅读他们使用的所有内容的文档,对吗?也许我刚刚看到太多“作为开发人员意味着整天从 stackoverflow 粘贴”的模因。
推荐阅读
- dpdk - 运行 dpdk testpmd 时显示“链接状态:关闭”
- bootstrap-4 - Bootstrap 安装弄乱了我在 SCSS 中的菜单
- python - 在 python 上画线的问题
- r - 将向量传递给 httr2 req_headers()
- reactjs - 嘿,我遇到了关于 git 和 heroku 的问题
- javascript - 如何将 tiff.js 导入我的 Vue 项目?
- c# - 为什么我得到这个错误没有足够的内存资源来处理这个命令?
- python - 如何将数组从串口保存到 arduino(保存在 EEPROM 存储器中)
- assembly - 错误的装配逻辑?
- python - 删除使用合并数据框创建的列