【pygame】面向對象實現(xiàn)飛機大戰(zhàn)(附完整代碼)

【寫在前面】:本人在網(wǎng)上,似乎還沒有找到關于飛機大戰(zhàn)的完整程序。基本都是講了一些比較瑣碎的小知識點。那么本篇文章呢,是使用pygame 通過面向對象的方式實現(xiàn)的“飛機大戰(zhàn)”的完整程序的串講。

【文章特點】主要是夠【硬核】,夠【詳實】。文末附有完整的本項目所有內容的GitHub地址...

【特點介紹】

  • 設置游戲背景;

  • 設置游戲背景音樂;

  • 設置了游戲名稱“外星人入侵”;

  • 設置了積分裝置(左上角);

  • 設置了玩家的生命值(右上角);

  • 設置了兩種道具(powerup)和(liveup);

  • 設置了我方戰(zhàn)機三種攻擊模式(吃了道具后,模型轉變(持續(xù)時間:5秒));

  • 設置了敵機的隨機產(chǎn)生,以及敵機子彈的隨機發(fā)射;

  • 我方戰(zhàn)機死亡后,游戲界面轉變;

  • 我方戰(zhàn)機死亡后,可選擇【重新游戲】和【游戲結束】

  • ......


【是否拭目以待了呢?】
先來看一下游戲的運行結果吧!


游戲開始

火力升級【power up】


【power up】

火力升級【power up(MAX)】


【power up(MAX)】

【死亡后界面跳轉】


死亡后界面跳轉-圖例

看著醬紫的界面,是否有玩一局的沖動呢?

再一次游戲【once again】

再一次游戲-圖例

下面進入正題

先提一下:什么是游戲循環(huán)?

每個游戲的核心都是一個循環(huán),將其稱為“游戲循環(huán)”。這個循環(huán)一直在不斷運行,一遍又一遍地完成游戲工作所需的所有事情。每次循環(huán)顯示一次游戲當前畫面,稱為幀。


【本文主要有以下10個模塊】

  • App.py文件

  • hero.py文件

  • Npc.py文件

  • bullet.py文件

  • prop.py文件

  • hit.py文件

  • information.py文件

  • music.py文件

  • setting.py文件

  • setup.py文件


關于App.py文件

【作用如下】

  • 啟動pygame;

  • 確定游戲界面;

  • 設置幀率

  • 設置游戲名稱;

  • 設置游戲背景;

  • 設置游戲背景音樂;

  • 【調用各個模塊來豐富游戲功能】

  • 游戲關閉;

# @Author  : Zurich.Alcazar
# @Email   : 1178824808@qq.com
# @File    : App.py
# @Software: PyCharm

import pygame
import sys
import hero
import os.path as path
import setting
from information import DataBus
from Npc import EnermyFactory
from Npc import Button
from prop import PropFactory
import hit
# import music

