python飞机大战源码以及素材资源

一、实现功能包括:多架敌机随机出现,生命数3,死亡时倒计时后重新开局,炸弹随机降落,统计击败敌机数,三张地图每局随机出现,击败敌机数达到10时出现大飞机,大飞机发射子弹更密集等。

二、pycharm源码文件以及图片素材资源已在主页上传,代码以及运行结果如下:

import time
import random
from PIL import Image

import pygame
from pygame.constants import *


#己方飞机类
class Player(pygame.sprite.Sprite):
    # 存放所有飞机的子弹的组
    bullets = pygame.sprite.Group()
    def __init__(self,screen):
        # 这个精灵的初始化方法 必须调用
        pygame.sprite.Sprite.__init__(self)

        # 创建一个玩家飞机图片,当做真正的飞机
        self.image = pygame.image.load("./feiji/hero1.png")

        #通过图片获得矩阵
        self.rect = self.image.get_rect()  # rect:矩形

        # 定义飞机初始化坐标
        self.rect.topleft = [Manager.bg_size[0] / 2 - 100 / 2,600]

        # 飞机速度
        self.speed = 10

        #记录当前窗口对象
        self.screen = screen

        #子弹图片
        self.bullet_image = "./feiji/bullet.png"

        # 飞机子弹频率 1~100,表示每0.01秒百分之几的概率发射
        self.bullet_frequency = 10


    def key_control(self):
        # 监听键盘事件
        key_pressed = pygame.key.get_pressed()

        if key_pressed[K_w] or key_pressed[K_UP]:
            self.rect.top -= self.speed
        if key_pressed[K_s] or key_pressed[K_DOWN]:
            self.rect.bottom += self.speed
        if key_pressed[K_a] or key_pressed[K_LEFT]:
            # 定义飞机左行驶尽头边界
            if self.rect.left >= 10 :
                self.rect.left -= self.speed
        if key_pressed[K_d] or key_pressed[K_RIGHT]:
            #定义飞机右行驶尽头边界
            if self.rect.right <= Manager.bg_size[0]:
                self.rect.right += self.speed

        if key_pressed[K_SPACE]:
            # 随机发射子弹
            if  random.randint(0,99) in range(self.bullet_frequency):
                bullet = Bullet(self.screen ,self.rect.left + 50 - Image.open(self.bullet_image).size[0]/2
                                ,self.rect.top - Image.open(self.bullet_image).size[1])
                # 将己方子弹子弹改为
                bullet.image = pygame.image.load(self.bullet_image)
                Player.bullets.add(bullet)

    #键盘监听控制飞机,飞机的显示
    def update(self):
        self.key_control()
        self.display()



    def display(self):
        # 粘贴飞机坐标
        self.screen.blit(self.image, self.rect)
        #更新子弹坐标
        for i in Player.bullets:
            i.player_fire()

        # 对应子弹的update方法
        Player.bullets.update()
        # 把所有子弹全部添加到屏幕
        Player.bullets.draw(self.screen)




