【前端】Matter:过滤与高级碰撞检测
在物理引擎中,控制物体的碰撞行为是物理模拟的核心之一。Matter.js 提供了强大的碰撞检测机制和碰撞过滤功能,让开发者可以控制哪些物体能够相互碰撞,如何处理复杂的碰撞情况。本文将详细介绍 碰撞过滤 (Collision Filtering) 与 高级碰撞检测 (Advanced Collision Detection),并通过实例展示如何在应用中使用这些技术。
碰撞过滤 (Collision Filtering)
碰撞过滤 是一种控制物体是否会相互碰撞的机制。通过设置物体的碰撞过滤属性,我们可以定义不同的规则来实现复杂的碰撞逻辑。例如,我们可以让某些物体只与特定物体碰撞,或者禁止它们与其他物体发生碰撞。
碰撞过滤的基本概念
在 Matter.js 中,每个刚体都有一个 collisionFilter 属性,该属性包含以下三个关键值:
category: 碰撞类别,一个物体可以属于多个类别。mask: 碰撞掩码,决定该物体能与哪些类别碰撞。group: 碰撞组,物体可以分配到同一碰撞组内,组内物体是否相互碰撞由组的数值决定。
每个物体都有默认的 category 和 mask,其中默认情况下,所有物体的 category 都是 0x0001,mask 是 0xFFFFFFFF(可以与所有类别碰撞)。
设置碰撞类别和掩码
通过自定义 category 和 mask,可以灵活控制物体之间的碰撞关系。例如,如果我们希望某些物体只与特定类别的物体发生碰撞,可以使用以下代码:
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 的物体碰撞,而不与其他类别的物体碰撞。
碰撞组
除了 category 和 mask,还可以使用 group 来实现更精细的碰撞控制。碰撞组 (Collision Groups) 允许将多个物体分配到同一个组,并控制组内物体的碰撞行为。不同于 category 和 mask,group 的值可以是正数或负数:
- 正数:组内物体相互碰撞。
- 负数:组内物体不会相互碰撞。
例如,我们可以创建一个由多个部件组成的物体(如车轮和车身),并使其在物体内部不会发生碰撞,但可以与外部的物体发生碰撞。
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);
在这里,wheelA 和 wheelB 都属于碰撞组 -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工作…...
C++初阶-list的底层
目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...
springboot 百货中心供应链管理系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,百货中心供应链管理系统被用户普遍使用,为方…...
【OSG学习笔记】Day 18: 碰撞检测与物理交互
物理引擎(Physics Engine) 物理引擎 是一种通过计算机模拟物理规律(如力学、碰撞、重力、流体动力学等)的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互,广泛应用于 游戏开发、动画制作、虚…...
线程与协程
1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指:像函数调用/返回一样轻量地完成任务切换。 举例说明: 当你在程序中写一个函数调用: funcA() 然后 funcA 执行完后返回&…...
NFT模式:数字资产确权与链游经济系统构建
NFT模式:数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新:构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议:基于LayerZero协议实现以太坊、Solana等公链资产互通,通过零知…...
自然语言处理——Transformer
自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效,它能挖掘数据中的时序信息以及语义信息,但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN,但是…...
【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分
一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计,提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合:各模块职责清晰,便于独立开发…...
dify打造数据可视化图表
一、概述 在日常工作和学习中,我们经常需要和数据打交道。无论是分析报告、项目展示,还是简单的数据洞察,一个清晰直观的图表,往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server,由蚂蚁集团 AntV 团队…...
2023赣州旅游投资集团
单选题 1.“不登高山,不知天之高也;不临深溪,不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...
Java编程之桥接模式
定义 桥接模式(Bridge Pattern)属于结构型设计模式,它的核心意图是将抽象部分与实现部分分离,使它们可以独立地变化。这种模式通过组合关系来替代继承关系,从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...