class App:

    def start(self):
        pygame.init()    # 啟動pygame
        pygame.mixer.init()
        # 確定游戲界面
        screen = pygame.display.set_mode((400, 600))

        # 設置幀率
        clock = pygame.time.Clock()
        bus = DataBus()
        # 設置游戲名稱
        pygame.display.set_caption("外星人入侵")
        # 設置游戲背景
        # bg_img = pygame.image.load(path.join(setting.img_folder, "background.png")).convert()
        bg_img = pygame.image.load(path.join(setting.img_folder, "789.jpg")).convert()
        # bg_img = pygame.image.load(path.join(setting.img_folder, "888.png")).convert()
        screen.blit(bg_img,(0,0))

        # 設置游戲背景音樂
        bgm = pygame.mixer.Sound(path.join(setting.snd_folder,'game_music.ogg'))
        bgm.set_volume(0.5)
        bgm.play(loops = -1)
        # 調用

        ef = EnermyFactory()
        pp = PropFactory()
        transColor = pygame.Color(0, 0, 0)
        player_img = pygame.image.load(path.join(setting.img_folder, "me1.png")).convert()

        player_mini_img = pygame.transform.scale(player_img, (25, 30))
        player_mini_img.set_colorkey(transColor)

        game_font = pygame.font.SysFont('arial', 24, True)


        # 讓渲染結果一次顯示
        pygame.display.flip()

        while True:
            screen.blit(bg_img, (0, 0))
            clock.tick(30)
            if not bus.is_game_over:
                # 制造敵機
                ef.generate_enermy()
                # 制造道具
                pp.generate_bomb_prop()
                pp.generate_bullet_prop()

                # 更新坐標(核心)
                bus.all_sprites.update()
                # 映射到屏幕
                bus.all_sprites.draw(screen)
                # 碰撞檢測: 玩家子彈和敵機
                bus.game_helper.collision()
                screen.blit(game_font.render(u'%d' % bus.score, True, [255, 0, 0]), [20, 20])
                hero.Hero.draw_lives(screen, 300, 20, 3, player_mini_img)

                # 讓渲染結果一次顯示
                pygame.display.flip()

            if bus.is_game_over:
                bg_img = pygame.image.load(path.join(setting.img_folder, "888.png")).convert()
                screen.blit(bg_img, (0, 0))
                bus.game_helper.draw_game_over_view()

            bus.all_sprites.draw(screen)
            pygame.display.flip()


            for event in pygame.event.get():
                if event.type == pygame.QUIT:  # 游戲關閉
                    sys.exit()

App().start()

關于hero.py文件

【作用】:定義英雄的各種功能(移動、發(fā)射子彈等等)

  • 定義初始位置;

  • 定義子彈發(fā)射音效;

  • 彈延時(效果);

  • 我方戰(zhàn)機生命值;

  • 是否觸碰游戲邊界【檢查】;

  • 等級提升,火力升級【powerup】;

  • 戰(zhàn)機隱藏;

  • 我方戰(zhàn)機爆炸(此功能尚未實現(xiàn));

# @Author  : Zurich.Alcazar
# @Email   : 1178824808@qq.com
# @File    : hero.py
# @Software: PyCharm
import pygame
from pygame.sprite import Sprite
import os.path as path
import setting
from bullet import HeroBullet
from bullet import HeroBullet2
import information as info

