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

上一篇講解敵機、補給包坐搔、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)
運行效果

本篇就重點講解碰撞檢測原理和實現(xiàn)如庭,至此游戲主體部分也完成了,下一篇開始逐步完善游戲撼港,首先是增加背景和音效坪它。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市帝牡,隨后出現(xiàn)的幾起案子往毡,更是在濱河造成了極大的恐慌,老刑警劉巖靶溜,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件开瞭,死亡現(xiàn)場離奇詭異,居然都是意外死亡罩息,警方通過查閱死者的電腦和手機嗤详,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來瓷炮,“玉大人葱色,你說我怎么就攤上這事∧锵悖” “怎么了苍狰?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長烘绽。 經(jīng)常有香客問我淋昭,道長,這世上最難降的妖魔是什么诀姚? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任响牛,我火速辦了婚禮,結(jié)果婚禮上赫段,老公的妹妹穿的比我還像新娘呀打。我一直安慰自己,他們只是感情好糯笙,可當(dāng)我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布贬丛。 她就那樣靜靜地躺著,像睡著了一般给涕。 火紅的嫁衣襯著肌膚如雪豺憔。 梳的紋絲不亂的頭發(fā)上额获,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天,我揣著相機與錄音恭应,去河邊找鬼抄邀。 笑死,一個胖子當(dāng)著我的面吹牛昼榛,可吹牛的內(nèi)容都是我干的境肾。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼胆屿,長吁一口氣:“原來是場噩夢啊……” “哼奥喻!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起非迹,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤环鲤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后憎兽,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體冷离,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年唇兑,在試婚紗的時候發(fā)現(xiàn)自己被綠了酒朵。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡扎附,死狀恐怖蔫耽,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情留夜,我是刑警寧澤匙铡,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站碍粥,受9級特大地震影響鳖眼,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜嚼摩,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一钦讳、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧枕面,春花似錦愿卒、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至枕荞,卻和暖如春柜候,著一層夾襖步出監(jiān)牢的瞬間搞动,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工渣刷, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留鹦肿,地道東北人。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓辅柴,卻偏偏與公主長得像狮惜,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子碌识,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容