2014-02-06 54 views
1

我必須在Rectangle類中編寫一個collide方法,該類需要另一個Rectangle對象作爲參數,如果它與執行該方法的矩形相碰撞則返回True,如果不是,則返回。我的解決方案是使用for循環遍歷一個矩形中的x和y的每個值,以查看它是否落在另一個矩形內,但我懷疑可能有更高效或更優雅的方法來執行此操作。這是方法(我認爲所有的名字都相當自我解釋,只問如果有什麼不明確):這對於碰撞檢測如何?

def collide(self,target): 
    result = False 
    for x in range(self.x,self.x+self.width): 
     if x in range(target.get_x(),target.get_x()+target.get_width()): 
      result = True 
    for y in range(self.y,self.y+self.height): 
     if y in range(target.get_y(),target.get_y()+target.get_height()): 
      result = True 
    return result 

提前感謝!

+4

如您所料,使用循環是進行碰撞檢測的低效方法。我會建議做一些圖紙,並提出一組條件,當[兩個矩形正在相交]時保持爲真(http://stackoverflow.com/questions/306316/determine-if-two-rectangles-overlap-each-其他)。 –

+1

您的代碼是否存在特定問題?或者您只是要求某人爲您制定等效但更快的解決方案? –

+0

我想看看其他解決方案,以便我可以提高我對Python的知識。 – reggaelizard

回答

4

碰撞檢測的問題是衆所周知的,所以我想,而不是猜測我可能會搜索一個使用衆所周知的搜索引擎的工作算法。事實證明,關於矩形重疊的優秀文獻不如您想象的那麼容易。我們向在此之前,或許我可以在您使用結構像

if x in range(target.get_x(),target.get_x()+target.get_width()): 

這是Python的信譽爲目的,你的想法的這樣一個明顯的表達實際上成功發表評論。你可能沒有意識到的是(無論如何,Python 2中)每次使用range()都會創建一個列表(在Python 3中,它會創建一個生成器並對其進行迭代;如果您不知道這意味着什麼,請接受這在計算方面稍微好一點)。我懷疑你可能指的是

if target.get_x() <= x < target.get_x()+target.get_width(): 

(我用開區間測試,以反映您的range()使用)這與兩個鏈式比較用N相等比較的優點。通過相對簡單的數學運算(減去從比較每學期target.get_x()),我們將其轉化成

if 0 <= x-target.get_x() < target.get_width(): 

不要忽視消除這些冗餘的方法調用的價值,但它往往是簡單的任務,爲救計算的表達式以後的參考。

當然,這推敲後我們必須以新的活力看

for x in range(self.x,self.x+self.width): 

這將設置一個下限和x上的上限,和你寫的不平等是對x的所有值假。然而,超越代碼達到算法的目的是值得的。因爲內部測試可能完成的任何點亮創建現在都會重複多次(按對象的寬度,準確而言)。我採取意譯

for x in range(self.x,self.x+self.width): 
    if x in range(target.get_x(),target.get_x()+target.get_width()): 
     result = True 

成僞代碼的自由:「如果self.x之間的任何x和self.x + self.width在於目標的x和目標的X +寬度之間,則物體碰撞」 。換句話說,兩個範圍是否重疊。但是你確實在做很多工作來找出答案。

此外,僅僅因爲兩個物體在x維中相撞並不意味着它們在空間中發生碰撞。事實上,如果他們不也碰撞在y維度則物體不相交,否則,你將評估這些矩形的碰撞:

+----+ 
| | 
| | 
+----+ 

    +----+ 
    | | 
    | | 
    +----+ 

所以,你要知道,如果他們在兩個維度上發生碰撞,不只是一個。理想情況下,人們會定義一個一維碰撞檢測(現在我們只是有...),然後應用於兩個維度。我也希望那些訪問函數可以被簡單的屬性訪問所取代,而我的代碼從現在開始假設是這樣。

走了這麼遠,現在可以快速看看this YouTube video中的原理,這使得幾何圖形相對清晰,但並不能很好地表達公式。只要您使用相同的座標系,它就可以很好地解釋這些原理。基本上,如果A的左側位於B的左側和右側之間,則兩個對象A和B水平重疊。如果B的權利在A的左側和右側之間,它們也重疊。兩種情況都可能是真實的,但在Python中,您應該考慮使用關鍵字or來避免不必要的比較。

所以,讓我們定義一個一維重疊功能:

def oned_ol(aleft, aright, bleft, bright): 
    return (aleft <= bright < aright) or (bleft <= aright < bright) 

我要欺騙,並使用這個兩個維度,因爲我的函數裏面不知道哪個維度的數據I CAM打電話它與。如果我是正確的,下面的配方應該做的:

def rect_overlap(self, target): 
    return oned_ol(self.x, self.x+self.width, target.x, target.x+target.width) \ 
     and oned_ol(self.y, self.y+self.height, target.y, target.y+target.height 

如果你堅持使用這些訪問器方法,你將不得不重新投放代碼,包括他們。我已經對1-D重疊函數進行了粗略測試,並且在rect_overlap上完全沒有,所以請讓我知道 - 注意事項。出現兩件事。

  1. 的代碼膚淺的檢查,可導致低能得無以算法的「優化」,所以有時它更好地回到第一的原則,並在你的算法更仔細地看。

  2. 如果您使用表達式作爲函數的參數,它們可以在函數體內按名稱使用,而無需進行明確的分配。

2
def collide(self, target): 

    # self left of target? 
    if x + self.width < target.x: 
     return False 

    # self right of target? 
    if x > target.x + target.width : 
     return False 

    # self above target? 
    if y + self.height < target.y: 
     return False 

    # self below target? 
    if y > target.y + target.height: 
     return False 

    return True 

類似的東西(取決於你的座標系上,即Y的正值向上或向下)