飛機大戰(zhàn)(pygame)開發(fā)實錄七

上一篇講解敵機、補給包、Boss的生成及控制。本篇就重點講解碰撞檢測原理和實現(xiàn)。


碰撞檢測原理

圖片在程序中都是矩形,我們看到的不規(guī)則形狀,只是透明效果。所以碰撞實際就是兩個矩形重疊。

碰撞檢測原理為矩形重疊
5種重疊

以圖中5種重疊為例,重疊部分的矩形坐標都會滿足

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ù),我們只要把需要檢測的兩個對象的坐標(minX, minY,maxX, maxY )傳入函數(shù)就可以了。
minX, minY 就是對象的x,y屬性,maxX, maxY 可以通過x,y和w,h屬性演算獲得。

圖片坐標獲取

然后把對象分成 敵機、敵機子彈、補給包 與 玩家飛機玩家飛機子彈與敵機 兩組,進行檢測。
這里,玩家飛機做了一個特殊處理。把機頭和機身分成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): #當前判斷的是敵機子彈,
                        del(objs[i])
                        if hero.invincible == False:
                            hero.hit = True
                    elif isinstance(objs[i],EnemyPlane): #當前判斷的是敵機
                        objs[i].hit = True
                        if hero.invincible == False:
                            hero.hit = True
                    elif isinstance(objs[i],RewardGoods): #當前判斷的是補給包
                        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)
運行效果

本篇就重點講解碰撞檢測原理和實現(xiàn),至此游戲主體部分也完成了,下一篇開始逐步完善游戲,首先是增加背景和音效。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容