#敌方飞机类
class Enemyplayer(pygame.sprite.Sprite):
    # 放子弹的列表,类属性,通过类名调用
    bullets = pygame.sprite.Group()
    def __init__(self,screen,image ):
        # 这个精灵的初始化方法 必须调用
        pygame.sprite.Sprite.__init__(self)

        #记录窗口
        self.screen = screen

        #获取敌方飞机图片
        self.image = pygame.image.load(image)
        #通过图片获得矩阵
        self.rect = self.image.get_rect()
        #敌方飞机坐标初始化
        self.rect.topleft = [Manager.bg_size[0]/2 - 50/2,0]

        # 放子弹的列表,类属性,通过类名调用
        self.bullets = pygame.sprite.Group()

        # 子弹图片
        self.bullet_image = "./feiji/bullet1.png"

        #敌方飞机子弹频率 1~100,平均一秒发射几个
        self.bullet_frequency = 3

        #敌机移动方向
        self.direciton= "left"
        #飞机是否向下移动
        self.direciton_up = False

        #敌机速度
        self.speed = 4

    def display(self):
        #粘贴敌机到窗口
        self.screen.blit(self.image,self.rect.topleft)


    #敌方飞机自动开火方法
    def auto_fire(self):
        #控制敌方子弹频率
        if random.randint(1, 100) in range(0,self.bullet_frequency):
            #通过飞机坐标跟子弹分辨率大小调用子弹对象
            bullet = Bullet(self.screen,self.rect.left + 25 - Image.open(self.bullet_image).size[0]/2
                            ,self.rect.top + Image.open(self.bullet_image).size[1] + 20)
            #将敌方子弹子弹改为
            bullet.image = pygame.image.load(self.bullet_image)
            #向Bullet子弹对象列表增加一个子弹对象
            Enemyplayer.bullets.add(bullet)


    #敌方飞机自动飞行方法
    def auto_move(self):

        if self.direciton == "left":
            self.rect.left -= self.speed
            if self.direciton_up :
                self.rect.bottom += self.speed
        elif self.direciton == "right":
            self.rect.right += self.speed
            if self.direciton_up:
                self.rect.bottom += self.speed
        if self.rect.left <= 0 :
            self.direciton = "right"
        elif self.rect.right >=Manager.bg_size[0]:
            self.direciton = "left"

    #使敌方飞机飞出窗口时消除该敌方飞机对象
    def kill_enemy(self):
        if self.rect.top > Manager.bg_size[1]:
            self.kill()

    #敌方飞机自动移动,自动发射以及显示
    def update(self):
        self.auto_move()
        self.auto_fire()
        self.display()
        self.kill_enemy()


#子弹类
class Bullet(pygame.sprite.Sprite):
    def __init__(self,screen,x,y):
        # 这个精灵的初始化方法 必须调用
        pygame.sprite.Sprite.__init__(self)
        self.screen = screen
        self.image = pygame.image.load("./feiji/bullet.png")
        #通过图片获得矩阵
        self.rect = self.image.get_rect()
        # 初始化子弹坐标
        self.rect.topleft = [x , y ]
        #子弹速度
        self.speed = 8

    #己方飞机开火
    def player_fire(self):
        self.rect.top -= self.speed+4
    #敌方飞机开火
    def enemy_fire(self):
        self.rect.bottom += self.speed/2

    def update(self):
        # 如果子弹移出屏幕上方 则销毁子弹对象
        if self.rect.top > Manager.bg_size[1] or self.rect.bottom < 0 :
            self.kill()

        self.enemy_fire()
        # 把所有子弹全部添加到屏幕
        Enemyplayer.bullets.draw(self.screen)


# 炸弹类
class Bombshell(pygame.sprite.Sprite):
    def __init__(self,screen):
        # 这个精灵的初始化方法 必须调用
        pygame.sprite.Sprite.__init__(self)
        self.screen = screen
        # 传入炸弹图片
        self.image = pygame.image.load("./feiji/bomb-2.gif")
        # 炸弹矩形获取
        self.rect = self.image.get_rect()
        # 炸弹速度
        self.speed = 2
        self.direciton = "left"
        # 炸弹初始坐标
        self.rect.topleft = [0,0]

    def auto_move(self):
        # 往左移动
        if self.direciton == "left":
            self.rect.left -= self.speed
            self.rect.bottom += self.speed
        # 往右移动
        elif self.direciton == "right":
            self.rect.right += self.speed
            self.rect.bottom += self.speed
        #左右移动边界
        if self.rect.left <= 0:
            self.direciton = "right"
        elif self.rect.right >= Manager.bg_size[0]:
            self.direciton = "left"


    # 使敌方炸弹飞出窗口时消除该敌方飞机对象
    def kill_bomb(self):
        if self.rect.top > Manager.bg_size[1]:
            self.kill()

    def display(self):

        # 粘贴炸弹到窗口
        self.screen.blit(self.image, self.rect.topleft)

    def update(self):
        self.auto_move()
        self.display()
        self.kill_bomb()


