【前端】Matter:交互与碰撞

在 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 轴正方向上的力将使物体向右移动。

摩擦力与空气阻力

摩擦力和空气阻力是阻止物体无限运动的因素。你可以通过调整刚体的 frictionfrictionAir 来改变这些阻力的影响。

摩擦力

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 包含两个物体 (bodyAbodyB),表示它们发生了碰撞。你可以根据这些信息执行其他操作,比如播放音效或改变物体颜色。

世界边界与限制

设置世界边界

为了防止物体掉出屏幕,我们可以为物理世界设置边界。这通常通过创建不可移动的墙壁或边界物体来实现。

创建边界

使用 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 的其他功能,如约束和复合物体,可以帮助你更好地理解物理引擎,并应用于实际项目中。

相关推荐
我命由我12345几秒前
CesiumJS 案例 P13:删除标记、移动标记、标记点击事件
前端·javascript·前端框架·html·css3·html5·js
GDAL28 分钟前
HTML入门教程18:HTML类
前端·html
.又是新的一天.32 分钟前
第一章 HTML
前端·html
@无铭1 小时前
第七章 利用CSS和多媒体美化页面
前端·css
retun_true1 小时前
记录生活之JSON.parse坑 -- 【JavaScript】
前端·javascript
黑子Kuroko1 小时前
【解决方案】微信小程序如何使用 ProtoBuf 进行 WebSocket 通信
前端·websocket·微信小程序·语音识别·protobuf·语音对话·arraybuff
正小安1 小时前
JavaScript对象的深拷贝和浅拷贝 - 2024最新版前端秋招面试短期突击面试题【100道】
前端·javascript·面试
小小李程序员1 小时前
CSS网格布局
前端·css
掘金酱2 小时前
【🎁 请领取打卡礼】掘金 AI 刷题功能再次升级,AI 编程助手带你领取打卡能量包!
前端·后端·求职
小旺仔爱代码2 小时前
AJAX和JSON
前端·ajax·json