實作精靈碰撞偵測的三種方式,以及如何移除精靈
訂閱 375
Pygame 實作碰撞偵測(Sprite 精靈、Group 精靈組),以及精靈組移除精靈的方式影片示範 YouTube
前言
在遊戲開發過程中,碰撞偵測是一個常見且關鍵的技術問題。無論是判斷道具撿取、子彈擊中目標,還是角色與環境互動,都需要可靠的碰撞偵測機製。Python 的 Pygame 通過其sprite
模組,為開發者提供了強大的遊戲精靈(Sprite
)碰撞偵測功能。
本文將講解 Pygame 中三種主要的碰撞偵測方式:精靈與精靈之間、精靈與精靈組之間,以及精靈組與精靈組之間的碰撞偵測,並詳細介紹移除精靈的多種方法。
範例準備
為了示範各種碰撞偵測技術,我們組建了一個簡單的遊戲案例。在這個案例中,玩家可以通過點選滑鼠右鍵,在滑鼠位置建立鐳射(Laser
)物件,並與案例中的糖果(Candy
)和門(Door
)進行互動。
# 定義三個精靈類別
class Candy(pygame.sprite.Sprite):
pass # 具體實作省略
class Laser(pygame.sprite.Sprite):
pass # 具體實作省略
class Door(pygame.sprite.Sprite):
pass # 具體實作省略
# 建立對應的精靈組
cs = pygame.sprite.Group() # Candy 精靈組
ls = pygame.sprite.Group() # Laser 精靈組
Pygame 中的碰撞偵測
Pygame 中所有Sprite
物件都擁有一個rect
變數,這個矩形不僅表示精靈的位置和大小,同時也作為預設的碰撞偵測區域。值得註意的是,理想情況下碰撞偵測區域應小於精靈的影像,並位於影像中心,以獲得更真實的碰撞效果。但在本文的範例中,我們直接使用精靈表面物件建立的矩形作為碰撞區域,這可能導致碰撞現象看起來不太「真實」。
碰撞偵測方式一:精靈與精靈之間
sprite
模組提供的collide_rect
函式,可以實作兩個精靈物件之間的碰撞偵測。
collide_rect(left, right)
- left,right 參數
參與檢測的兩個精靈物件。
- 傳回值
如果兩個精靈的碰撞偵測區域(
rect
變數)有重疊部分,則傳回True
,否則傳回False
。
Group
物件的sprites
方法傳回一個包含組中所有精靈的串列。
當檢測到碰撞時,呼叫精靈的kill
方法會將該精靈從所有包含他的精靈組中移除。由於範例通過精靈組來更新和繪製所有鐳射,被移除的鐳射會從遊戲視窗中消失,其update
方法也不再被呼叫。
# 周遊所有鐳射精靈
for l in ls.sprites():
# 檢測鐳射與門的碰撞
if pygame.sprite.collide_rect(l, door):
l.kill() # 從所有包含該精靈的組中移除精靈
碰撞偵測方式二:精靈與精靈組之間
sprite
模組提供的spritecollide
函式,可用於檢測精靈與精靈組中所有精靈的碰撞。
spritecollide(sprite, group, dokill, collided=None)
- sprite 參數
參與檢測的精靈物件。
- group 參數
參與檢測的精靈組。
- dokill 參數
布林值,決定是否自動移除精靈組中被碰撞的精靈。
- 傳回值
傳回一個串列,包含了精靈組中與指定精靈發生碰撞的所有精靈。
在這個範例中,我們將dokill
設為False
,然後手動處理碰撞後的移除操作。Sprite
物件的remove
方法可以從指定精靈組中移除精靈,Group
物件的remove
方法可以從精靈組中移除指定的精靈。
for l in ls.sprites():
# 檢測鐳射與糖果組的碰撞,但不自動移除
rcs = pygame.sprite.spritecollide(l, cs, False)
if rcs: # 如果發生碰撞
l.remove(ls) # 手動從鐳射組中移除鐳射
cs.remove(rcs) # 從糖果組中移除所有碰撞的糖果
碰撞偵測方式三:精靈組與精靈組之間
sprite
模組提供的groupcollide
函式,可用於檢測兩個精靈組之間的碰撞。
groupcollide(groupa, groupb, dokilla, dokillb, collided=None)
- groupa,groupb 參數
參與檢測的兩個精靈組。
- dokilla,dokillb 參數
布林值,決定是否自動移除各自組中被碰撞的精靈。
- 傳回值
字典,鍵是第一個組中被碰撞的精靈,值是一個串列,包含了第二個組中與該精靈碰撞的所有精靈。
這種方式比較簡潔,特別適合處理大量需要相互檢測的物件,如子彈與敵人群體之間的碰撞。
# 檢測鐳射組與糖果組的碰撞,自動移除碰撞的精靈和糖果
pygame.sprite.groupcollide(ls, cs, True, True)
精靈移除方法
Sprite
和Group
物件提供了多種移除精靈的方式,當然,你也可以通過碰撞偵測函式的相關參數自動移除精靈。
kill
方法,由Sprite
物件呼叫,可從所有包含該精靈的組中移除精靈。
sprite.kill()
remove
方法,由Sprite
或Group
物件呼叫,可從指定組中移除精靈,或從組中移除指定精靈。
sprite.remove(*groups)
group.remove(*sprites)
- groups 參數
可變參數
groups
所包含的位置參數,可以是Group
精靈組物件,或巢狀包含Group
物件的序列物件。- sprites 參數
可變參數
sprites
所包含的位置參數,可以是Sprite
精靈物件,或巢狀包含Sprite
物件的序列物件。
結論
Pygame 的sprite
模組提供了全面而靈活的碰撞偵測機製,開發者可以根據具體需求選擇最適合的檢測方式。