class Bomb(object):
    # 初始化爆炸
    def __init__(self, screen, type):

        self.screen = screen
        if type == 'enemy':
            # 加载爆炸资源
            self.mImages = [
                pygame.image.load("./feiji/enemy0_down" + str(v) + ".png") for v in range(1, 5)]
        else:
            # 加载爆炸资源
            self.mImages = [pygame.image.load(
                "./feiji/hero_blowup_n" + str(v) + ".png") for v in range(1, 5)]

        self.mImages += self.mImages

        # 设置当前爆炸播放索引
        self.mIndex = 0
        # 爆炸位置
        self.mPos = [0, 0]
        # 是否可见
        self.mVisible = False

    # 设置位置
    def action(self, rect):
        # 触发爆炸方法draw
        # 爆炸的坐标
        self.mPos[0] = rect.left
        self.mPos[1] = rect.top
        # 打开爆炸的开关
        self.mVisible = True

    # 绘制爆炸
    def draw(self):
        if not self.mVisible:
            return
        self.screen.blit(self.mImages[self.mIndex], (self.mPos[0], self.mPos[1]))

        self.mIndex += 1
        if self.mIndex >= len(self.mImages):
            # 如果下标已经到最后 代表爆炸结束
            # 下标重置 mVisible重置
            self.mIndex = 0
            self.mVisible = False

# 地图
class GameBackground(object):
    # 初始化地图,传入参数窗口跟地图编号
    def __init__(self, screen,num):
        self.mImage1 = pygame.image.load("./feiji/img_bg_level_"+str(num)+".jpg")
        self.mImage2 = pygame.image.load("./feiji/img_bg_level_"+str(num)+".jpg")
        # 窗口
        self.screen = screen
        # 辅助移动地图
        self.y1 = 0
        self.y2 = -Manager.bg_size[1]  # -768

    # 移动地图
    def move(self):
        self.y1 += 2
        self.y2 += 2
        if self.y1 >= Manager.bg_size[1]:
            self.y1 = 0
        if self.y2 >= 0:
            self.y2 = -Manager.bg_size[1]

    # 绘制地图
    def draw(self):
        self.screen.blit(self.mImage1, (0, self.y1))
        self.screen.blit(self.mImage2, (0, self.y2))


# 背景音乐类
class GameSound(pygame.sprite.Sprite):
    def __init__(self):
        #这个精灵的初始化方法必须调用
        pygame.sprite.Sprite.__init__(self)

        pygame.mixer.init()  # 音乐模块初始化
        pygame.mixer.music.load('./feiji/bg2.ogg') #载入背景音乐
        pygame.mixer.music.set_volume(0.5)  # 声音大小,0.5表示一半大小的声音
        self.__bomb = pygame.mixer.Sound('./feiji/bomb.wav')


    # 背景音乐
    def playBackgroundMusic(self):
        pygame.mixer.music.play(-1)  # 开始播放音乐,数字表示播放次数,-1表示循环播放
    # 爆炸音乐
    def playBombSound(self):
        self.__bomb.play()


