之前一直想看box2d,后面发现了matter.js,听说文档比较全面,稍微看了下也没觉得有多全面(),拖了很久才来写了个相对完整的例子,记录一下。
先说下整体感觉,使用的时候发现了一些bug(也可能是我使用姿势不对),性能不是太好,文档形式是API加demo,有些功能需要自己尝试,建议把官方demo都看一遍,试一试。并且因为是个物理引擎,如果用来写游戏,有些你想要不遵守物理法则的时候就得想点办法绕过去,还是有点麻烦,其实很多情况下应该用不到的。
还是代码加注释的形式吧,比较方便查看。html文件只有在body里面引入了下面这些代码和matter.js的代码,没别的。
const { Engine, Render, Bodies, World, Runner, Events } = Matter;
// 创建一个engine实例
const engine = Engine.create();
// 设置当前的重力为1,这个具体我没细看,我估计是指1个标准重力
engine.world.gravity.y = 1;
const options = {
width: 800,
height: 600,
// showAngleIndicator: true, // 显示物体的角度
wireframes: false, // 线框模式,这里选择关闭,线框模式适合调试用
background: "#fff"
};
// 创建一个render实例,绑定到body上面
// 应该也可以绑到子元素上,不过我没试
const render = Render.create({
element: document.body,
engine: engine,
options: options
});
Engine.run(engine);
Render.run(render);
const world = engine.world;
// world在这里是一个物体集合的角色,
World.add(world, [
// 添加四面墙,这个是官方例子里的,虽然这个墙好像不够墙,
// 经常发现物体穿过去,不知道是不是我的使用姿势有问题
Bodies.rectangle(400, 0, 800, 50, { isStatic: true }),
Bodies.rectangle(400, 600, 800, 50, { isStatic: true }),
Bodies.rectangle(800, 300, 50, 600, { isStatic: true }),
Bodies.rectangle(0, 300, 50, 600, { isStatic: true })
]);
// 创建一个长方形
let rect = Bodies.rectangle(200, 550, 150, 20, {
restitution: 0, // 刚度?弹性?
friction: 0, // 摩擦力,这个指的好像是动摩擦力,下面那个是静摩擦力,还有一个空气摩擦力
frictionStatic: 0,
render: {
fillStyle: "#f11" // 填充的颜色
// sprite: { // 设置图片,在texture属性上设置一个图片路径就可以了
// texture: "https://csdnimg.cn/cdn/content-toolbar/csdn-write.png"
// }
}
});
// 这个球打算动态添加,所以这里还没有创建的代码,下面有
let circle = null;
World.add(world, [rect]); // 要添加到world里面
// 检测是否有碰撞事件发生,还有很多事件可以检测,不过我没找到事件列表
Events.on(engine, "collisionActive", function(event) {
if (circle) {
// 查询长方形和球是否有碰撞,如果有就打印一下,
// 我开始使用的是循环查询所有pairs,看body的id是否和长方形和球相等,发现有点问题
const pairs = Matter.Query.collides(rect, [circle]);
if (pairs.length > 0) {
console.log(pairs);
}
}
});
document.addEventListener("keydown", e => {
const { x: posX, y: posY } = rect.position;
// 打印rect信息,这个信息比较全面,比自己打console强
// Matter.Common.info(rect);
// 按下d
if (e.keyCode === 68) {
// 给长方形一个速度,也可以给一个力,不过给一个力好像是个挺耗性能的操作?
Matter.Body.setVelocity(rect, { x: 15, y: 0 });
}
// 按下a
if (e.keyCode === 65) {
Matter.Body.setVelocity(rect, { x: -15, y: 0 });
}
// 按下j
if (e.keyCode === 74) {
if (circle) {
// 如果球已经创建了,我们就拿掉它
World.remove(world, [circle]);
circle = null;
} else {
// 创建球,并且添加到world里面,还给球一个初速度
circle = Bodies.circle(posX, posY - 25, 5, {
restitution: 1,
friction: 0,
frictionAir: 0,
frictionStatic: 0,
mass: 0,
render: {
fillStyle: "#000"
}
});
World.add(world, [circle]);
Matter.Body.setVelocity(circle, { x: 20, y: -20 });
}
}
});
本来是为了写一个小游戏玩,结果发现性能不达标而且有bug,球经常穿过墙(),个人觉得比较重要的几个地方,一个是碰撞检测的地方,一个是物体怎么渲染的(就是绑定sprite),一个是物体怎么动起来,知道这几个怎么用就能写东西了,当然我还是决定不用它来写那个游戏了。