class Hero(Sprite):
    def __init__(self):
        super().__init__()

        image = pygame.image.load(path.join(setting.img_folder,"me1.png"))
        self.image = pygame.transform.scale(image,(51,60))
        # 定義初始位置
        self.rect = self.image.get_rect()
        self.rect.center = (setting.SCREEN_WIDTH - 200,setting.SCREEN_HEIGHT - 80)
        self.bus = info.DataBus()
        # 定義子彈發(fā)射音效
        self.shoot_sud = pygame.mixer.Sound(path.join(setting.snd_folder,"bullet.wav"))
        self.shoot_sud.set_volume(0.8)
        # self.clock = pygame.time.Clock()
        # 子彈延時(效果)
        self.shoot_delay = 500
        self.last_shoot_time = pygame.time.get_ticks()
        self.power = 1
        self.POWERUP_TIME = 5000
        self.power_time = pygame.time.get_ticks()
        # 我方戰(zhàn)機生命值
        self.lives = 3
        self.hidden = False
        self.hide_timer = pygame.time.get_ticks()

        player_img = pygame.image.load(path.join(setting.img_folder, "me1.png")).convert()
        player_mini_img = pygame.transform.scale(player_img, (25, 30))
        player_mini_img.set_colorkey()



    def update(self, *args):
        speed = 10
        keystate = pygame.key.get_pressed()
        if (keystate[pygame.K_LEFT] or keystate[pygame.K_a]):
            self.rect.x -= speed
        if keystate[pygame.K_RIGHT] or keystate[pygame.K_d]:
            self.rect.x += speed
        if keystate[pygame.K_UP] or keystate[pygame.K_w]:
            self.rect.y -= speed
        if keystate[pygame.K_DOWN] or keystate[pygame.K_s]:
            self.rect.y += speed
        # if keystate[pygame.K_SPACE]:  # 空格鍵 射擊
        if self.power == 1:
            self.shoot()
        if self.power == 2:
            self.powershoot()
        if self.power >= 3:
            self.superpower()
        # 戰(zhàn)機復活影藏
        if self.hidden and pygame.time.get_ticks() - self.hide_timer > 1000:
            self.hidden = False
            self.rect.centerx = setting.SCREEN_WIDTH / 2
            self.rect.bottom = setting.SCREEN_HEIGHT - 80


        # 邊界檢查
        if self.rect.right > setting.SCREEN_WIDTH:
            self.rect.right = setting.SCREEN_WIDTH
        if self.rect.left < 0:
            self.rect.left = 0
        if self.rect.top < 0:
            self.rect.top = 0
        if self.rect.bottom > setting.SCREEN_HEIGHT:
            self.rect.bottom = setting.SCREEN_HEIGHT

        if self.power >= 2 and pygame.time.get_ticks() - self.power_time > self.POWERUP_TIME:
            self.power -= 1
            self.power_time = pygame.time.get_ticks()

    # 生命值減少
    def Lives(self):
        self.lives -= 1

    # 等級提升
    def powerup(self):
        self.power += 1
        self.power_time = pygame.time.get_ticks()

    # 戰(zhàn)機隱藏
    def hide(self):
        # hide the player temporarily

        self.hidden = True
        self.hide_timer = pygame.time.get_ticks()
        self.rect.center = (setting.SCREEN_WIDTH/ 2, setting.SCREEN_HEIGHT + 200)



    def shoot(self):
        now = pygame.time.get_ticks()
        if now - self.last_shoot_time > self.shoot_delay:
            self.last_shoot_time = now

            bullet = HeroBullet(self.rect.centerx, self.rect.top)
            self.shoot_sud.play()
            self.bus.add_sprite(bullet)
            self.bus.add_hero_bullet(bullet)

    # 火力升級
    def powershoot(self):
        now = pygame.time.get_ticks()
        if now - self.last_shoot_time > self.shoot_delay:
            self.last_shoot_time = now

            bullet1 = HeroBullet(self.rect.left + 15, self.rect.top)
            bullet2 = HeroBullet(self.rect.right - 15, self.rect.top)
            bullet3 = HeroBullet(self.rect.centerx, self.rect.top - 5)

            # 發(fā)射子彈時的音效
            self.shoot_sud.play()

            self.bus.add_sprite(bullet1)
            self.bus.add_sprite(bullet2)
            self.bus.add_sprite(bullet3)

            self.bus.add_hero_bullet(bullet1)
            self.bus.add_hero_bullet(bullet2)
            self.bus.add_hero_bullet(bullet3)

    def superpower(self):
        now = pygame.time.get_ticks()
        if now - self.last_shoot_time > 50:
            self.last_shoot_time = now

            bullet3 = HeroBullet2(self.rect.centerx - 32, self.rect.top)
            self.shoot_sud.play()
            self.bus.add_sprite(bullet3)
            self.bus.add_hero_bullet(bullet3)

    def draw_lives(surf, x, y, lives, img):
        for i in range(lives):
            img_rect = img.get_rect()
            img_rect.x = x + 30 * i
            img_rect.y = y
            surf.blit(img, img_rect)


class HeroLive(Sprite):
    """
    我方戰(zhàn)機爆炸
    """
    def __init__(self, name, num, center):
        super().__init__()
        self.animation = []

【解釋一下】:只要是與我方戰(zhàn)機掛鉤的功能,都可在此模塊添加。


上面寫完了有關我方戰(zhàn)機的各種功能,下面就該【邪惡角色】外星人出場了..

關于Npc.py文件

【作用】:隨機生成敵機。

【小技巧介紹】:

class EnermyFactory:

【敵機工廠類】:來實現(xiàn)敵機的隨機產(chǎn)生

class Explosion(Sprite):

【爆炸效果類】:實現(xiàn)敵機與子彈碰撞后的爆炸效果。
【此代碼塊如下】

