当前位置: 首页 > news >正文

【前端】Matter:过滤与高级碰撞检测

在物理引擎中,控制物体的碰撞行为是物理模拟的核心之一。Matter.js 提供了强大的碰撞检测机制和碰撞过滤功能,让开发者可以控制哪些物体能够相互碰撞,如何处理复杂的碰撞情况。本文将详细介绍 碰撞过滤 (Collision Filtering)高级碰撞检测 (Advanced Collision Detection),并通过实例展示如何在应用中使用这些技术。

碰撞过滤 (Collision Filtering)

碰撞过滤 是一种控制物体是否会相互碰撞的机制。通过设置物体的碰撞过滤属性,我们可以定义不同的规则来实现复杂的碰撞逻辑。例如,我们可以让某些物体只与特定物体碰撞,或者禁止它们与其他物体发生碰撞。

碰撞过滤的基本概念

在 Matter.js 中,每个刚体都有一个 collisionFilter 属性,该属性包含以下三个关键值:

  • category: 碰撞类别,一个物体可以属于多个类别。
  • mask: 碰撞掩码,决定该物体能与哪些类别碰撞。
  • group: 碰撞组,物体可以分配到同一碰撞组内,组内物体是否相互碰撞由组的数值决定。

每个物体都有默认的 categorymask,其中默认情况下,所有物体的 category 都是 0x0001mask0xFFFFFFFF(可以与所有类别碰撞)。

设置碰撞类别和掩码

通过自定义 categorymask,可以灵活控制物体之间的碰撞关系。例如,如果我们希望某些物体只与特定类别的物体发生碰撞,可以使用以下代码:

const { Engine, Render, Runner, World, Bodies } = Matter;// 创建引擎和渲染器
const engine = Engine.create();
const render = Render.create({element: document.body,engine: engine,options: {width: 800,height: 600,wireframes: false}
});// 定义碰撞类别
const defaultCategory = 0x0001;
const categoryA = 0x0002;
const categoryB = 0x0004;// 创建物体并分配类别和掩码
const ballA = Bodies.circle(300, 200, 40, {collisionFilter: {category: categoryA,mask: categoryB // 只与类别B的物体碰撞}
});const ballB = Bodies.circle(500, 200, 40, {collisionFilter: {category: categoryB,mask: categoryA // 只与类别A的物体碰撞}
});const ground = Bodies.rectangle(400, 600, 810, 60, { isStatic: true });World.add(engine.world, [ballA, ballB, ground]);Engine.run(engine);
Render.run(render);

在这个例子中,ballA 属于类别 categoryA,它的 mask 设为 categoryB,这意味着它只会与属于类别 categoryB 的物体碰撞。同样,ballB 也只会与属于 categoryA 的物体碰撞,而不与其他类别的物体碰撞。

碰撞组

除了 categorymask,还可以使用 group 来实现更精细的碰撞控制。碰撞组 (Collision Groups) 允许将多个物体分配到同一个组,并控制组内物体的碰撞行为。不同于 categorymaskgroup 的值可以是正数或负数:

  • 正数:组内物体相互碰撞。
  • 负数:组内物体不会相互碰撞。

例如,我们可以创建一个由多个部件组成的物体(如车轮和车身),并使其在物体内部不会发生碰撞,但可以与外部的物体发生碰撞。

const wheelA = Bodies.circle(300, 400, 40, {collisionFilter: {group: -1}
});const wheelB = Bodies.circle(500, 400, 40, {collisionFilter: {group: -1}
});const ground = Bodies.rectangle(400, 600, 810, 60, { isStatic: true });// 轮子和地面会发生碰撞,但两个轮子之间不会
World.add(engine.world, [wheelA, wheelB, ground]);Engine.run(engine);
Render.run(render);

在这里,wheelAwheelB 都属于碰撞组 -1,因此它们不会相互碰撞,但它们可以与其他物体(例如地面)发生碰撞。

高级碰撞检测 (Advanced Collision Detection)

Matter.js 中的高级碰撞检测功能允许你检测并处理更加复杂的碰撞事件,比如检测特定物体的碰撞、获取碰撞接触点、以及响应特定碰撞事件。

监听碰撞事件

Matter.js 提供了事件监听器,可以在物体发生碰撞时触发特定的回调函数。以下是常用的三个碰撞事件:

  • collisionStart: 两个物体开始碰撞时触发。
  • collisionActive: 两个物体在碰撞过程中持续触发。
  • collisionEnd: 两个物体碰撞结束时触发。

你可以通过 Matter.Events.on() 来监听这些碰撞事件。例如:

Matter.Events.on(engine, 'collisionStart', function(event) {const pairs = event.pairs;pairs.forEach(pair => {const { bodyA, bodyB } = pair;console.log(`Collision detected between ${bodyA.label} and ${bodyB.label}`);});
});

在这个例子中,当两个物体开始碰撞时,会在控制台中输出相关信息。

检测碰撞的详细信息

当物体发生碰撞时,Matter.js 提供了关于碰撞点、碰撞深度等的详细信息。你可以使用这些信息来实现更加细致的碰撞处理。

以下是一个例子,展示如何获取碰撞的接触点:

Matter.Events.on(engine, 'collisionStart', function(event) {const pairs = event.pairs;pairs.forEach(pair => {const { bodyA, bodyB, collision } = pair;const { supports } = collision;console.log(`Collision point: x=${supports[0].x}, y=${supports[0].y}`);});
});

supports 是碰撞的接触点坐标数组,你可以使用这些坐标来执行更多的逻辑,比如根据碰撞点触发爆炸、声音效果或粒子效果。

手动处理碰撞

除了依赖引擎的自动处理,你还可以通过监听事件手动修改物体的碰撞行为。以下是一个示例,展示如何在物体碰撞时改变物体的颜色:

Matter.Events.on(engine, 'collisionStart', function(event) {const pairs = event.pairs;pairs.forEach(pair => {pair.bodyA.render.fillStyle = '#FF0000';pair.bodyB.render.fillStyle = '#FF0000';});
});

在这个例子中,当两个物体发生碰撞时,它们的颜色会变成红色。通过这种方式,你可以根据碰撞的结果来实现自定义的视觉效果。

碰撞的条件过滤

有时我们只想对特定的碰撞进行处理,而忽略其他的碰撞。可以通过在事件监听器中添加条件过滤来实现这一点。例如,如果你只想处理特定物体的碰撞,可以这样实现:

Matter.Events.on(engine, 'collisionStart', function(event) {const pairs = event.pairs;pairs.forEach(pair => {if (pair.bodyA.label === 'ball' && pair.bodyB.label === 'ground') {console.log('Ball hit the ground!');}});
});

在这个示例中,只有当 ball 碰到 ground 时,才会触发日志输出。这样可以避免处理无关的碰撞事件。

性能优化

高级碰撞检测和复杂的碰撞过滤可能会影响性能,尤其是在处理大量物体时。为了保持物理引擎的性能,以下是一些优化技巧:

  • 简化碰撞形状: 使用简单的几何形状(如矩形、圆形)代替复杂的多边形。
  • 减少不必要的碰撞检测: 使用碰撞过滤或分层逻辑,避免处理无关的物体碰撞。
  • 降低引擎更新频率: 调整 engine.timing.timeScale 来控制引擎的更新频率,减少每帧计算的负载。

总结

在本教程中,我们深入探讨了 Matter.js 中的 碰撞过滤高级碰撞检测。通过碰撞过滤,可以精确控制物体的碰撞行为,定义复杂的碰撞规则。而通过高级碰撞检测,可以获取碰撞的详细信息,监听碰撞事件并自定义碰撞响应逻辑。

这些功能使得 Matter.js 能够处理复杂的物理交互,提供了更大的灵活性,适用于需要细致控制和优化的物理模拟场景。

相关文章:

【前端】Matter:过滤与高级碰撞检测

在物理引擎中,控制物体的碰撞行为是物理模拟的核心之一。Matter.js 提供了强大的碰撞检测机制和碰撞过滤功能,让开发者可以控制哪些物体能够相互碰撞,如何处理复杂的碰撞情况。本文将详细介绍 碰撞过滤 (Collision Filtering) 与 高级碰撞检测…...

wps图标没有坐标轴标题怎么办?wps表格不能用enter下怎么办?

目录 wps图标没有坐标轴标题怎么办 一、在WPS PPT中添加坐标轴标题 二、在WPS Excel中添加坐标轴标题 wps表格不能用enter下怎么办 一、检查并修改设置 二、检查单元格保护状态 三、使用快捷键实现换行 wps图标没有坐标轴标题怎么办 一、在WPS PPT中添加坐标轴标题 插入…...

在ESP-IDF环境中如何进行多文件中的数据流转-FreeRTOS实时操作系统_流缓存区“xMessageBuffer”

一、建立三个源文件和对应的头文件 建立文件名,如图所示 图 1-1 二、包含相应的头文件 main.h 图 2-1 mess_send.h mess_rece.h和这个中类似,不明白的大家看我最后面的源码分享 图2-2 三、声明消息缓存区的句柄 大家注意,在main.c中定义的是全局变…...

ConcurrentLinkedQueue适合什么样的使用场景?

ConcurrentLinkedQueue 是 Java 中一种无界线程安全的队列,适合多线程环境中的高并发场景。以下是一些它特别适合的使用场景: 1. 高频读操作,低频写操作 ConcurrentLinkedQueue 对于实际应用中读操作相对频繁,写操作较少的场景非…...

C语言 | Leetcode C语言题解之第480题滑动窗口中位数

题目: 题解: struct Heap {int* heap;int heapSize;int realSize;bool (*cmp)(int, int); };void init(struct Heap* obj, int n, bool (*cmp)(int, int)) {obj->heap malloc(sizeof(int) * (n 1));obj->heapSize 0;obj->cmp cmp; }bool c…...

LabVIEW开发如何实现降维打击

在LabVIEW开发中实现“降维打击”可以理解为利用软件优势和高效工具来解决复杂的问题,将多维度、多层次的技术简化为容易操作和管理的单一维度,达到出其不意的效果。以下是几种关键策略: 1. 模块化设计与封装 将复杂系统分解为若干模块&…...

docker 文件目录迁移

文章参考 du -hs /var/lib/docker/ 命令查看磁盘使用情况。 du -hs /var/lib/docker/docker system df命令,类似于Linux上的df命令,用于查看Docker的磁盘使用情况: rootnn0:~$ docker system df TYPE TOTAL ACTIVE SIZE RECLAIMABLE Images 7 2 122.2…...

Markdown 标题

Markdown 标题 Markdown 是一种轻量级标记语言,它允许人们使用易读易写的纯文本格式编写文档,然后转换成格式化的HTML代码。Markdown 的语法简洁明了,广泛用于撰写文档、博客文章、笔记等。本文将详细介绍 Markdown 的标题语法及其在文档中的应用。 Markdown 标题语法 在…...

【动手学电机驱动】TI InstaSPIN-FOC(5)Lab04 力矩控制

TI InstaSPIN-FOC(1)电机驱动和控制测试平台 TI InstaSPIN-FOC(2)Lab01 闪灯实验 TI InstaSPIN-FOC(3)Lab03a 测量电压电流漂移量 TI InstaSPIN-FOC(4)Lab02b 电机参数辨识 TI Insta…...

Mysql的CommunicationsException

一、报错内容 com.mysql.cj.jdbc.exceptions.CommunicationsException: The last packet successfully received from the server was 1,500,378 milliseconds ago. The last packet sent successfully to the server was 1,500,378 milliseconds ago. is longer than the s…...

C++学习笔记----9、发现继承的技巧(二)---- 重用目的的继承

现在你对继承的基本语法已经比较熟悉了,是时候探索继承是c语言中重要属性的一个主要原因了。继承是一个装备允许你平衡既有代码。本节会举出基于代码重用目的的继承的例子。 1、WeatherPrediction类 假想你有一个任务,写一个程序来发出简单的天气预报&a…...

锐评 Nodejs 设计模式 - 创建与结构型

本系列文章的思想,都融入了 让 Java 再次伟大 这个全新设计的脚手架产品中,欢迎大家使用。 单例模式与模块系统 Node 的单例模式既特殊又简单——凡是从模块中导出的实例天生就是单例。 // database.js function Database(connect, account, password)…...

【RoadRunner】自动驾驶模拟3D场景构建 | 软件简介与视角控制

💯 欢迎光临清流君的博客小天地,这里是我分享技术与心得的温馨角落 💯 🔥 个人主页:【清流君】🔥 📚 系列专栏: 运动控制 | 决策规划 | 机器人数值优化 📚 🌟始终保持好奇心&…...

15分钟学Go 第4天:Go的基本语法

第4天:基本语法 在这一部分,将讨论Go语言的基本语法,了解其程序结构和基础语句。这将为我们后续的学习打下坚实的基础。 1. Go语言程序结构 Go语言程序的结构相对简单,主要包括: 包声明导入语句函数语句 1.1 包声…...

【Qt】Qt的介绍——Qt的概念、使用Qt Creator新建项目、运行Qt项目、纯代码方式、可视化操作、认识对象模型(对象树)

文章目录 Qt1. Qt的概念2. 使用Qt Creator新建项目3. 运行Qt项目3.1 纯代码方式实现3.2 可视化操作实现 4. 认识对象模型(对象树) Qt 1. Qt的概念 Qt 是一个跨平台的 C 图形用户界面应用程序开发框架。它是软件开发者提供的用于界面开发的程序框架&#…...

论文笔记:PTR: Prompt Tuning with Rules for Text Classification

Abstract 手动设计大量语言提示麻烦且易出错,而自动生成的提示,在非小样本场景下验证其有效性昂贵且耗时。因此,提示调优以处理多类别分类任务仍然具有挑战。为此,本文提出使用规则进行多类别文本分类提示调优(PTR&…...

服务器和中转机协同工作以提高网络安全

服务器和中转机(代理服务器)可以通过多种方式协同工作来提高网络安全。 常见的协同工作策略: 1. 使用代理服务器作为安全网关 访问控制:代理服务器可以作为网络的入口点,实施访问控制策略,如基于IP地址、…...

Java利用itextpdf实现pdf文件生成

前言 最近公司让写一个数据页面生成pdf的功能,找了一些市面代码感觉都太麻烦,就自己综合性整合了一个便捷的工具类,开发只需简单组装数据直接调用即可快速生成pdf文件。望大家一起学习!!! 代码获取方式&am…...

2010年国赛高教杯数学建模C题输油管的布置解题全过程文档及程序

2010年国赛高教杯数学建模 C题 输油管的布置 某油田计划在铁路线一侧建造两家炼油厂,同时在铁路线上增建一个车站,用来运送成品油。由于这种模式具有一定的普遍性,油田设计院希望建立管线建设费用最省的一般数学模型与方法。   1. 针对两炼…...

datawhale大模型bot应用开发--task3:工作流

目录 一、介绍:Coze工作流 1.1工作流应用场景 1.2什么是工作流 1.3思考环节 二、各个工作流详情 2.1情感分类工作流 2.2 随机数工作流 2.3 必应搜索工作流 2.4 天气查询工作流 三、集合上面五个工作流的总工作流 一、介绍:Coze工作流 1.1工作…...

Ubuntu系统下交叉编译openssl

一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机:Ubuntu 20.04.6 LTSHost:ARM32位交叉编译器:arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...

shell脚本--常见案例

1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件: 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...

C++中string流知识详解和示例

一、概览与类体系 C 提供三种基于内存字符串的流&#xff0c;定义在 <sstream> 中&#xff1a; std::istringstream&#xff1a;输入流&#xff0c;从已有字符串中读取并解析。std::ostringstream&#xff1a;输出流&#xff0c;向内部缓冲区写入内容&#xff0c;最终取…...

大学生职业发展与就业创业指导教学评价

这里是引用 作为软工2203/2204班的学生&#xff0c;我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要&#xff0c;而您认真负责的教学态度&#xff0c;让课程的每一部分都充满了实用价值。 尤其让我…...

rnn判断string中第一次出现a的下标

# coding:utf8 import torch import torch.nn as nn import numpy as np import random import json""" 基于pytorch的网络编写 实现一个RNN网络完成多分类任务 判断字符 a 第一次出现在字符串中的位置 """class TorchModel(nn.Module):def __in…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA

浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求&#xff0c;本次涉及的主要是收费汇聚交换机的配置&#xff0c;浪潮网络设备在高速项目很少&#xff0c;通…...

【笔记】WSL 中 Rust 安装与测试完整记录

#工作记录 WSL 中 Rust 安装与测试完整记录 1. 运行环境 系统&#xff1a;Ubuntu 24.04 LTS (WSL2)架构&#xff1a;x86_64 (GNU/Linux)Rust 版本&#xff1a;rustc 1.87.0 (2025-05-09)Cargo 版本&#xff1a;cargo 1.87.0 (2025-05-06) 2. 安装 Rust 2.1 使用 Rust 官方安…...

在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)

考察一般的三次多项式&#xff0c;以r为参数&#xff1a; p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]&#xff1b; 此多项式的根为&#xff1a; 尽管看起来这个多项式是特殊的&#xff0c;其实一般的三次多项式都是可以通过线性变换化为这个形式…...

mac 安装homebrew (nvm 及git)

mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用&#xff1a; 方法一&#xff1a;使用 Homebrew 安装 Git&#xff08;推荐&#xff09; 步骤如下&#xff1a;打开终端&#xff08;Terminal.app&#xff09; 1.安装 Homebrew…...

【 java 虚拟机知识 第一篇 】

目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...