1. 程式人生 > >圓與旋轉矩形的碰撞檢測(下篇)

圓與旋轉矩形的碰撞檢測(下篇)

圓與旋轉矩形的碰撞檢測

本文我將解釋如何實現圓和旋轉矩形的碰撞檢測。碰撞檢測用於確定物件A是否碰撞了物件B。圓包含圓心位置x,y和一個半徑。矩形包含左上角的x,y位置、寬度、長度和一個可以旋轉的角度。我們假設矩形沿著它的中心點旋轉。

我將使用一個小程式、圖片和程式碼來展示這一點。為了更好地理解圓和不旋轉矩形之間的碰撞檢測,可以閱讀這篇文章

程式示例

這裡有一個程式示例來展示碰撞檢測。如果檢測到碰撞,圖形就變為藍色。綠色輪廓形狀表示該用於計算的狀態。橙色的線將未旋轉圓的圓心與矩形上最近的一個點連線。你可以設定一個角度,點選按鈕使其旋轉。點選或者拖動某個地方使圓形移動。

設定一個角度實現圓形和矩形碰撞檢測

想法很簡單。為了計算方便,我們需要在矩形角度為0時,記下兩個形狀的位置。如果我們將矩形旋轉一個角度,計算將會有一點複雜。將矩形保持0度角時候通過簡單的加法就可以很容易地獲得其他點的位置座標。左上角為(x,y),右上角為(x+width, y),左下角為(x, y+height)。

c1.png

這裡我們不旋轉矩形,而是用同樣的角度旋轉圓。將圓心放在矩形角度為0時的位置。單點比較容易旋轉。如下簡圖所示,藍色區域代表我們所看到的矩形在旋轉。黑色區域用於計算。我們用0度調整形狀,換言之,我們將矩形設為0度,用矩形的角度來旋轉圓。

所用的公式如下所示。變數cx/cy代表圓心點,originX/originY代表旋轉圓的點,x’/y’為旋轉點。

x’= cos(theta) * (cx – originX) – sin(theta) * (cy – originY) + originX

y’= sin(theta) * (cx – originX) + cos(theta) * (cy – originY) + originY

c2.png

找到離未旋轉的圓和矩形最近的點,我們需要做的就是分別為x和y做if-else判斷。

對於x,使用矩形的left x(rx)和right x(rx+width)與圓心x(cx)做比較。如果cx在rx的左邊,那麼rx離x最近。如果cx在rx+width的右邊,那麼rx+width離x最近。最後如果以上兩點都不符合,那麼cx本身離x最近。如下圖所示,紅色線表示x的位置。

c3.png

對於y,與x的規則相同。如果圓心y(cy)在top y(ry)的上面,那麼ry離y點最近。如果cy在bottom y(ry+height)的下面,ry+heigh離y最近。如果以上兩點都不符合,那麼cy離y最近。

c4.png

最後,我們需要計算未旋轉圓的圓心和我們所找到的最近點的距離。我使用勾股定理計算這個最近距離(a^2 + b^2 = c^2)。然後將這個值與圓的半徑作比較,如果這個距離遠遠小於半徑,那麼這兩個圖形就會發生碰撞。

c5.png

程式碼例項

1 2 3 4 5 6 7 8 9 10 11 // Rotate circle's center point backdouble unrotatedCircleX = Math.cos(rect.angle) * (circle.x - rect.centerX) -  Math.sin(rect.angle) * (circle.y - rect.centerY) + rect.centerX;double unrotatedCircleY  = Math.sin(rect.angle) * (circle.x - rect.centerX) +  Math.cos(rect.angle) * (circle.y - rect.centerY) + rect.centerY; // Closest point in the rectangle to the center of circle rotated backwards(unrotated)double closestX, closestY; // Find the unrotated closest x point from center of unrotated circleif (unrotatedCircleX  < rect.x) closestX = rect.x;else if (unrotatedCircleX  > rect.x + rect.width) closestX = rect.x + rect.width;else closestX = unrotatedCircleX ; // Find the unrotated closest y point from center of unrotated circleif (unrotatedCircleY < rect.y) closestY = rect.y;else if (unrotatedCircleY > rect.y + rect.height) closestY = rect.y + rect.height;else closestY = unrotatedCircleY; // Determine collisionboolean collision = false; double distance = findDistance(unrotatedCircleX , unrotatedCircleY, closestX, closestY);if (distance < circle.radius) collision = true// Collisionelse collision = false;
1 2 3 4 5 6 7 8 9 /** * Pythagorean theorem * @param fromX * @param fromY * @param toX * @param toY */public double findDistance(double fromX, double fromY, double toX, double toY){ double a = Math.abs(fromX - toX); double b = Math.abs(fromY - toY);     return Math.sqrt((a * a) + (b * b));}

相關推薦

旋轉矩形碰撞檢測下篇

圓與旋轉矩形的碰撞檢測 本文我將解釋如何實現圓和旋轉矩形的碰撞檢測。碰撞檢測用於確定物件A是否碰撞了物件B。圓包含圓心位置x,y和一個半徑。矩形包含左上角的x,y位置、寬度、長度和一個可以旋轉的角度。我們假設矩形沿著它的中心點旋轉。 我將使用一個小程式、圖片和程

2D遊戲中的碰撞檢測:圓形矩形碰撞檢測Javascript&C++版

這幾天放寒假了,時間也多了起來,當然又有時間搞搞程式了。哈哈~昨天在開發我的塔防遊戲時突然發現人物實際攻擊範圍比規定的範圍小,按理說應該是一樣大的,但偏偏不是,我被這個問題搞得糊里糊塗的,一直沒想出問題所在。最後詢問了一個程式高手——我哥哥。他雖然是搞C++的,但聽了我程式碼