# @Author  : Zurich.Alcazar
# @Email   : 1178824808@qq.com
# @File    : Npc.py
# @Software: PyCharm

import random
import pygame

from pygame.sprite import Sprite
import os.path as path

import setting
import information as info
from bullet import NpcBullet

class commonEnermy(Sprite):
    def __init__(self,x,y):
        super().__init__()
        image = pygame.image.load(path.join(setting.img_folder,"enemy1.png"))
        self.image = pygame.transform.scale(image,(40,30))
        self.bus = info.DataBus()
        self.rect = self.image.get_rect()
        self.rect.centerx = x
        self.rect.centery = y
        self.shoot_time = pygame.time.get_ticks()
        self.delay_shoot = random.randint(500,3500)

    def update(self, *args):
        speed = 4
        self.rect.y += speed
        # 可設計其他軌跡
        self.shoot()
        if self.rect.y > setting.SCREEN_HEIGHT:
            self.kill()

    def shoot(self):
        now =  pygame.time.get_ticks()
        if now - self.shoot_time > self.delay_shoot:
            self.delay_shoot = random.randint(500, 3500)
            self.shoot_time = now
            bullet = NpcBullet(self.rect.centerx,self.rect.bottom)
            self.bus.add_sprite(bullet)
            self.bus.add_npc_bullet(bullet)

class EnermyFactory:
    def __init__(self):
        self.bus = info.DataBus()
        # 普通敵軍生成時間
        self.last_common_time = pygame.time.get_ticks()

    def generate_comon_enermy(self):
        x = random.randint(26,setting.SCREEN_WIDTH - 26)
        y = random.randint(-100,80)
        common_enermy = commonEnermy(x,y)
        self.bus.add_sprite(common_enermy)
        self.bus.add_enermy(common_enermy)

    def generate_enermy(self):
        now = pygame.time.get_ticks()
        if now - self.last_common_time > 800:
            self.generate_comon_enermy()
            self.last_common_time = now

class Explosion(Sprite):
    animations = dict()
    def __init__(self, who, center):
        super().__init__()
        self.aninmation = []
        self.load()

        if who == "enermy":
            self.animation = Explosion.animations['enemy_main']
        self.frame = 0
        self.image = self.animation[self.frame]
        self.rect = self.image.get_rect()
        self.rect.center = center
        # 上一幀圖片的顯示時間
        self.last_frame_time = pygame.time.get_ticks()

    def load(self):
        # 加載敵機爆炸資源
        if Explosion.animations.get("enemy_main") is None:
            enemy_explosion_res = []
            for i in range(0, 4):
                filename = "enemy1_down{}.png".format(i+1)
                img = pygame.image.load(path.join(setting.img_folder,filename))
                enemy_explosion_res.append(img)
            Explosion.animations["enemy_main"] = enemy_explosion_res

    def update(self, *args):
        now = pygame.time.get_ticks()
        if now - self.last_frame_time > 100:
            if self.frame == len(self.animation) - 1:
                self.kill()
            else:
                self.frame += 1
                self.image = self.animation[self.frame]

class HeroExplosion(Sprite):
    animations = dict()
    def __init__(self, who, center):
        super().__init__()
        self.aninmation = []
        self.load()

        if who == "hero":
            self.animation = Explosion.animations['enemy_main']
        self.frame = 0
        self.image = self.animation[self.frame]
        self.rect = self.image.get_rect()
        self.rect.center = center
        # 上一幀圖片的顯示時間
        self.last_frame_time = pygame.time.get_ticks()

    def load(self):
        # 加載爆炸資源
        if Explosion.animations.get("enemy_main") is None:
            enemy_explosion_res = []
            for i in range(0, 4):
                filename = "me_destroy_{}.png".format(i+1)
                img = pygame.image.load(path.join(setting.img_folder,filename))
                enemy_explosion_res.append(img)
            Explosion.animations["enemy_main"] = enemy_explosion_res

    def update(self, *args):
        now = pygame.time.get_ticks()
        if now - self.last_frame_time > 100:
            if self.frame == len(self.animation) - 1:
                self.kill()
            else:
                self.frame += 1
                self.image = self.animation[self.frame]


