使用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.pswp.cn/diannao/77529.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/77529.shtml
英文地址,請注明出處:http://en.pswp.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…