当前位置: 首页 > 工具软件 > Matter.js > 使用案例 >

matter.js使用小记

欧阳德运
2023-12-01

之前一直想看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),一个是物体怎么动起来,知道这几个怎么用就能写东西了,当然我还是决定不用它来写那个游戏了。

 类似资料: