飛機(jī)大戰(zhàn)(pygame)開發(fā)實(shí)錄五

上一篇講解了動態(tài)背景,并創(chuàng)建了飛機(jī)的基類啸澡。本篇繼續(xù)講解玩家飛機(jī)類的創(chuàng)建及其控制方法飞崖。


class HeroPlane(BasePlane):
    def __init__(self, pygame_screen, bullets):
        BasePlane.__init__(self, pygame_screen, (210, 700), Image_HeroPlane, 5, bullets)
        self.moveToLeft = False  # 控制玩家飛機(jī)移動位置
        self.moveToRight = False
        self.moveToUp = False
        self.moveToDown = False
        self.keepFire = False
        self.moveSpeed = 3
        self.health = 6
        self.maxHealth = 6
        self.live = 5
        self.invincible = True
        self.invincibleTime = 400  # 無敵時(shí)間
        self.invincibleTiming = 0  # 無敵倒計(jì)時(shí)
        self.bulletType = "normal"
        self.__crate_images()  # 添加爆炸動畫圖片組
    def __crate_images(self):
        for i in range(4):
            self.bombList.append(pygame.image.load("./res/hero_blowup_n" + str(i + 1) + ".png"))
    def move(self):
        self.image = pygame.image.load(Image_HeroPlane)  # 飛機(jī)普通狀態(tài)顯示的圖片
        if self.moveToRight and self.x < 480 - self.w:  # 移動越界判斷
            self.x += self.moveSpeed
        if self.moveToLeft and self.x > self.moveSpeed:
            self.x -= self.moveSpeed
        if self.moveToDown and self.y < 852 - self.h:
            self.y += self.moveSpeed
        if self.moveToUp and self.y > self.moveSpeed:
            self.image = pygame.image.load(Image_HeroPlaneUp)  # 飛機(jī)往前飛狀態(tài)顯示的圖片
            self.y -= self.moveSpeed
    def fire(self):
        # 玩家飛機(jī)開火
        if self.keepFire and self.bulletCdOk:
            #PlaySound(Sound_HeroFire)
            if self.bulletType == "normal":
                self.bulletList.append(Bullet(self.screen, (self.x + (self.w / 2) - 2, self.y - 2), "line"))
            elif self.bulletType == "doublebullet":
                self.bulletList.append(Bullet(self.screen, (self.x + (self.w / 2) - 34, self.y + 20), "line"))
                self.bulletList.append(Bullet(self.screen, (self.x + (self.w / 2) + 28, self.y + 20), "line"))
            elif self.bulletType == "shotbullet":
                self.bulletList.append(Bullet(self.screen, (self.x + (self.w / 2) - 34, self.y + 20), "Lbiasline"))
                self.bulletList.append(Bullet(self.screen, (self.x + (self.w / 2) + 28, self.y + 20), "Rbiasline"))
                self.bulletList.append(Bullet(self.screen, (self.x + (self.w / 2) - 2, self.y - 2), "line"))
            self.bulletCoolDownstate = 1
            self.bulletCdOk = False
    def display(self):
        if self.invincible:
            self.invincibleTiming += 1
            if self.invincibleTiming == self.invincibleTime:
                # 無敵時(shí)間到
                self.invincibleTiming = 0
                self.invincible = False
            else:
                # 無敵倒計(jì)時(shí)顯示
                fontColor = (80, 80, 80)
                fontObj = pygame.font.Font(Font_Consola, 18)
                showinvincibleTiming = fontObj.render(
                    str(int((self.invincibleTime - self.invincibleTiming) // (self.invincibleTime / 10))), True,
                    fontColor)
                showinvincibleTimingObj = showinvincibleTiming.get_rect()
                showinvincibleTimingObj.center = (self.x - 5, self.y + 20)
                self.screen.blit(showinvincibleTiming, showinvincibleTimingObj)
        BasePlane.display(self)
        # 血條顯示
        for i in range(self.health):
            self.screen.blit(self.healthImage, (self.x - 10, self.y + self.h - 44 - i * 9))            
class BaseBullet(Base):
    def display(self):
        self.screen.blit(self.image, (self.x, self.y))
class Bullet(BaseBullet): #玩家飛機(jī)子彈
    def __init__(self, pygame_screen,postion,movingpath):
        Base.__init__(self, pygame_screen, postion, Image_HeroBullet)
        self.movingPath = movingpath  #子彈飛行路線
    def move(self):
        if self.movingPath == "line":
           self.y -= 10
        elif self.movingPath == "Lbiasline":
            self.y -= 10
            self.x -= 3
        elif self.movingPath == "Rbiasline":
            self.y -= 10
            self.x += 3
class EnemyBullet(BaseBullet): #敵機(jī)子彈
    def __init__(self, pygame_screen, postion):
        Base.__init__(self, pygame_screen,postion, Image_EnemyBullet)
    def move(self):
        self.y += 4
    def __str__(self):
        return isinstance()
創(chuàng)建飛機(jī)對象需要傳入子彈對象,所以這里把子彈類的代碼也一起發(fā)了上來德撬。

玩家飛機(jī)繼承基類 BasePlane 的基礎(chǔ)上铲咨,增加了一些特有屬性和方法:
moveTo... 4 個(gè)屬性分別存儲移動方向。
invincible 用來保存無敵狀態(tài)蜓洪,玩家飛機(jī)刷新時(shí)有一個(gè)無敵時(shí)間纤勒,避免一刷新就被子彈打中,玩家沒有反應(yīng)時(shí)間隆檀。

無敵倒計(jì)時(shí)


接下來要添加系統(tǒng)事件控制函數(shù):包含對飛機(jī)移動摇天、窗口關(guān)閉按鈕粹湃、按鈕的控制。

# 相應(yīng)鍵盤泉坐、鼠標(biāo)为鳄、窗口關(guān)閉按鈕等
def MainControl(hero, pygame_screen, *params):
    if len(params) > 1:
        cbsound = params[0]
        cbmusic = params[1]
    else:
        cbsound = False
        cbmusic = False
    for event in pygame.event.get():
        if event.type == QUIT:  # 判斷是否是點(diǎn)擊了退出按鈕
            exit()
        if event.type == KEYDOWN and hero.live > 0:  # 鍵盤按鍵按下,玩家飛機(jī)掛了腕让,就不相應(yīng)了
            if event.key == K_a or event.key == K_LEFT:
                hero.moveToLeft = True
            elif event.key == K_d or event.key == K_RIGHT:
                hero.moveToRight = True
            elif event.key == K_w or event.key == K_UP:
                hero.moveToUp = True
            elif event.key == K_s or event.key == K_DOWN:
                hero.moveToDown = True
            elif event.key == K_SPACE:
                hero.keepFire = True
            elif event.key == K_ESCAPE:
                return Paused(pygame_screen)
        elif event.type == KEYUP:  # 鍵盤按鍵彈起
            if event.key == K_a or event.key == K_LEFT:
                hero.moveToLeft = False
            elif event.key == K_d or event.key == K_RIGHT:
                hero.moveToRight = False
            elif event.key == K_w or event.key == K_UP:
                hero.moveToUp = False
            elif event.key == K_s or event.key == K_DOWN:
                hero.moveToDown = False
            elif event.key == K_SPACE:
                hero.keepFire = False
        if cbmusic:
            if event.type == pygame.MOUSEBUTTONDOWN and cbmusic.isOver():  # 關(guān)閉背景音樂
                if pygame.mixer.music.get_busy() == 1:
                    pygame.mixer.music.stop()
                else:
                    pygame.mixer.music.play(-1, 0)
        if cbsound:
            if event.type == pygame.MOUSEBUTTONDOWN and cbsound.isOver():  # 關(guān)閉音效
                global Sound_IsPlay  # 修改全局變量
                Sound_IsPlay = False if Sound_IsPlay else True  # 三目運(yùn)算孤钦,更加簡潔
    return ''

pygame.event.get() 獲取系統(tǒng)事件,返回的是Event對象,比如按鍵彈起事件

<Event(3-KeyUp {'key': 276, 'mod': 0, 'scancode': 75, 'window': None})>

通過 event.typeevent.key兩個(gè)屬性就可以判斷玩家對按鍵做了什么操作纯丸,然后修改HeroPlane 對象偏形,飛機(jī)移動的相關(guān)屬性,這樣飛機(jī)調(diào)用move 方法就會對應(yīng)的改變飛機(jī)坐標(biāo)液南,從而達(dá)到控制的目的壳猜。


更新 Main()函數(shù),添加飛機(jī)相關(guān)控制方法的調(diào)用

def main():
    pygame.init()
    screen = pygame.display.set_mode((480, 852), 0, 32)
    # 添加背景
    Bg = BackGround(screen, Image_Background, 'dynamic')
    Bullets = []
    hero = HeroPlane(screen, Bullets)
    while True:
        Bg.display()
        hero.move()  #生成飛機(jī)移動后位置
        hero.bulletCoolDown()  # 玩家飛機(jī)子彈冷卻       
        hero.fire()        # 玩家飛機(jī)發(fā)射子彈
        hero.display()        #繪制玩家飛機(jī)       
        pygame.display.update()
        MainControl(hero, screen)

運(yùn)行腳本就可以控制玩家飛機(jī)了滑凉,不過仍然沒有顯示子彈统扳,因?yàn)闆]有調(diào)用子彈的 movedisplay 方法。


