ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

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

2021-07-31 18:58:15  阅读:254  来源: 互联网

标签:__ python self def 素材 源码 pygame screen rect


一、实现功能包括:多架敌机随机出现,生命数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,self,def,素材,源码,pygame,screen,rect
来源: https://blog.csdn.net/weixin_46707493/article/details/119279853

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有