成員函式指標高效能的C++委託下篇

Member Function Pointers and the Fastest Possible C++ Delegates 撰文: 翻譯:周翔 (接中篇) 委託(delegate) 和成員函式指標不同,你不難發現委託的用處。最重要的,使用委託可以很容易地實現一個 現

大數據江湖之即席查詢分析下篇--手把手教你搭建即席查詢分析Demo

dmi 安裝centos 用戶 author sla repo 相關 中文 plugin 上篇小弟分享了幾個“即席查詢與分析”的典型案例,引起了不少共鳴,好多小夥伴迫不及待地追問我們:說好的“手把手教你搭建即席查詢與分析Demo”啥時候能出?說到就得做到,差啥不能差

特徵提取檢測 --- SIFT演算法

        SIFT(Scale-invariant feature transform)是一種檢測區域性特徵的演算法,該演算法通過求一幅圖中的特徵點(interest points,or corner points)及其有關scale 和 orien

JavaScript 遍歷、列舉迭代的騷操作下篇

前言 JavaScript 遍歷、列舉與迭代的騷操作(上篇)總結了一些常用物件的遍歷方法,大部分情況下是可以滿足工作需求的。但下篇介紹的內容,在工作中95%的情況下是用不到的,僅限裝逼。俗話說:裝得逼多必翻車!若本文有翻車現場,請輕噴。 ES6 迭代器(iterator)、生成器(generator)

【蜂口 | AI人工智慧】人臉檢測——龍鵬 深度學習人臉影象應用連載

我們接著上一節的分享,繼續分享人臉檢測的下半部分。這次的分享主要是深度學習相關的。我們會主要講述當前深度學習在人臉檢測這個領域的發展水平。主要從以下幾個方向進行分享: 首先,我們會講講當前主流的基於深度學習的一個人臉檢測的框架,包括兩個框架,一個是級聯CNN框架

機器學習計算機視覺入門專案——視訊投籃檢測

在第二部分,我記錄了實驗中提取影象特徵的HOG運算元及其實現程式碼,我們接下來就要構造幾個簡單的分類器,對資料集的HOG特徵來分類,實現進球/不進球的分類任務。 分類器的設計和選擇 實驗中要用到的分類模型主要有四個: logistic迴歸 SVM支援向量機

聊天室下篇GatewayWorker Laravel 的整合

思路 上一篇大概梳理了一下 GatewayWorker 的基礎知識。這篇就來準備整合 GatewayWorker 到 Laravel。 GatewayWorker 是基於 Socket 監聽的伺服器框架,而 Laravel 是基於 HTTP 請求/響應模型的 Web 框架。所以一定要明白,兩者的部署是

QT QPainter用法包含畫點,畫,畫矩形,畫線等

       QPainter可以繪製從簡單的直線到像餅圖和絃這樣的複雜形狀。它也可以繪製排列的文字和畫素對映。通常,它在一個“自然的”座標系統中繪製,但是它也可以在視和世界轉換中做到這些。繪圖工具的典型用法是:構造一個繪圖工具。設定畫筆、畫刷等等。繪製。銷燬這個繪圖工具。下

檢測- RANSAC

繼之前提到的兩種方法之後,這裡再列出基於RANSAC的圓檢測,RANSAC(Random Sample Consensus)隨機抽樣一致性,略不同於霍夫圓變換那種基於投票的策略,這是一種對觀測資料進行最大化模型檢驗的方法。下面來簡單介紹一下它的原理: 1、原理

Cocos2d-x 精靈碰撞檢測方法一

宣告函式碰撞檢測函式,兩個精靈和重寫update bool isCollision( CCPoint p1,CCPoint p2,int w1,int h1,int w2,int h2 ); CCSprite *sp2; CCSprite *sp1; virtua

Unity中武器人物的碰撞檢測

Description Returns true if there is any collider intersecting the line between start and end. 3、碰撞體回撥 給武器上掛一個空的GameObject,然後給這個GameObject掛上一個Collider(勾

OnTriggerEnterRigidbody-Unity碰撞檢測

寫在前面的話 用unity做開發碰撞的檢測是經常要用到的,但是有時候會發現碰撞不起作用,小弟頗為疑惑。於是做了個小小的實驗來探討一下。 Unity為4.6.3 Rigidbody元件 常用的 1.Mass 指定GameObject質量

Cocos2d-X 瓦片地圖使用的例項專案包含碰撞檢測,移動

(1)標頭檔案中 #include <iostream> #include "cocos2d.h" usingnamespacecocos2d; class AA:publicCCLayer { public:     virtual bool init()

呼叫中心的起源發展下篇

呼叫中心的發展經歷了以下幾個階段:   第一代呼叫中心:簡單的人工熱線電話; 第二代呼叫中心:互動式自動語音應答系

不使用Visual Studio開發ASP.NET MVC應用下篇

構建 onf log rdquo 你們 err ica ide lan 書接上回! 前文“純手工”、徹底拋棄Visual Studio,制作了一個ASP.NET MVC應用,運行起來還不錯,項目目錄、源代碼、web.config等所有東西都已經做到

javajavax的區別分析

mes ges 歷史 java虛擬機 虛擬 over 問題 c語言 enc Java是一種受C語言影響的編程語言。Java和Javax本質上是與Java編程語言的上下文一起使用的包。實際上Java和Javax沒有區別。這只是不同的名字。 Java是一種編程語言,受到C語言

數據結構算法題目集中文——5-13 統計工齡 (20分)——桶排序

color 單位 html out cin hit lis -s cnblogs 給定公司NN名員工的工齡,要求按工齡增序輸出每個工齡段有多少員工。 輸入格式: 輸入首先給出正整數NN(\le 10^5≤10?5??),即員工總人數;隨後給出NN個整數,即每個員工的工齡