使用dyn4j做碰撞检测

文章目录

  • 前言
  • 一、环境准备
    • 添加依赖
    • 基本概念
  • 二、实现步骤
    • 1.创建世界
    • 2.添加物体
    • 3.设置碰撞监听器
    • 4.更新世界
  • 三、完整代码示例
  • 四、优化补充
  • 总结


前言

dyn4j 提供了高效的碰撞检测和物理模拟功能,适用于游戏开发、动画制作以及其他需要物理交互的场景。通过简单的 API,用户可以快速构建物理世界并实现复杂的碰撞检测逻辑。


一、环境准备

Java 开发环境:安装 JDK 8 或更高版本。
Maven 或 Gradle:用于管理依赖项。
IDE:如 IntelliJ IDEA 或 Eclipse。

添加依赖

<dependency><groupId>org.dyn4j</groupId><artifactId>dyn4j</artifactId><version>5.0.2</version> <!-- 请检查最新版本 -->
</dependency>

基本概念

在使用 dyn4j 时,有几个核心概念需要了解:

World(世界):表示物理模拟的环境,所有物体和碰撞事件都发生在世界中。
Body(物体):表示物理世界中的实体,可以是静态或动态的。
Fixture(形状):附加到物体上的几何形状,用于定义碰撞区域。
Collision Listener(碰撞监听器):用于监听和处理碰撞事件。

二、实现步骤

以下是使用 dyn4j 实现碰撞检测的基本步骤。

1.创建世界

首先,我们需要创建一个 World 对象,它是所有物理模拟的基础。

        World<Body> world = new World<>();world.setGravity(World.ZERO_GRAVITY);

2.添加物体