class Button(Sprite):
    def __init__(self,img_name,offset_y):
        super(Button, self).__init__()
        self.image = pygame.image.load(path.join(setting.img_folder,img_name))
        self.rect = self.image.get_rect()
        self.rect.center = setting.SCREEN_WIDTH / 2, (setting.SCREEN_HEIGHT/2) + offset_y

    @staticmethod
    def check_click(button):
        pressed = pygame.mouse.get_pressed()
        print(pressed)
        if pressed == (1, 0, 0):
            print("左鍵點擊")
            pos = pygame.mouse.get_pos()
            button_x = pos[0]
            button_y = pos[1]

            if button.rect.left < button_x < button.rect.right and button.rect.top < button_y < button.rect.bottom:
                return True
            return False

那么敵軍和我方英雄都存在了,接下來,我們介紹一下關于【子彈發(fā)射的問題】

bullet.py

【作用】:導入子彈、定義子彈初始位置、以及移動軌跡。

【代碼塊】

# @Author  : Zurich.Alcazar
# @Email   : 1178824808@qq.com
# @File    : bullet.py
# @Software: PyCharm

import pygame
import os.path as path
import setting
from pygame.sprite import Sprite

class HeroBullet(Sprite):
    def __init__(self,x,y):
        super(HeroBullet, self).__init__()
        # 導入子彈
        self.image = pygame.image.load(path.join(setting.img_folder,"bullet2.png"))
        # 定義子彈初始位置
        self.rect = self.image.get_rect()
        self.rect.centerx = x
        self.rect.bottom = y

    def update(self, *args):
        self.rect.y -= 10
        if self.rect.bottom < 0:
            self.kill()

class HeroBullet2(Sprite):
    def __init__(self,x,y):

        super(HeroBullet2, self).__init__()
        # 導入子彈
        self.image = pygame.image.load(path.join(setting.img_folder,"bullet2.png"))
        # 定義子彈初始位置
        self.rect = self.image.get_rect()
        # self.rect.center = center
        self.rect.centerx = x
        self.rect.bottom = y
        self.speedx = 0
        self.d = 6

    def update(self, *args):

        self.rect.y -= 4
        if self.speedx < -12:
            self.d = 3
        if self.speedx > 12:
            self.d = -3
        self.speedx += self.d
        self.rect.x += self.speedx

        if self.rect.bottom < 0:
            self.kill()

class NpcBullet(Sprite):
    def __init__(self,x,y):
        super(NpcBullet, self).__init__()
        # 導入敵機子彈
        image = pygame.image.load(path.join(setting.img_folder,"bullet1.png"))
        self.image = pygame.transform.scale(image, (4, 8))
        self.rect = self.image.get_rect()
        self.rect.centerx = x
        self.rect.bottom = y

    def update(self, *args):
        self.rect.y += 7
        if self.rect.centery < 0:
            self.kill()

【解釋】:關于子彈這一塊,其實是最簡單的啦。子彈能發(fā)射了,那接下來就可以加載以下道具了。


關于prop.py文件

【分類】

  • 火力提升道具

class Bulletprop(Sprite):

  • 加血道具

class Bombprop(Sprite):

【小技巧】

class PropFactory:

通過調用【道具工廠類】來實現(xiàn)道具的生成。
【代碼】

import random
import pygame
from pygame.sprite import Sprite
import os.path as path
import setting
import hit
import information as info
import math




class Bombprop(Sprite):
    # 定義加血道具
    def __init__(self,x,y):
        super().__init__()
        image = pygame.image.load(path.join(setting.img_folder,"bomb_supply.png"))
        self.image = pygame.transform.scale(image,(20,35))

        self.rect = self.image.get_rect()
        self.rect.centerx = x
        self.rect.centery = y

    def update(self, *args):
        speed = 2
        self.rect.y += speed
        if self.rect.y > setting.SCREEN_HEIGHT:
            self.kill()


class Bulletprop(Sprite):
    # 定義加火力道具
    def __init__(self,x,y):
        super(Bulletprop, self).__init__()
        prop_image = pygame.image.load(path.join(setting.img_folder,"bullet_supply.png"))
        self.image = pygame.transform.scale(prop_image, (20, 35))
        self.rect = self.image.get_rect()
        self.rect.centerx = x
        self.rect.centery = y

    def update(self, *args):
        speed = 2
        self.rect.y += speed
        if self.rect.y > setting.SCREEN_HEIGHT:
            self.kill()

class PropFactory:
    def __init__(self):
        self.bus = info.DataBus()
        # 普通敵軍生成時間
        self.prop_time = pygame.time.get_ticks()
        self.bullet_time = pygame.time.get_ticks() - 500

    def generate_comon_prop(self):
        # 定義加血道具位置
        x = random.randint(26, setting.SCREEN_WIDTH - 26)
        y = random.randint(26, 180)
        bomb_supply = Bombprop(x, y)
        self.bus.add_sprite(bomb_supply)
        self.bus.add_bomb_prop(bomb_supply)

    def bullet_prop(self):
        # 定義火力道具位置
        x = random.randint(26, setting.SCREEN_WIDTH - 26)
        y = random.randint(26, 180)

        bullet_supply = Bulletprop(x, y)
        self.bus.add_sprite(bullet_supply)
        self.bus.add_bullet_prop(bullet_supply)

    # 加血道具出現(xiàn)時間間隔
    def generate_bomb_prop(self):
        now = pygame.time.get_ticks()
        if now - self.prop_time > 2000 :
            self.generate_comon_prop()
            self.prop_time  = now

    def generate_bullet_prop(self):
        it = pygame.time.get_ticks()
        if it - self.bullet_time > 3000:
            self.bullet_prop()
            self.bullet_time = it

【注意事項】:在設置道具產(chǎn)生時,會很容易出現(xiàn)滿屏的道具問題,如果自己在編程中有遇到,(請自行百度解決,或者參考本篇文章)。


【插播小廣告,嘻嘻】
【關于爆炸效果】:其實游戲設置中的爆炸效果,是由幾張圖片在極短的時間內閃過產(chǎn)生的視覺效果。

下面來講一講碰撞檢測。


關于hit.py文件

【碰撞檢測分類】

  • 子彈和敵軍碰撞檢測;

  • 敵機與戰(zhàn)機碰撞檢測;

  • 敵機子彈和戰(zhàn)機碰撞檢測;

  • 戰(zhàn)機和火力道具碰撞檢測;

  • 戰(zhàn)機和加血道具碰撞檢測;

【代碼】:此塊代碼中有許多被 住掉的(#...)如果有興趣的話,可以嘗試嘗試。

import pygame
import sys
import setting
import os.path as path
import hero
from pygame.sprite import Sprite
# from Npc import EnermyFactory
import information as info
from Npc import Explosion
# from Npc import HeroExplosion
from Npc import Button


class Hit(Sprite):
    """
    碰撞類
    """
    def __init__(self):
        super(Hit, self).__init__()
        self.score = 0
        self.power = 1
        self.die_music = pygame.mixer.Sound(path.join(setting.snd_folder, "enemy1_down.wav"))
        self.get_bullet = pygame.mixer.Sound(path.join(setting.snd_folder,"get_bullet.wav"))
        self.bus = info.DataBus()


class GameHelper:
    def __init__(self):
        self.bus = info.DataBus()

    def collision(self):
        """
        全局碰撞檢測
        :return:
        """
        # 子彈和敵軍碰撞檢測
        hits = pygame.sprite.groupcollide(self.bus.hero_bullets, self.bus.enermys, True, True)
        if hits:
            self.handle_collision(hits)

        #  敵機與戰(zhàn)機碰撞
        enermys = self.bus.enermys.sprites()
        enermys_hit = pygame.sprite.spritecollide(self.bus.hero, self.bus.enermys, True, pygame.sprite.collide_circle_ratio(0.7))
        # for e in enermys:
        #     pygame.sprite.collide_circle_ratio(0.7)
        #     if pygame.sprite.collide_circle(self.bus.hero, e):

        if enermys_hit:
            # for b, e in hits.items():
            #     for eson in e:
            #         explosion = HeroExplosion('hero', eson.rect.center)
            #         self.bus.add_sprite(explosion)
            # hero.Hero.hide(self.bus.hero)
            # hero.Hero.Lives(self.bus.hero)
            # hero.Hero.shield = 100
                self.bus.is_game_over =True
                print("Game Over...")

        # 敵機子彈和戰(zhàn)機碰撞
        enermys_bullets = self.bus.enermy_bullets.sprites()
        for i in enermys_bullets:
            if pygame.sprite.collide_rect(self.bus.hero, i):
                # # 敵人爆炸動畫
                # for b, e in hits.items():
                #     for eson in e:
                #         explosion = HeroExplosion('hero', eson.rect.center)
                #         self.bus.add_sprite(explosion)
                # hero.Hero.hide(self.bus.hero)
                # hero.Hero.Lives(self.bus.hero)
                # hero.Hero.shield = 100
                self.bus.is_game_over = True
                print("Game Over...")


        # 戰(zhàn)機和火力道具碰撞
        bullet_prop = self.bus.bullet_props.sprites()
        bullet_hit = pygame.sprite.spritecollide(self.bus.hero, self.bus.bullet_props,True, pygame.sprite.collide_circle_ratio(0.7))
        # for k in bullet_prop:
        #     pygame.sprite.collide_circle_ratio(0.7)
        #     if pygame.sprite.collide_circle(self.bus.hero, k):
        #         hero.Hero.powerup(self.bus.hero)
        if bullet_hit:
            hero.Hero.powerup(self.bus.hero)


        # 戰(zhàn)機和加血道具碰撞
        bomb_prop = self.bus.bomb_props.sprites()
        bomb_hit = pygame.sprite.spritecollide(self.bus.hero, self.bus.bomb_props, pygame.sprite.collide_circle_ratio(0.8))
        # if bomb_hit:
        #     hero.Hero.(self.bus.hero)

    def handle_collision(self, hits):
        # 加分
        self.bus.add_score(10 * len(hits))
        # 敵人死亡聲音
        self.bus.m.play_die_music()

        # 敵人爆炸動畫
        for b, e in hits.items():
            for eson in e:
                explosion = Explosion('enermy', eson.rect.center)
                self.bus.add_sprite(explosion)

    def draw_game_over_view(self):
        self.bus.all_sprites.empty()

        game_over_button = Button("gameover.png", -40)
        begin_button = Button("again.png",40)
        self.bus.all_sprites.add(game_over_button)
        self.bus.all_sprites.add(begin_button)

        if Button.check_click(game_over_button):
            sys.exit()

        if Button.check_click(begin_button):
            self.bus.reset()
            self.bus.is_game_over = False

關于information.py文件

這個文件特別重要。
【作用】

  • 初始化英雄(...);

  • 將游戲中的各個元素(敵機、子彈、道具等)分門別類的“存”起來;

【代碼】

# @Author  : Zurich.Alcazar
# @Email   : 1178824808@qq.com
# @File    : information.py
# @Software: PyCharm
import pygame
import hero
import music
import hit
import setting
# from Npc import Explosion

class DataBus:
   instance = None


   def __new__(cls, *args, **kwargs):
       if DataBus.instance is None:
           DataBus.instance = super().__new__(cls)
           DataBus.instance.reset()


       return DataBus.instance

   def reset(self):

       self.score = 0
       self.is_game_over = False

       self.all_sprites = pygame.sprite.Group()
       self.hero_bullets = pygame.sprite.Group()

       self.enermy_bullets = pygame.sprite.Group()
       self.heros = pygame.sprite.Group()
       self.enermys = pygame.sprite.Group()
       self.bomb_props = pygame.sprite.Group()
       self.bullet_props = pygame.sprite.Group()
       self.m = music.Music()
       self.game_helper = hit.GameHelper()
       # self.game_over_button = Npc.Button("gameover.png")
       # self.game_over_button_clicked = False

       # 初始化英雄
       self.__init_hero()

   def __init_hero(self):
       """
       初始化英雄
       :return:
       """
       self.hero = hero.Hero()
       self.add_sprite(self.hero)

   def add_sprite(self,sprite):
       self.all_sprites.add(sprite)

   def remove_sprite(self,sprite):
       self.all_sprites.remove(sprite)

   def add_hero_bullet(self,hero_bullet):
       self.hero_bullets.add(hero_bullet)

   def add_npc_bullet(self,npc_bullet):
       self.enermy_bullets.add(npc_bullet)

   def add_hero(self,hero):
       self.heros.add(hero)

   def add_enermy(self,enermy):
       self.enermys.add(enermy)

   def add_bomb_prop(self,prop):
       self.bomb_props.add(prop)

   def add_bullet_prop(self,prop):
       self.bullet_props.add(prop)

   def add_score(self,score):
       self.score += score
       num_score = self.score

       print("當前得分:%d" % self.score)


   def draw_text(self, screen):
       font1 = pygame.font.Font(16, True)
       screen.blit(font1.render(u'當前得分:%d' % self.score, True,'red'), [20, 20])

【解釋一下】:這個文件就是拿來存儲數(shù)據(jù)的。


關于music.py文件

【作用】:配置音樂

【代碼】:

# @Author  : Zurich.Alcazar
# @Email   : 1178824808@qq.com
# @File    : music.py
# @Software: PyCharm
import pygame
import sys
import setting
import os.path as path


class Music:

    singleton = None
    def __new__(cls, *args, **kwargs):
        if Music.singleton is None:
            Music.singleton = super().__new__(cls, *args, **kwargs)
            Music.singleton.initial()

        return Music.singleton

    def initial(self):
        self.die_music = pygame.mixer.Sound(path.join(setting.snd_folder, "enemy1_down.wav"))
        self.bgm = pygame.mixer.Sound(path.join(setting.snd_folder, 'game_music.ogg'))
        self.shoot_sud = pygame.mixer.Sound(path.join(setting.snd_folder, "bullet.wav"))
        self.enermy_die_music = pygame.mixer.Sound(path.join(setting.snd_folder, "enemy1_down.wav"))

        self.set_config()

    def set_config(self):
        """
        配置音樂
        :return:
        """
        self.bgm.set_volume(0.6)

    def play_die_music(self):
        self.die_music.play()

    def play_bgm(self):
        self.bgm.play(loops=-1)

    def play_shoot_sud(self):
        self.shoot_sud.play()

    def play_enmery_die_music(self):
        self.enermy_die_music.play()


關于setting.py文件

【作用】:設置工程目錄,并且設置游戲的邊界。

import os.path as path
import pygame

SCREEN_WIDTH = 400
SCREEN_HEIGHT = 600

# 工程目錄
print(__file__)
project_folder = path.dirname(__file__)

img_folder = path.join(project_folder,"plane/images")
snd_folder = path.join(project_folder,"plane/sound")
print(img_folder)


總結一下

本篇文章主要是理一下使用pygame面向對象編程的思路,說一下本文中程序的缺點吧,此程序其實部分功能沒有實現(xiàn),例如:關于加血道具那一塊、以及我方戰(zhàn)機的爆炸效果等。不把這個做的盡善盡美,也是為了看這篇文章的你能夠有自己的【Idea】。能夠學著自己去實現(xiàn)一種小小的功能。

github地址:https://github.com/Alacazar99/Power_Plane

【如果簡書的朋友們有什么想法或者建議】歡迎留言。
【關于所使用的一些圖片素材】,歡迎留言。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,837評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,196評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,688評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,654評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,456評論 6 406
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,955評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,044評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,195評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,725評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,608評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,802評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,318評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,048評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,422評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,673評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,424評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,762評論 2 372

推薦閱讀更多精彩內容