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