在 Matter.js 中,物体之间的碰撞和交互是物理模拟中的关键组成部分。本教程将详细介绍如何处理物体间的力和碰撞、设置边界、以及实现用户与物体的交互。
世界中的力与碰撞
力的作用
在物理模拟中,力是影响物体运动的关键因素。Matter.js 提供了多种方式来施加力,如重力、摩擦力和手动施加的力。
设置重力
引擎默认会有一个模拟地球重力的效果,但你可以通过引擎的 gravity
属性自定义重力。例如,关闭重力或设置水平方向的重力:
js
// 关闭重力
engine.world.gravity.y = 0;
// 设置水平方向的重力
engine.world.gravity.x = 0.1;
施加力
使用 Body.applyForce()
可以向物体施加力。该函数需要指定三个参数:物体、力作用的点以及力的大小。例如,模拟物体受到风的影响:
js
// 向物体施加一个向右的力
Matter.Body.applyForce(ball, { x: ball.position.x, y: ball.position.y }, { x: 0.05, y: 0 });
在这个示例中,ball
是一个物体,{ x: 0.05, y: 0 }
表示力的大小和方向。x
轴正方向上的力将使物体向右移动。
摩擦力与空气阻力
摩擦力和空气阻力是阻止物体无限运动的因素。你可以通过调整刚体的 friction
和 frictionAir
来改变这些阻力的影响。
摩擦力
friction
用于模拟物体与接触表面之间的摩擦,数值越大,物体移动越慢。默认值是 0.1
。
js
// 增加摩擦力
const box = Bodies.rectangle(200, 200, 50, 50, {
friction: 0.5
});
World.add(engine.world, box);
空气阻力
frictionAir
用于模拟空气阻力的影响。默认值为 0.01
,较大的值会显著降低物体的移动速度:
js
const ball = Bodies.circle(300, 100, 50, {
frictionAir: 0.05
});
World.add(engine.world, ball);
碰撞检测与事件处理
Matter.js 会自动处理物体间的碰撞。你还可以监听碰撞事件,通过自定义逻辑来处理碰撞结果。
基本碰撞检测
Matter.js 会根据物体的形状、速度等因素计算碰撞。碰撞后的结果包括物体的反弹和物体相对位置的调整。默认情况下,碰撞后的物体会按照物理规则反弹或停止。
处理碰撞事件
你可以监听特定的碰撞事件,例如物体开始碰撞、碰撞中、或碰撞结束:
js
Matter.Events.on(engine, 'collisionStart', function(event) {
const pairs = event.pairs;
pairs.forEach(pair => {
const { bodyA, bodyB } = pair;
console.log('Collision between:', bodyA.label, bodyB.label);
});
});
collisionStart
事件触发时,会提供一组 pairs
,每对 pair
包含两个物体 (bodyA
和 bodyB
),表示它们发生了碰撞。你可以根据这些信息执行其他操作,比如播放音效或改变物体颜色。
世界边界与限制
设置世界边界
为了防止物体掉出屏幕,我们可以为物理世界设置边界。这通常通过创建不可移动的墙壁或边界物体来实现。
创建边界
使用 Bodies.rectangle()
可以在世界四周创建边界,防止物体越界。例如,创建地板、左右墙壁和天花板:
js
const ground = Bodies.rectangle(400, 600, 810, 60, { isStatic: true });
const leftWall = Bodies.rectangle(0, 300, 60, 600, { isStatic: true });
const rightWall = Bodies.rectangle(800, 300, 60, 600, { isStatic: true });
const ceiling = Bodies.rectangle(400, 0, 810, 60, { isStatic: true });
World.add(engine.world, [ground, leftWall, rightWall, ceiling]);
isStatic: true
表示这些物体是静态的,不会受到重力或碰撞的影响。
限制物体运动
有时候,我们希望物体只能在特定区域内活动。Matter.js 提供了 Bounds
对象,用于定义物体可以活动的范围。
限制物体在画布内移动
可以通过监听物体的位置,并在其超过边界时将其移回画布内:
js
Matter.Events.on(engine, 'beforeUpdate', function() {
World.bodies.forEach(body => {
if (body.position.x < 0 || body.position.x > 800) {
Matter.Body.setPosition(body, { x: Math.max(0, Math.min(800, body.position.x)), y: body.position.y });
}
if (body.position.y < 0 || body.position.y > 600) {
Matter.Body.setPosition(body, { x: body.position.x, y: Math.max(0, Math.min(600, body.position.y)) });
}
});
});
用户交互
Matter.js 允许通过鼠标或触摸设备与物体交互。这使得我们可以实现拖拽、点击和其他交互行为。
拖拽物体
Matter.js 提供了 MouseConstraint
,它允许用户通过鼠标拖拽物体。
添加鼠标控制
首先,引入 MouseConstraint
并将其添加到世界中:
js
const mouse = Matter.Mouse.create(render.canvas);
const mouseConstraint = Matter.MouseConstraint.create(engine, {
mouse: mouse,
constraint: {
stiffness: 0.2,
render: {
visible: false
}
}
});
World.add(engine.world, mouseConstraint);
// 使渲染器跟随鼠标
render.mouse = mouse;
这个代码会创建一个鼠标约束,使用户能够点击并拖拽物体。stiffness
控制拖拽的弹性,render.visible
设置为 false
,意味着不会显示约束线。
点击与其他交互
除了拖拽物体,我们还可以监听鼠标点击事件,并做出相应反应。例如,点击时改变物体的颜色:
js
Matter.Events.on(mouseConstraint, 'mousedown', function(event) {
const mousePosition = event.mouse.position;
const clickedBodies = Matter.Query.point(World.bodies, mousePosition);
if (clickedBodies.length > 0) {
clickedBodies.forEach(body => {
body.render.fillStyle = '#ff0000';
});
}
});
在这个示例中,当用户点击某个物体时,物体的颜色会变成红色。
触摸交互
Matter.js 支持触摸屏设备的交互。你可以使用相同的 MouseConstraint
来处理触摸事件。触摸设备会被识别为鼠标输入设备,因此不需要额外配置。
总结
在本教程中,我们学习了如何在 Matter.js 中处理物体的力和碰撞,如何创建边界防止物体掉出屏幕,以及如何通过鼠标或触摸设备与物体交互。通过这些技术,你可以创建丰富的交互式物理模拟。
继续深入学习 Matter.js 的其他功能,如约束和复合物体,可以帮助你更好地理解物理引擎,并应用于实际项目中。