2013-04-10 130 views
0

我一直在努力在概念上如何在遊戲中實現簡單的方形碰撞檢測我正在寫作,同時避免Pygame;我想學習如何做到而不是作弊。預期的程序結構看起來是這樣的: 遊戲加載一個包含關卡的文本文件。每個級別由25行25位數字(總共625位數字)組成。它被提取到二維數組中以模擬與屏幕相對應的笛卡爾網格。從那裏程序在屏幕上的適當位置繪製一個32x32塊。例如,如果位置[2] [5]處的數字是1,則它將在像素座標(96,192)處繪製白色正方形(由於它是數組,所以正方形的計數從零開始)。它還會爲與原始數組對應的每個位置生成一個由True或False組成的碰撞數組。抽象碰撞檢測

我有一個玩家對象,可以沿網格自由移動,不限於32x32的方格。我的問題是:我將如何實現方形碰撞檢測?我已經嘗試了很多方法,但我不太確定我卡在哪裏。我會發布我的最新化身和下面的相關代碼。

碰撞代碼:

def checkPlayerEnvCollision(self,player): 
    p = player 
    c = self.cLayer #this is the collision grid generated when loading the level 
    for row in range(25): 
     for col in range (25): 
      print("checkEnvCollision") 
      if c[row][col] != False: 
       tileleftx = row*32 
       tilerightx = tileleftx + 32 
       tilelefty = col*32 
       tilerighty = tilelefty+32 
       if (abs(tileleftx - p.x) * 2 < (tilerightx + (p.x + 32))) and (abs(tilelefty - p.y) * 2 < (tilerighty + (p.y + 32))): 
        print("OH NO, COLLISION") 

加載從文本文件中的地磚爲陣列的代碼:

def loadLevel(self, level): 
    print("Loading Level") 
    levelFile = open(level) 
    count=0 
    for line in levelFile: 
     tempArray = [] 
     if line.startswith("|"): 
      dirs = line.split('|') 
      self.north = dirs[1] 
      self.south = dirs[2] 
      self.east = dirs[3] 
      self.west = dirs[4] 
      continue 

     for item in line: 
      if item in self.tileValues: 
       tempArray.append(int(item)) 
     self.tileLayer[count] = tempArray 
     count+=1 
    for items in self.tileLayer: 
     if len(items) > 25: 
      print("Error: Loaded Level Too Large") 

    count = 0 
    for line in self.tileLayer: 
     tempArray = [] 
     for item in line: 
      if self.tilePassableValues[item] == False: 
       tempArray.append(False) 
      else: 
       tempArray.append(True) 
     self.collisionLayer[count] = tempArray 
     count += 1 

不知道這是有用的,但這裏是對一個簡單的演示繪圖方法:

def levelTiles(self, level): 
    row = 0 
    for t in level: 
     col = 0 
     for r in t: 
      color = "white" 
      if r == 0: 
       col+=1 
       continue 
      elif r == 1: 
       color = "red" 
      elif r == 2: 
       color = "white" 
      elif r == 3: 
       color = "green" 
      self.Canvas.create_rectangle(row*32, col*32, row*32+32, col*32+32, fill=color, width=1,tags='block') 
      col += 1 
     row += 1 

最後,這裏是我一直在測試它的文本文件:

1111111111111111111111111 
1222222222222222222222221 
1222222222222222222222221 
1222222222222222222222221 
1222222222222222222222221 
1222222222222222222222221 
1222233332222222222222221 
1222233332222222222222221 
1222222222222222222222221 
1222222222222222222222221 
1222222222222222222222221 
1222222222222222222222221 
1222222222222222222222221 
1222222222233332222222221 
1222222222333332332222221 
1222222222222222332222221 
1222222222222222332222221 
1222222222222222222222221 
1222222222222222222222221 
1222222222222222222222221 
1222222222222222222222221 
1222222222222222222222221 
1222222222222222222222221 
1222222222222222222222221 
1111111111111111111111111 
|onescreen2|onescreen2|onescreen2|onescreen2 

(最後一行是當到達關卡邊緣時將地圖加載到北,南,東,西的地圖;你可以忽略它。)

感謝您的幫助。要問很多,但我被困在這個問題上!

回答

0

如果玩家是聯繫在一起的電網,爲什麼不試網格位置:

if grid[player.x][player.y] == some_collidable_thing: 
    # there was a collision 

如果沒有,
我還提供了一個答案的東西在This question

def check_col(self, rect): 
    for row in self.cLayer: 
     for column in row: 
      grid_position = (row*element_size, column*element_width) 
      collide_x = False 
      collide_y = False 

      # check x axis for collision 
      if self.rect.x + self.rect.w > grid_position[0]: 
       collide_x = True 
      elif self.rect.x < grid_position[0] + element_width: 
       collide_x = True 

      # check y axis for collision 
      if self.rect.y < grid_position[1] + element_height: 
       collide_y = True 
      elif self.rect.y + self.rect.h > grid_position[1]: 
       collide_y = True 

      # act on a collision on both axis 
      if collide_x and collide_y: 
       # act on the collision 
       return True 
      else: 
       # act on no collision 
       return False 
+0

我沒有直接測試網格的位置,因爲如果玩家正在向下移動,它將不會註冊碰撞,直到它一直在可碰撞的正方形中,因爲它們是從tkinter的左上角繪製的。我會檢查你發佈的第二個!謝謝回覆。 – 2013-04-10 01:02:39

+0

請注意,通過使用equalities而不是if/else語句,這段代碼可以被簡化很多。例如(不是平等,但它提供了正確的想法),最後四行可以寫成「return collide_x和collide_y」。 – 2013-04-10 01:04:43

+0

無意中刪除了我說方法1需要連接到網格的玩家的部分,方法2應該適合您。另外,是的,代碼可以做得更好一點,但是如果你願意,你所描述的將會消除任何對函數中的碰撞採取行動的能力。 – Serdalis 2013-04-10 01:05:50

0
幾乎相同

一個更簡單的方法是爲玩家的移動定義向量,併爲對象的邊界定義線條。然後你檢查矢量是否與任何一條線(不應該有多條線檢查)碰撞(我假設玩家/對象可以在另一個對象的邊界上):

Take由檢查碰撞的直線的運動矢量和終點形成的三角形的行列式,並通過行列式取其區域。比較它的面積與另一個端點形成的三角形的面積。如果它們都是正面/負面,那麼就沒有交集。如果他們的標誌不同,那麼有可能是一個十字路口。

如果它們的符號不同,除了使用運動向量的端點而不是線的端點外,請執行與上面相同的操作。 (並用整條線代替運動矢量)。

如果他們的標誌不同,那麼肯定有一個交叉點,如果他們是相同的,那麼就沒有交集。

我希望這有助於(如果沒有意義,只是評論)。