子彈畅姊、敵機(jī)咒钟、補(bǔ)給包,都有一個(gè)越界問題若未,就是飛出了顯示區(qū)域朱嘴,所以我們把 movedisplay 方法調(diào)用封裝到一個(gè)IsOverBound函數(shù)中和越界判斷一起處理。

def IsOverBound(*params):  # 判斷子彈粗合、敵機(jī)是否越界,包括子彈移動
    if len(params) < 1:
        return
    objGroup = [param for param in params]
    for objs in objGroup:
        for index in range(len(objs) - 1, -1, -1):
            if objs[index].y > Screen_Height or objs[index].y < - 20:
                del (objs[index])
            else:
                if isinstance(objs[index], EnemyBullet) or isinstance(objs[index], Bullet):  # 當(dāng)前判斷的是敵機(jī)子彈萍嬉,
                    objs[index].move()
                    objs[index].display()

def IsOverBound(*params) 這里用到不定參數(shù),因?yàn)檫@個(gè)函數(shù)包括了敵機(jī)隙疚、補(bǔ)給包的判斷壤追,但這兩個(gè)對象我們還沒有創(chuàng)建,如果固定的參數(shù)就無法對子彈進(jìn)行調(diào)試供屉。
isinstance(objs[index], EnemyBullet) 通過isinstance函數(shù)來判斷行冰,當(dāng)前處理的是哪個(gè)對象,來進(jìn)行差異控制伶丐。
Main() 函數(shù)中添加調(diào)用 IsOverBound(Bullets)悼做,再次運(yùn)行,就可以控制飛機(jī)移動并發(fā)射子彈了哗魂。