接下来,我们向世界中添加物体。每个物体都需要一个形状(如矩形、圆形)和质量属性。

        Body npcBody = createBody(0, 0, 1, 1);Body itemBody = createBody(4, 0, 1, 1);world.addBody(npcBody);world.addBody(itemBody);/*** 创建物体*/private static Body createBody(double x, double y, double w, double h) {Body body = new Body();body.addFixture(Geometry.createRectangle(w, h));body.getTransform().setTranslation(x, y);// 如果不设置质量,碰撞监听不生效body.setMass(MassType.NORMAL);return body;}

3.设置碰撞监听器

        world.addCollisionListener(new CollisionListener<>() {@Overridepublic boolean collision(BroadphaseCollisionData broadphaseCollisionData) {// 碰撞会调用到这里log.info("broadphaseCollisionData:{}, {}",broadphaseCollisionData.getBody1().getTransform().getTranslation(),broadphaseCollisionData.getBody2().getTransform().getTranslation());return true;}@Overridepublic boolean collision(NarrowphaseCollisionData narrowphaseCollisionData) {log.info("narrowphaseCollisionData:{}", narrowphaseCollisionData);return false;}@Overridepublic boolean collision(ManifoldCollisionData manifoldCollisionData) {log.info("manifoldCollisionData:{}", manifoldCollisionData);return false;}});

4.更新世界

        for (int i = 0; i < 100; i++) {// 模拟移动itemBody.translate(-0.1, 0);// 手动判断是否碰撞if (world.getBroadphaseDetector().detect(itemBody, npcBody)) {log.info("npc: {}, item: {}", npcBody.getTransform().getTranslation(), itemBody.getTransform().getTranslation());break;}// 更新世界world.update(1d / 60d);}

三、完整代码示例

import lombok.extern.slf4j.Slf4j;
import org.dyn4j.dynamics.Body;
import org.dyn4j.geometry.Geometry;
import org.dyn4j.geometry.MassType;
import org.dyn4j.world.BroadphaseCollisionData;
import org.dyn4j.world.ManifoldCollisionData;
import org.dyn4j.world.NarrowphaseCollisionData;
import org.dyn4j.world.World;
import org.dyn4j.world.listener.CollisionListener;@Slf4j
public class WorldApp {public static void main(String[] args) {World<Body> world = new World<>();world.setGravity(World.ZERO_GRAVITY);Body npcBody = createBody(0, 0, 1, 1);Body itemBody = createBody(4, 0, 1, 1);world.addBody(npcBody);world.addBody(itemBody);world.addCollisionListener(new CollisionListener<>() {@Overridepublic boolean collision(BroadphaseCollisionData broadphaseCollisionData) {log.info("broadphaseCollisionData:{}, {}",broadphaseCollisionData.getBody1().getTransform().getTranslation(),broadphaseCollisionData.getBody2().getTransform().getTranslation());return false;}@Overridepublic boolean collision(NarrowphaseCollisionData narrowphaseCollisionData) {log.info("narrowphaseCollisionData:{}", narrowphaseCollisionData);return false;}@Overridepublic boolean collision(ManifoldCollisionData manifoldCollisionData) {log.info("manifoldCollisionData:{}", manifoldCollisionData);return false;}});for (int i = 0; i < 100; i++) {itemBody.translate(-0.1, 0);if (world.getBroadphaseDetector().detect(itemBody, npcBody)) {log.info("npc: {}, item: {}", npcBody.getTransform().getTranslation(), itemBody.getTransform().getTranslation());break;}world.update(1d / 60d);}}/*** 创建物体*/private static Body createBody(double x, double y, double w, double h) {Body body = new Body();body.addFixture(Geometry.createRectangle(w, h));body.getTransform().setTranslation(x, y);body.setMass(MassType.NORMAL);return body;}
}

会打印

11:31:49.723 [main] [] INFO  c.z.g.t.l.WorldApp.collision(WorldApp.java:62) broadphaseCollisionData:(1.1999999999999975, 0.0), (0.0, 0.0)
11:31:49.723 [main] [] INFO  c.z.g.t.l.WorldApp.main(WorldApp.java:84) npc: (0.0, 0.0), item: (1.0999999999999974, 0.0)

四、优化补充

在上述代码中,添加了碰撞监听器,使用了BroadphaseDetector().detect()方法进行碰撞检测。而在实际的使用中,世界更新时(调用update或者step方法)会自动检测所有碰撞体,可以使用getCollisionDataIterator()方法获取。这样可以避免循环世界所有的物体判断碰撞。

	/*** 移动并检测是否碰撞* @param body 要检测的物体*/public static boolean isCollision(Body body, double x, double y) {// 保存上次位置Transform copy = body.getTransform().copy();body.translate(x, y);world.update(1d / 60d);// 获取所有碰撞体Iterator<WorldCollisionData<Body>> collisionDataIterator = world.getCollisionDataIterator();// 直接遍历碰撞体,判断是否存在碰撞while (collisionDataIterator.hasNext()) {WorldCollisionData<Body> collisionData = collisionDataIterator.next();if (collisionData.getBody1() == body || collisionData.getBody2() == body) {// 如果碰撞,回退上次位置body.getTransform().set(copy);return true;}}return false;}

总结

通过以上步骤,我们学习了如何使用 dyn4j 实现基本的碰撞检测功能。dyn4j 提供了丰富的物理模拟功能,可以帮助开发者快速构建复杂的物理交互场景。如果需要更高级的功能,可以参考官方文档进一步探索。
参考资料:dyn4j 官方文档

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/77529.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VS Code settings.json 文件中常用的预定义变量‌及其用途说明

VS Code settings.json 常用预定义变量 以下是 Visual Studio Code 配置文件中常用的预定义变量列表&#xff1a; 1. 工作区相关变量 变量描述示例值${workspaceFolder}当前工作区根目录的绝对路径C:/projects/my-project${workspaceFolderBasename}工作区文件夹名称&#x…

elasticSearch-搜索引擎

搜索引擎的优势 有了数据库分页查询&#xff0c;为什么还需要搜索引擎&#xff1f; 搜索引擎速度上很快数据库分页查询&#xff0c;随着数据库数据量增大&#xff0c;页数靠后&#xff0c;会导致搜索速度变慢&#xff0c;但是搜索引擎不会搜索引擎支持分词查询&#xff0c;地…

安装OpenJDK1.8 17 (macos M芯片)

安装OpenJDK 1.8 下载完后&#xff0c;解压&#xff0c;打开 环境变量的配置文件即可 vim ~/.zshrc #export JAVA_HOME/Users/xxxxx/jdk-21.jdk/Contents/Home #export JAVA_HOME/Users/xxxxx/jdk-17.jdk/Contents/Home #export JAVA_HOME/Users/xxxxx/jdk-11.jdk/Contents…

断言与反射——以golang为例

断言 x.(T) 检查x的动态类型是否是T&#xff0c;其中x必须是接口值。 简单使用 func main() {var x interface{}x 100value1, ok : x.(int)if ok {fmt.Println(value1)}value2, ok : x.(string)if ok {//未打印fmt.Println(value2)} }需要注意如果不接受第二个参数就是OK,这…

Java设计模式:系统性解析与核心模式

一、设计模式三大分类总览 创建型模式&#xff08;5种&#xff09; 核心目标&#xff1a;对象创建的优化与解耦 单例模式&#xff08;Singleton&#xff09; 工厂模式&#xff08;Factory&#xff09; 抽象工厂模式&#xff08;Abstract Factory&#xff09; 建造者模式&#…

Elasticsearch 向量数据库,原生支持 Google Cloud Vertex AI 平台

作者&#xff1a;来自 Elastic Valerio Arvizzigno Elasticsearch 将作为第一个第三方原生语义对齐引擎&#xff0c;支持 Google Cloud 的 Vertex AI 平台和 Google 的 Gemini 模型。这使得联合用户能够基于企业数据构建完全可定制的生成式 AI 体验&#xff0c;并借助 Elastics…

408 计算机网络 知识点记忆(7)

前言 本文基于王道考研课程与湖科大计算机网络课程教学内容&#xff0c;系统梳理核心知识记忆点和框架&#xff0c;既为个人复习沉淀思考&#xff0c;亦希望能与同行者互助共进。&#xff08;PS&#xff1a;后续将持续迭代优化细节&#xff09; 往期内容 408 计算机网络 知识…

10-MySQL-性能优化思路

1、优化思路 当我们发现了一个慢SQL的问题的时候,需要做性能优化,一般我们是为了提高SQL查询更快,一个查询的流程由下图的各环节组成,每个环节都会消耗时间,要减少消耗时候需要从各个环节都分析一遍。 2 连接配置优化 第一个环节是客户端连接到服务端,这块可能会出现服务…

Docker:安装与部署 Nacos 的技术指南

1、简述 Nacos(Dynamic Naming and Configuration Service)是阿里巴巴开源的一个动态服务发现、配置管理和服务治理的综合解决方案,适用于微服务架构。 Nacos 主要功能: 服务发现与注册:支持 Dubbo、Spring Cloud 等主流微服务框架的服务发现与注册。动态配置管理:支持…

【非机动车检测】用YOLOv8实现非机动车及驾驶人佩戴安全帽检测

非机动车及驾驶人佩戴安全帽检测任务的意义主要包括以下几点&#xff1a; 保障行车安全&#xff1a;非机动车包括自行车、电动车等&#xff0c;佩戴安全帽能够有效保护骑车人头部&#xff0c;减少因交通事故造成的头部伤害风险&#xff0c;提高行车安全系数。 符合交通法规&am…

壹起航:15年深耕互联网营销,助力中国工厂出海获客

在全球化浪潮下&#xff0c;越来越多的中国工厂渴望拓展海外市场&#xff0c;但面临品牌建立、稳定询盘获取及营销成本降低等多重挑战。壹起航凭借15年的丰富经验&#xff0c;整合外贸建站、SEO优化及海外短视频营销&#xff0c;为中国工厂提供一站式出海解决方案。 一、外贸独…

Emacs 折腾日记(二十)——修改emacs的一些默认行为

上一篇我们完成了emacs输入法的配置以及将emacs配置成了使用vim的操作方式。但是emacs目前有些默认行为我不太喜欢&#xff0c;这节我们一起来修改它 备份设置 我们打开emacs的配置文件所在路径&#xff0c;发现有大量的~结尾的文件&#xff0c;这是emacs的备份文件。这里&am…

聊透多线程编程-线程基础-4.C# Thread 子线程执行完成后通知主线程执行特定动作

在多线程编程中&#xff0c;线程之间的同步和通信是一个常见的需求。例如&#xff0c;我们可能需要一个子线程完成某些任务后通知主线程&#xff0c;并由主线程执行特定的动作。本文将基于一个示例程序&#xff0c;详细讲解如何使用 AutoResetEvent 来实现这种场景。 示例代码…

【网络安全 | 项目开发】Web 安全响应头扫描器(提升网站安全性)

原创项目,未经许可,不得转载。 文章目录 项目简介工作流程示例输出技术栈项目代码使用说明项目简介 安全响应头是防止常见 Web 攻击(如点击劫持、跨站脚本攻击等)的有效防线,因此合理的配置这些头部信息对任何网站的安全至关重要。 Web 安全响应头扫描器(Security Head…

使用libcurl编写爬虫程序指南

用户想知道用Curl库编写的爬虫程序是什么样的。首先&#xff0c;我需要明确Curl本身是一个命令行工具和库&#xff0c;用于传输数据&#xff0c;支持多种协议。而用户提到的“Curl库”可能指的是libcurl&#xff0c;这是一个客户端URL传输库&#xff0c;可以用在C、C等编程语言…

使用pip3安装PyTorch与PyG,实现NVIDIA CUDA GPU加速

使用python3的pip3命令安装python依赖库。 # python3 -V Python 3.12.3 # # pip3 -V pip 25.0.1 from /root/.pyenv/versions/3.12.3/lib/python3.12/site-packages/pip (python 3.12)Usage: pip3 install [options] <package> ...pip3 install [options] -r <re…

五种常用的web加密算法

文章目录 五种常用Web加密算法实战及原理详解1. AES (高级加密标准)原理详解应用场景实战代码&#xff08;Node.js&#xff09; 2. RSA (非对称加密)原理详解应用场景实战代码&#xff08;Node.js&#xff09; 3. SHA-256 (安全哈希算法)原理详解应用场景实战代码&#xff08;浏…

深入解析 C++ 设计模式:原理、实现与应用

一、引言 在 C 编程的广袤领域中&#xff0c;设计模式犹如闪耀的灯塔&#xff0c;为开发者指引着构建高效、可维护软件系统的方向。设计模式并非神秘莫测的代码魔法&#xff0c;实际上&#xff0c;我们在日常编程中或许早已与之打过交道。简单来说&#xff0c;设计模式常常借助…

Python刷题笔记

Python刷题笔记 1、输出格式化 第一种格式化的输出&#xff1a; name "jack" age 17 salary 20031.8752 print("你的名字是&#xff1a;%s,今年 %d 岁,工资 %7.2f" % (name,age,salary) ) --------------------------------------- 你的名字是&#…

【Kubernetes】Kubernetes 如何进行日志管理?Fluentd / Loki / ELK 适用于什么场景?

由于 Kubernetes 运行在容器化的环境中&#xff0c;应用程序和系统日志通常分布在多个容器和节点上&#xff0c;传统的日志管理方法&#xff08;例如直接访问每个节点的日志文件&#xff09;在 Kubernetes 中不适用。 因此&#xff0c;Kubernetes 引入了集中式日志管理方案&am…