matter.js使用小記

之前一直想看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),一個是物體怎麼動起來,知道這幾個怎麼用就能寫東西了,當然我還是決定不用它來寫那個遊戲了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章