上一篇講解敵機、補給包坐搔、Boss的生成及控制。本篇就重點講解碰撞檢測原理和實現(xiàn)敬矩。
碰撞檢測原理
圖片在程序中都是矩形概行,我們看到的不規(guī)則形狀,只是透明效果弧岳。所以碰撞實際就是兩個矩形重疊凳忙。
碰撞檢測原理為矩形重疊
5種重疊
以圖中5種重疊為例,重疊部分的矩形坐標(biāo)都會滿足
minX = max(minX1, minX2)
minY = max(minY1, minY2)
maxX = min(maxX1, maxX2)
maxY = min(maxY1, maxY2)
所以只要要判斷這個矩形成立禽炬,即重疊涧卵。
矩形碰撞測試
def CollideTest(postion1, postion2): #碰撞檢測
minX1, minY1,maxX1, maxY1 = postion1
minX2, minY2,maxX2, maxY2 = postion2
minX = max(minX1, minX2)
minY = max(minY1, minY2)
maxX = min(maxX1, maxX2)
maxY = min(maxY1, maxY2)
if (minX < maxX) and (minY < maxY):
return True
else:
return False
有了這個函數(shù),我們只要把需要檢測的兩個對象的坐標(biāo)(minX, minY,maxX, maxY )
傳入函數(shù)就可以了腹尖。
minX, minY
就是對象的x,y屬性柳恐,maxX, maxY
可以通過x,y和w,h屬性演算獲得。
圖片坐標(biāo)獲取
然后把對象分成
敵機热幔、敵機子彈乐设、補給包 與 玩家飛機
和 玩家飛機子彈與敵機
兩組,進(jìn)行檢測绎巨。這里近尚,玩家飛機做了一個特殊處理。把機頭和機身分成1,2兩個區(qū)域來做碰撞測試场勤,這樣3,4區(qū)域不會參與碰撞檢測肿男。
玩家飛機碰撞檢測
碰撞測試
def IsCollide(hero, enemyplanes, Bullets, EnemyBullets, Rewards):
if hero.live > 0 :
# 敵機介汹、敵機子彈、補給包 與 玩家飛機的 碰撞檢測
enemyObj = [enemyplanes, EnemyBullets, Rewards]
for objs in enemyObj:
for i in range(len(objs) - 1, -1, -1):
postion1 = (objs[i].x, objs[i].y, objs[i].x + objs[i].w, objs[i].y + objs[i].h) #(x1,y1,x2,y2)定位矩形區(qū)域
postion2 = (hero.x + hero.w / 3, hero.y, hero.x + hero.w * 2 / 3, hero.y + hero.h / 4) #機頭部分
postion3 = (hero.x, hero.y + hero.h / 4, hero.x + hero.w, hero.y + hero.h) # 機身部分
if CollideTest(postion1, postion2) or CollideTest(postion1, postion3):
PlaySound(Sound_Hit)
if isinstance(objs[i],EnemyBullet): #當(dāng)前判斷的是敵機子彈舶沛,
del(objs[i])
if hero.invincible == False:
hero.hit = True
elif isinstance(objs[i],EnemyPlane): #當(dāng)前判斷的是敵機
objs[i].hit = True
if hero.invincible == False:
hero.hit = True
elif isinstance(objs[i],RewardGoods): #當(dāng)前判斷的是補給包
hero.bulletType = objs[i].RewardItem
del(objs[i])
# 子彈和敵機碰撞檢測
for i in range(len(Bullets) - 1,-1, -1):
for k in range(len(enemyplanes) -1,-1,-1):
postion1 = (Bullets[i].x,Bullets[i].y,Bullets[i].x+Bullets[i].w,Bullets[i].y+Bullets[i].h)
postion2 = (enemyplanes[k].x, enemyplanes[k].y, enemyplanes[k].x + enemyplanes[k].w, enemyplanes[k].y + enemyplanes[k].h)
if CollideTest(postion1, postion2):
del(Bullets[i])
enemyplanes[k].hit = True
break
帶補給包的敵機,被摧毀會刷新補給包窗价。需要先創(chuàng)建補給包的類 RewardGoods
class RewardGoods(Base):
def __init__(self, pygame_screen, postion, image_name, RewardItem):
Base.__init__(self, pygame_screen, postion, image_name)
self.RewardItem = RewardItem
def move(self):
self.y += 1
def display(self):
self.screen.blit(self.image, (self.x, self.y))
更新Main()
def Main():
pygame.init()
scores = 0
screen = pygame.display.set_mode((480, 852), 0, 32)
# 添加背景
Bg = BackGround(screen, Image_Background, 'dynamic')
bullets = []
rewards = []
#添加測試敵機
enemyBullets = []
enemyPlanes = []
enemyPlanes.append(EnemyPlane(screen,enemyBullets))
enemyPlanes.append(BossPlane(screen,enemyBullets))
enemyPlanes.append(RewardPlane(screen, enemyBullets,'shotbullet'))
hero = HeroPlane(screen, bullets)
while True:
Bg.display()
hero.move() #生成飛機移動后位置
hero.bulletCoolDown() # 玩家飛機子彈冷卻
hero.fire() # 玩家飛機發(fā)射子彈
hero.display() #繪制玩家飛機
# 在列表中清除被消滅的敵機
for i in range(len(enemyPlanes) - 1, -1, -1):
if enemyPlanes[i].live == 0 and enemyPlanes[i].hit == False:
if enemyPlanes[i].reward == "shotbullet": # 敵機如果附帶獎勵
rewards.append(RewardGoods(screen, (enemyPlanes[i].x, enemyPlanes[i].y), Image_Reward2, "shotbullet"))
elif enemyPlanes[i].reward == "doublebullet": # 敵機如果附帶獎勵
rewards.append(RewardGoods(screen, (enemyPlanes[i].x, enemyPlanes[i].y), Image_Reward1, "doublebullet"))
scores += enemyPlanes[i].score
del (enemyPlanes[i])
# 更新敵機狀態(tài)
for enemy in enemyPlanes:
enemy.bulletCoolDown()
enemy.move()
enemy.fire()
enemy.display()
# 刷新獎勵補給包
for Reward in rewards:
Reward.move()
Reward.display()
# IsOverBound(Bullets, EnemyBullets, enemyplanes, Rewards)
IsOverBound(bullets,enemyBullets,enemyPlanes)
# 碰撞檢測
IsCollide(hero, enemyPlanes, bullets, enemyBullets, rewards)
pygame.display.update()
MainControl(hero, screen)
運行效果