玩家飛機(jī)控制效果


本篇講解玩家飛機(jī)控制方法,以及子彈越界判斷肛走。下一篇繼續(xù)講解敵機(jī)、補(bǔ)給包录别、Boss的生成及控制羹与。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末故硅,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子纵搁,更是在濱河造成了極大的恐慌,老刑警劉巖往踢,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件腾誉,死亡現(xiàn)場離奇詭異,居然都是意外死亡峻呕,警方通過查閱死者的電腦和手機(jī)利职,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來瘦癌,“玉大人猪贪,你說我怎么就攤上這事⊙端剑” “怎么了热押?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵,是天一觀的道長斤寇。 經(jīng)常有香客問我桶癣,道長,這世上最難降的妖魔是什么娘锁? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任牙寞,我火速辦了婚禮,結(jié)果婚禮上莫秆,老公的妹妹穿的比我還像新娘间雀。我一直安慰自己,他們只是感情好镊屎,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布惹挟。 她就那樣靜靜地躺著,像睡著了一般杯道。 火紅的嫁衣襯著肌膚如雪匪煌。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天党巾,我揣著相機(jī)與錄音萎庭,去河邊找鬼。 笑死齿拂,一個(gè)胖子當(dāng)著我的面吹牛驳规,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播署海,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼吗购,長吁一口氣:“原來是場噩夢啊……” “哼医男!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起捻勉,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤镀梭,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后踱启,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體报账,經(jīng)...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年埠偿,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了透罢。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,605評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡冠蒋,死狀恐怖羽圃,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情抖剿,我是刑警寧澤朽寞,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站牙躺,受9級特大地震影響愁憔,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜孽拷,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一吨掌、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧脓恕,春花似錦膜宋、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至乃秀,卻和暖如春肛著,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背跺讯。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工枢贿, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人刀脏。 一個(gè)月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓局荚,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子耀态,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評論 2 348

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