class Manager(object):
    #对应图片的窗口大小
    bg_size = (512,768)

    #玩家生命数
    life_num = 3

    #生成敌方飞机的定时器
    create_enemy_id = 10

    #游戏结束定时器
    create_game_over_id = 11

    #游戏结束标志
    gameover = False
    #倒计时数
    over_time = 3

    #boss最大数量
    boss_num = 10
    # 是否存在boss
    have_boss = False

    #初始化击败敌方飞机数
    defeat_num = 0
    def __init__(self):
        pygame.init()
        # 创建一个窗口
        self.screen = pygame.display.set_mode(Manager.bg_size)
        # 生成音乐对象
        self.gamesound = GameSound()
        # 己方飞机精灵组
        self.players = pygame.sprite.Group()
        # 敌方飞机精灵组
        self.enemyplayers = pygame.sprite.Group()
        # 敌方炸弹精灵组
        self.bombshells = pygame.sprite.Group()
        # 创建一个背景图片
        self.background = pygame.image.load(r"./feiji/background.png")
        #创建一个可移动地图 ,随机取一种地图,
        self.move_background_num = random.randint(1,5)
        self.move_background=GameBackground(self.screen,self.move_background_num)


    def player(self):
        # 调用一个飞机对象
        player = Player(self.screen)
        # 将该飞机对象增加到己方飞机精灵组中
        self.players.add(player)

    def enemyplayer(self):
        # 调用一个敌方飞机对象
        enemyplayer = Enemyplayer(self.screen,"./feiji/enemy0.png")
        # 将该飞机对象增加到己方飞机精灵组中
        self.enemyplayers.add(enemyplayer)

    #增加多个敌机对象
    def add_enemy(self):
        enemyplayer = Enemyplayer(self.screen,"./feiji/enemy0.png")
        enemyplayer.direciton_up = True
        x = random.randint(0,Manager.bg_size[0])
        #敌机随机出现
        enemyplayer.rect.topleft = (x,0)
        #如果敌机出现在窗口较左边,则敌机优先向右飞行
        if x <= Manager.bg_size[0] / 2:
            enemyplayer.direciton = "right"
        #向敌机精灵组增加一个敌机精灵
        self.enemyplayers.add(enemyplayer)



    #判断碰撞
    def judge_bomb(self,player_bomb,enemy_bomb):
        delete_sprite = False
        if Manager.life_num == 1:
            delete_sprite = True
        # 参1:碰撞对象1 ;参2:碰撞对象2 ;参3:判断调出碰撞对象1还是2还是一起的爆炸图片 ; 参3:是否删除爆炸对象1
        def judge(x1,x2,who,delete1):
            # 判断碰撞对象1(精灵组)与2(精灵组)的碰撞
            iscollide = pygame.sprite.groupcollide(x1, x2, delete1, True)
            if iscollide and (who == "player" or who == "both"):
                Manager.life_num -= 1
                if Manager.life_num == 0:
                    # 游戏结束
                    Manager.gameover = True
                    pygame.time.set_timer(Manager.create_game_over_id,1000)
            if iscollide:
                #取出爆炸对象1
                items = list(iscollide.items())[0]
                x = items[0]
                if who == "player":

                    # 传入爆炸位置,打开爆炸图片输出按钮
                    player_bomb.action(x.rect)
                elif who == "enemy":
                    #x = items[1][0]
                    # 传入敌方爆炸图片的位置
                    enemy_bomb.action(x.rect)
                    # 敌方爆炸击败数加1
                    Manager.defeat_num += 1
                # 爆炸的声音

                elif who == "both":
                    # 传入爆炸位置,打开爆炸图片输出按钮
                    player_bomb.action(x.rect)
                    # 取出爆炸对象2
                    y = items[1][0]
                    # 传入爆炸对象2的爆炸图片的位置
                    enemy_bomb.action(y.rect)
                    # 敌方爆炸击败数加1
                    Manager.defeat_num += 1

                # 爆炸删除子弹精灵组
                # Enemyplayer.bullets.empty()
                #爆炸音乐
                self.gamesound.playBombSound()

        # 判断玩家飞机(精灵组)与敌方子弹(精灵组)的碰撞
        judge(self.players, Enemyplayer.bullets, "player", delete_sprite)
        # 判断玩家飞机(精灵组)与敌方炸弹(精灵组)的碰撞
        judge(self.players, self.bombshells, "player", delete_sprite)
        # 判断敌方飞机(精灵组)与我方子弹(精灵组)的碰撞
        judge(self.enemyplayers, Player.bullets, "enemy", True)
        # 判断玩家飞机(精灵组)与敌方飞机(精灵组)的碰撞
        judge(self.players, self.enemyplayers, "both", delete_sprite)




    #召唤boss
    def add_boss(self):
        enemy_boss_player = Enemyplayer(self.screen,"./feiji/enemy1.png")
        enemy_boss_player.bullet_frequency *= 2
        enemy_boss_player.bullet_image ='./feiji/bullet2.png'
        self.enemyplayers.add(enemy_boss_player)


    # 绘制文字  rgb 红绿蓝 0 - 255
    # 参1要绘制的文字 参2 x轴坐标 参3y轴坐标 参4文字大小 参5 文字颜色 参6 背景颜色
    def drawText(self, text, x, y, textHeight = 30, fontColor = (255, 255, 255), backgroudColor = None):

        # 通过字体文件获得字体对象  参数1 字体文件 参数2 字体大小
        font_obj = pygame.font.Font('./feiji/baddf.ttf', textHeight)
        # 1文字  2是否抗锯齿 3文字颜色 4背景颜色
        text_obj = font_obj.render(text, True, fontColor, backgroudColor)  # 配置要显示的文字
        # 获得要显示的对象的rect
        text_rect = text_obj.get_rect()
        # 设置显示对象的坐标
        text_rect.topleft = (x, y)
        # 绘制字 到指定区域  参1是文字对象 参2 矩形对象
        self.screen.blit(text_obj, text_rect)

    def show_over_text(self):
        # 游戏结束 倒计时后重新开始
        self.drawText('gameover %d' % Manager.over_time, 100, Manager.bg_size[1] / 2,
                      textHeight=50, fontColor=[255, 0, 0])

    #显示击败敌机数
    def show_defeatnum_text(self):
        # 显示击败敌机数
        self.drawText('击败敌机数: %d' % Manager.defeat_num, Manager.bg_size[0]-150, 0,
                      textHeight=20, fontColor=[255, 0, 0])
        # 显示剩余生命数
        self.drawText('剩余生命数: %d' % Manager.life_num, Manager.bg_size[0] - 150, 20,
                      textHeight=20, fontColor=[255, 0, 0])



    def game_over(self):
        # 结束后倒计时
        Manager.over_time -= 1
        self.show_over_text()
        if Manager.over_time == 0:
            # 倒计时结束后游戏重新开始,相应变量返回初始化
            Manager.over_time = 3
            Manager.gameover = False
            self.game_start()


    def game_start(self):
        # 重新开始游戏,有些类属性要清空
        # 击败敌机数回 0
        Manager.defeat_num = 0
        # 生命数数回 3
        Manager.life_num = 3
        #boss按钮恢复
        Manager.have_boss = False
        #清空飞机类属性的子弹精灵组
        Player.bullets.empty()
        # 清空敌方飞机类属性的子弹精灵组
        Enemyplayer.bullets.empty()
        #重新运行游戏
        manager = Manager()
        manager.main()

    def main(self):

        # 播放背景音乐
        self.gamesound.playBackgroundMusic()
        # 增加一个己方飞机对象
        self.player()
        # 增加一个敌方飞机对象
        self.enemyplayer()
        # 开启生成敌方飞机定时器
        pygame.time.set_timer(Manager.create_enemy_id, 2000)
        # 初始化一个己方飞机爆炸对象
        player_bomb = Bomb(self.screen, 'player')
        # 初始化一个敌机爆炸的对象
        enemy_bomb = Bomb(self.screen, 'enemy')


        while True:
            # 调用地图移动方法
            self.move_background.move()
            # 向窗口不断添加背景图
            self.move_background.draw()
            # 窗口显示击败敌机数
            self.show_defeatnum_text()

            # 击败敌机数50时,召唤boss
            if Manager.defeat_num == 10 and Manager.have_boss == False:
                self.add_boss()
                Manager.have_boss = True

            # 随机增加炸弹,平均每十秒增加一个炸弹
            if random.randint(0, 1000) == 1:
                bombshell = Bombshell(self.screen)
                # 在窗口最上方左右之间随机出现
                bombshell.rect.topleft = (random.randint(0, Manager.bg_size[0]), -103)
                self.bombshells.add(bombshell)

            # 对应飞机类里的update方法
            self.players.update()
            self.enemyplayers.update()
            # 不断显示敌方子弹,此为类方法
            Enemyplayer.bullets.update()
            # 显示炸弹
            self.bombshells.update()

            #调用爆炸对象调出爆炸图片
            player_bomb.draw()
            enemy_bomb.draw()

            if self.players.sprites():
            #调用判断碰撞方法
                self.judge_bomb(player_bomb,enemy_bomb)

            #游戏结束播放倒计时文字
            if Manager.gameover:
                self.show_over_text()

            # 不断更新窗口
            pygame.display.update()

            # 遍历所有的事件、
            for event in pygame.event.get():
                # 判断事件类型如果是pygame的退出
                if event.type == QUIT:
                    # 执行pygame退出
                    pygame.quit()
                    # python程序的退出
                    exit()
                elif event.type == Manager.create_enemy_id:
                    # 创建一个敌机
                    self.add_enemy()
                elif event.type == Manager.create_game_over_id:
                    if Manager.gameover:
                        #游戏结束
                        self.game_over()
            time.sleep(0.01)


if __name__ == "__main__":
    manager = Manager()
    manager.main()

三、运行结果:

python飞机大战源码以及素材资源_第1张图片

python飞机大战源码以及素材资源_第2张图片

python飞机大战源码以及素材资源_第3张图片

注:需要全部图片文件以及代码加我微信(备注来意):gjwtxp

你可能感兴趣的:(python,pygame,游戏)