pygame游戏--飞机大战(plane)

简介: pygame游戏--飞机大战(plane)


项目下载链接:


https://download.csdn.net/download/qq_39236499/12793963


游戏操作:


1.wsad或者方向键操作飞机


2.空格键放全屏炸弹


代码:


此代码分5个模块



main.py


import pygame
import sys                   # 退出需要
import traceback             # 为了更好地退出
from pygame.locals import *  # 就直接用QUIT而不需要pygame.QUIT
from random import *         # 生成随机数需要
"""自建模块"""
import myplane               # 飞机模块
import bullet                # 子弹模块
import enemy                 # 敌机模块
import supply                # 补给模块
"""一些初始化"""
pygame.init()                                                      # 初始化
pygame.mixer.init()                                                # 混音器初始化
"""一些设置"""
########################################################################################################################
# 颜色设置
BLACK = (0, 0, 0)                                                  # 黑色
WHITE = (255, 255, 255)                                            # 白色
GREEN = (0, 255, 0)                                                # 绿色
RED = (255, 0, 0)                                                  # 红色
# 窗口尺寸设置
bg_size = width, height = 480, 700                                 # 背景尺寸
# 音乐设置
pygame.mixer.music.load("sound/game_music.ogg")                    # 游戏背景声音
pygame.mixer.music.set_volume(0.2)
bullet_sound = pygame.mixer.Sound("sound/bullet.wav")
bullet_sound.set_volume(0.2)
bomb_sound = pygame.mixer.Sound("sound/use_bomb.wav")
bomb_sound.set_volume(0.2)
supply_sound = pygame.mixer.Sound("sound/supply.wav")
supply_sound.set_volume(0.2)
get_bomb_sound = pygame.mixer.Sound("sound/get_bomb.wav")
get_bomb_sound.set_volume(0.2)
get_bullet_sound = pygame.mixer.Sound("sound/get_bullet.wav")
get_bullet_sound.set_volume(0.2)
upgrade_sound = pygame.mixer.Sound("sound/upgrade.wav")
upgrade_sound.set_volume(0.2)
enemy3_fly_sound = pygame.mixer.Sound("sound/enemy3_flying.wav")
enemy3_fly_sound.set_volume(0.2)
enemy1_down_sound = pygame.mixer.Sound("sound/enemy1_down.wav")
enemy1_down_sound.set_volume(0.2)
enemy2_down_sound = pygame.mixer.Sound("sound/enemy2_down.wav")
enemy2_down_sound.set_volume(0.2)
enemy3_down_sound = pygame.mixer.Sound("sound/enemy3_down.wav")
enemy3_down_sound.set_volume(0.5)
me_down_sound = pygame.mixer.Sound("sound/me_down.wav")
me_down_sound.set_volume(0.2)
########################################################################################################################
"""一些函数"""
########################################################################################################################
def add_small_enemies(group1, group2, num):
    for i in range(num):
        e1 = enemy.SmallEnemy(bg_size)
        group1.add(e1)
        group2.add(e1)
def add_mid_enemies(group1, group2, num):
    for i in range(num):
        e2 = enemy.MidEnemy(bg_size)
        group1.add(e2)
        group2.add(e2)
def add_big_enemies(group1, group2, num):
    for i in range(num):
        e3 = enemy.BigEnemy(bg_size)
        group1.add(e3)
        group2.add(e3)
def inc_speed(target, inc):
    for each in target:
        each.speed += inc
########################################################################################################################
screen = pygame.display.set_mode(bg_size)                          # 创建窗口
pygame.display.set_caption("飞机大战")                               # 窗口名字
background = pygame.image.load("images/background.png").convert()  # 加载背景图片
def main():                                  # 主函数
    pygame.mixer.music.play(-1)              # -1循环播放背景音乐
    clock = pygame.time.Clock()
    # 生成我方飞机
    me = myplane.MyPlane(bg_size)
    enemies = pygame.sprite.Group()
    # 生成敌方小型飞机
    small_enemies = pygame.sprite.Group()
    add_small_enemies(small_enemies, enemies, 15)   # 15个
    # 生成敌方中型飞机
    mid_enemies = pygame.sprite.Group()
    add_mid_enemies(mid_enemies, enemies, 4)        # 4个
    # 生成敌方大型飞机
    big_enemies = pygame.sprite.Group()
    add_big_enemies(big_enemies, enemies, 2)        # 2个
    # 生成普通子弹
    bullet1 = []
    bullet1_index = 0
    BULLET1_NUM = 4                                     # 子弹数量
    for i in range(BULLET1_NUM):
        bullet1.append(bullet.Bullet1(me.rect.midtop))  # 子弹放置飞机的顶部中央
    # 生成超级子弹
    bullet2 = []
    bullet2_index = 0
    BULLET2_NUM = 8                                     # 超级子弹数量,一列4个
    for i in range(BULLET2_NUM//2):
        bullet2.append(bullet.Bullet2((me.rect.centerx-33, me.rect.centery)))  # 第一列
        bullet2.append(bullet.Bullet2((me.rect.centerx+30, me.rect.centery)))  # 第二列
    # 中弹图片索引
    e1_destroy_index = 0
    e2_destroy_index = 0
    e3_destroy_index = 0
    me_destroy_index = 0
    # 统计得分
    score = 0                                            # 初始化0分
    score_font = pygame.font.Font("font/font.ttf", 36)   # 字体,字号
    # 标志是否暂停游戏
    paused = False
    pause_nor_image = pygame.image.load("images/pause_nor.png")\
        .convert_alpha()            # 暂停图片1
    pause_pressed_image = pygame.image.load("images/pause_pressed.png")\
        .convert_alpha()            # 暂停图片1
    resume_nor_image = pygame.image.load("images/resume_nor.png")\
        .convert_alpha()            # 非暂停图片1
    resume_pressed_image = pygame.image.load("images/resume_pressed.png")\
        .convert_alpha()            # 非暂停图片2
    paused_rect = pause_nor_image.get_rect()                                # 图片矩形
    paused_rect.left, paused_rect.top = width - paused_rect.width - 10, 10  # 图片矩形位置
    paused_image = pause_nor_image  # 初始化图片最初状态,为暂停图片1
    # 设置难度级别
    level = 1                       # 初始化等级
    # 全屏炸弹
    bomb_image = pygame.image.load("images/bomb.png").convert_alpha()      # 炸弹的图片
    bomb_rect = bomb_image.get_rect()                                      # 炸弹的图片的矩形
    bomb_font = pygame.font.Font("font/font.ttf", 48)                      # 显示炸弹个数的字体,字号
    bomb_num = 3                                                           # 初始化3个全屏炸弹
    # 每30秒发放一个补给包
    bullet_supply = supply.Bullet_Supply(bg_size)            # 超级子弹补给
    bomb_supply = supply.Bomb_Supply(bg_size)                # 全屏炸弹补给
    SUPPLY_TIME = USEREVENT                                  # 自定义事件1
    pygame.time.set_timer(SUPPLY_TIME, 30 * 1000)            # 定时器30秒,30×1000毫秒
    # 超级子弹定时器
    DOUBLE_BULLET_TIME = USEREVENT + 1                       # 自定义事件2
    # 标志是否使用超级子弹
    is_double_bullet = False
    # 解除我方无敌状态定时器
    INVINCIBLE_TIME = USEREVENT + 2                          # 自定义事件3
    # 生命数量
    life_image = pygame.image.load("images/life.png")\
        .convert_alpha()                                     # 生命的图片,小飞机表示生命
    life_rect = life_image.get_rect()                        # 图片矩形
    life_num = 3                                             # 初始化3条命
    # 用于阻止重复打开记录文件
    recorded = False
    # 游戏结束画面
    gameover_font = pygame.font.Font("font/font.ttf", 48)                # 字体,字号
    again_image = pygame.image.load("images/again.png").convert_alpha()  # 再来一次的图片
    again_rect = again_image.get_rect()                                  # 图片矩形
    gameover_image = pygame.image.load("images/gameover.png").convert_alpha()  # 游戏结束的图片
    gameover_rect = gameover_image.get_rect()                                  # 图片矩形
    # 用于切换图片
    switch_image = True
    # 用于延迟
    delay = 100
    running = True            # 这个就没改过
    while running:
        for event in pygame.event.get():                                       # 遍历事件
            if event.type == QUIT:
                pygame.quit()
                sys.exit()
            elif event.type == MOUSEBUTTONDOWN:                                # 按下鼠标
                if event.button == 1 and paused_rect.collidepoint(event.pos):  # 1是左键,鼠标在按钮上且点击了左键
                    paused = not paused                                        # 暂停不暂停相互切换
                    if paused:                                                 # 如果暂停
                        pygame.time.set_timer(SUPPLY_TIME, 0)                  # 暂停供给
                        pygame.mixer.music.pause()                             # 暂停音乐
                        pygame.mixer.pause()                                   # 暂停混音器
                    else:                                                      # 如果不暂停
                        pygame.time.set_timer(SUPPLY_TIME, 30*1000)            # 30秒一个供给
                        pygame.mixer.music.unpause()                           # 不暂停音乐
                        pygame.mixer.unpause()                                 # 不暂停混音器
            elif event.type == MOUSEMOTION:                                    # 鼠标有移动
                if paused_rect.collidepoint(event.pos):                        # 鼠标位置在图片上
                    if paused:
                        paused_image = resume_pressed_image
                    else:
                        paused_image = pause_pressed_image
                else:                                                          # 鼠标没在图片上,显示浅色的方案
                    if paused:
                        paused_image = resume_nor_image
                    else:
                        paused_image = pause_nor_image
            elif event.type == KEYDOWN:                                        # 如果有按键
                if event.key == K_SPACE:                                       # 按下的是空格键
                    if bomb_num:                                               # 如果还有全屏炸弹
                        bomb_num -= 1                                          # 剩余全屏炸弹数量-1
                        bomb_sound.play()                                      # 炸弹播放音效
                        for each in enemies:                                   # 遍历敌人
                            if each.rect.bottom > 0:                           # 如果有敌人在屏幕内
                                each.active = False                            # 毁灭它们
            elif event.type == SUPPLY_TIME:                                    # 如果有供给
                supply_sound.play()                                            # 供给音效播放
                if choice([True, False]):                                      # 随机供给
                    bomb_supply.reset()
                else:
                    bullet_supply.reset()
            elif event.type == DOUBLE_BULLET_TIME:                             # 如果是超级子弹
                is_double_bullet = False                                       # 改为False
                pygame.time.set_timer(DOUBLE_BULLET_TIME, 0)                   # 取消计时器
            elif event.type == INVINCIBLE_TIME:                                # 如果是无敌状态
                me.invincible = False                                          # 改False
                pygame.time.set_timer(INVINCIBLE_TIME, 0)                      # 取消计时器
# 升级提升游戏难度
########################################################################################################################
        # 根据用户的得分增加难度
        if level == 1 and score > 50000:
            level = 2
            upgrade_sound.play()
            # 增加3架小型敌机,2架中型敌机,1架大型敌机
            add_small_enemies(small_enemies, enemies, 3)
            add_mid_enemies(mid_enemies, enemies, 2)
            add_big_enemies(big_enemies, enemies, 1)
            # 提升小型敌机的速度
            inc_speed(small_enemies, 1)
        elif level == 2 and score > 300000:
            level = 3
            upgrade_sound.play()
            # 增加5架小型敌机,3架中型敌机,2架大型敌机
            add_small_enemies(small_enemies, enemies, 5)
            add_mid_enemies(mid_enemies, enemies, 3)
            add_big_enemies(big_enemies, enemies, 2)
            # 提升小型,中型敌机的速度
            inc_speed(small_enemies, 1)
            inc_speed(big_enemies, 1)
        elif level == 3 and score > 600000:
            level = 4
            upgrade_sound.play()
            # 增加5架小型敌机,3架中型敌机,2架大型敌机
            add_small_enemies(small_enemies, enemies, 5)
            add_mid_enemies(mid_enemies, enemies, 3)
            add_big_enemies(big_enemies, enemies, 2)
            # 提升小型,中型敌机的速度
            inc_speed(small_enemies, 1)
            inc_speed(big_enemies, 1)
        elif level == 4 and score > 1000000:
            level = 5
            upgrade_sound.play()
            # 增加5架小型敌机,3架中型敌机,2架大型敌机
            add_small_enemies(small_enemies, enemies, 5)
            add_mid_enemies(mid_enemies, enemies, 3)
            add_big_enemies(big_enemies, enemies, 2)
            # 提升小型,中型敌机的速度
            inc_speed(small_enemies, 1)
            inc_speed(big_enemies, 1)
########################################################################################################################
        screen.blit(background, (0, 0))                               # 绘制背景
        if life_num and not paused:                                   # 如果还有名且非暂停
            # 检测用户的键盘操作
            key_pressed = pygame.key.get_pressed()
            if key_pressed[K_w] or key_pressed[K_UP]:                 # 向上
                me.moveUp()
            if key_pressed[K_s] or key_pressed[K_DOWN]:               # 向下
                me.moveDown()
            if key_pressed[K_a] or key_pressed[K_LEFT]:               # 向左
                me.moveLeft()
            if key_pressed[K_d] or key_pressed[K_RIGHT]:              # 向右
                me.moveRight()
            # 绘制全屏炸弹补给并检测是否获得
            if bomb_supply.active:                                    # 炸弹供给为活跃状态时
                bomb_supply.move()                                    # 向下移动炸弹供给
                screen.blit(bomb_supply.image, bomb_supply.rect)      # 绘制炸弹图像
                if pygame.sprite.collide_mask(bomb_supply, me):       # 如果飞机接收到供给
                    get_bomb_sound.play()                             # 播放接收到的音效
                    if bomb_num < 3:                                  # 如果现存全屏炸弹数量 < 3
                        bomb_num += 1                                 # 全屏炸弹+1
                    bomb_supply.active = False                        # 供给状态改为非活跃状态
            # 绘制超级子弹补给并检测是否获得
            if bullet_supply.active:                                  # 超级子弹供给为活跃状态时
                bullet_supply.move()                                  # 向下移动超级子弹供给
                screen.blit(bullet_supply.image, bullet_supply.rect)  # 绘制超级子弹图像
                if pygame.sprite.collide_mask(bullet_supply, me):     # 如果飞机接收到供给
                    get_bullet_sound.play()                           # 播放音效
                    # 发射超级子弹
                    is_double_bullet = True                               # 超级子弹现在为活跃状态
                    pygame.time.set_timer(DOUBLE_BULLET_TIME, 18 * 1000)  # 18秒状态的定时器
                    bullet_supply.active = False                          # 供给状态改为非活跃
    # 子弹
########################################################################################################################
            # 发射子弹
            if not(delay % 10):                                       # 被10整除
                bullet_sound.play()
                if is_double_bullet:
                    bullets = bullet2
                    bullets[bullet2_index].reset((me.rect.centerx-33, me.rect.centery))
                    bullets[bullet2_index+1].reset((me.rect.centerx+30, me.rect.centery))
                    bullet2_index = (bullet2_index + 2) % BULLET2_NUM
                else:
                    bullets = bullet1
                    bullets[bullet1_index].reset(me.rect.midtop)          # 复位子弹
                    bullet1_index = (bullet1_index + 1) % BULLET1_NUM     # 索引+1
            # 检测子弹是否击中敌机
            for b in bullets:                                         # 遍历子弹
                if b.active:                                          # 如果活跃为True
                    b.move()                                          # 移动子弹
                    screen.blit(b.image, b.rect)                      # 绘制子弹
                    enemy_hit = pygame.sprite.spritecollide(b, enemies, False, pygame.sprite.collide_mask)  # 检测碰撞
                    if enemy_hit:                                     # 如果碰撞
                        b.active = False                              # 子弹活跃False
                        for e in enemy_hit:                           # 遍历碰撞
                            if e in mid_enemies or e in big_enemies:  # 如果碰撞大型敌机或者中型敌机
                                e.hit = True                          # 击中为True
                                e.energy -= 1                         # 血量-1
                                if e.energy == 0:                     # 当血量为0
                                    e.active = False                  # 敌机活跃改为False
                            else:                                     # 如果是小型飞机
                                e.active = False                      # 敌机活跃改为False
########################################################################################################################
            # 绘制大型敌机
########################################################################################################################
            for each in big_enemies:                                 # 遍历大型敌机
                if each.active:                                      # 如果敌机活跃为True
                    each.move()                                      # 移动敌机
                    if each.hit:                                     # 如果敌机被击中
                        # 绘制被打到的特效
                        screen.blit(each.image_hit, each.rect)       # 绘制击中的效果图像
                        each.hit = False                             # 击中改为False
                    else:                                            # 如果没有被击中,正常情况下
                        if switch_image:
                            screen.blit(each.image1, each.rect)      # 绘制第一张敌机图像
                        else:
                            screen.blit(each.image2, each.rect)      # 绘制第二张敌机图像
                    # 绘制血槽,黑线
                    pygame.draw.line(screen, BLACK,
                                     (each.rect.left, each.rect.top - 5),
                                     (each.rect.right, each.rect.top - 5),
                                     2)
                    # 当生命大于20%显示绿色,否则显示红色
                    energy_remain = each.energy / enemy.BigEnemy.energy
                    if energy_remain > 0.2:
                        energy_color = GREEN
                    else:
                        energy_color = RED
                    pygame.draw.line(screen, energy_color,
                                     (each.rect.left, each.rect.top - 5),
                                     (each.rect.left + each.rect.width * energy_remain,
                                      each.rect.top - 5), 2)
                    # 大型敌机即将出现在画面中,播放音效
                    if each.rect.bottom == -50:       # 大型敌机距离上边界50
                        enemy3_fly_sound.play(-1)     # 循环播放大型敌机的音效
                else:                                 # 如果大型敌机为非活跃状态
                    # 毁灭
                    if not (delay % 3):               # 被3整除
                        if e3_destroy_index == 0:     # 大型敌机被毁灭图片播放完
                            enemy3_down_sound.play()  # 播放大型敌机被击落的音效
                        screen.blit(each.destroy_images[e3_destroy_index], each.rect)
                        e3_destroy_index = (e3_destroy_index + 1) % 6   # 图片索引+1
                        if e3_destroy_index == 0:     # 播放完
                            enemy3_fly_sound.stop()   # 大型敌机被击落的音效暂停
                            score += 10000
                            each.reset()              # 敌机重置复位
########################################################################################################################
            # 绘制中型敌机
########################################################################################################################
            for each in mid_enemies:                             # 遍历中型敌机
                if each.active:                                  # 如果中型敌机活跃为True
                    each.move()                                  # 移动中型敌机
                    if each.hit:                                 # 如果被击中
                        screen.blit(each.image_hit, each.rect)   # 绘制被击中效果图像
                        each.hit = False                         # 被击中改为False,就是不在绘制被击中的效果图像
                    else:                                        # 没有被击中
                        screen.blit(each.image, each.rect)       # 绘制正常的中型敌机图像
                    # 绘制血槽
                    pygame.draw.line(screen, BLACK,
                                     (each.rect.left, each.rect.top - 5),
                                     (each.rect.right, each.rect.top - 5),
                                     2)
                    # 当生命大于20%显示绿色,否则显示红色
                    energy_remain = each.energy / enemy.MidEnemy.energy
                    if energy_remain > 0.2:
                        energy_color = GREEN
                    else:
                        energy_color = RED
                    pygame.draw.line(screen, energy_color,
                                     (each.rect.left, each.rect.top - 5),
                                     (each.rect.left + each.rect.width * energy_remain,
                                      each.rect.top - 5), 2)
                else:                                         # 如果非活跃状态
                    # 毁灭
                    if not (delay % 3):                       # 被3整除
                        if e2_destroy_index == 0:             # 播放完
                            enemy2_down_sound.play()          # 被击落的音效播放
                        screen.blit(each.destroy_images[e2_destroy_index], each.rect)  # 绘制被击落的效果图像
                        e2_destroy_index = (e2_destroy_index + 1) % 4                  # 索引+1
                        if e2_destroy_index == 0:             # 播放完
                            score += 6000
                            each.reset()                      # 复位
########################################################################################################################
            # 绘制小型敌机
########################################################################################################################
            for each in small_enemies:                   # 遍历小型敌机
                if each.active:                          # 为活跃状态
                    each.move()                          # 移动敌机
                    screen.blit(each.image, each.rect)   # 绘制敌机
                else:                                    # 如果为非活跃状态
                    # 毁灭
                    if not (delay % 3):
                        if e1_destroy_index == 0:        # 播放完
                            enemy1_down_sound.play()     # 播放被击落的音效
                        screen.blit(each.destroy_images[e1_destroy_index], each.rect)  # 绘制效果图
                        e1_destroy_index = (e1_destroy_index + 1) % 4                  # 索引+1
                        if e1_destroy_index == 0:        # 播放完
                            score += 1000
                            each.reset()                 # 复位
########################################################################################################################
########################################################################################################################
            # 检测我飞机是否被撞
            enemies_down = pygame.sprite.spritecollide(me, enemies, False, pygame.sprite.collide_mask)
            if enemies_down and not me.invincible:            # 如果被撞
                # 这里可以改无敌
                me.active = False      # 飞机活跃状态改为False
                for e in enemies_down:  # 遍历被撞的敌机
                    e.active = False    # 敌机状态也改为False
            # 绘制我方飞机
            if me.active:              # 没被撞,活跃正常时
                if switch_image:
                    screen.blit(me.image1, me.rect)   # 第一张图像
                else:
                    screen.blit(me.image2, me.rect)   # 第二张图像
            else:                      # 非活跃
                # 毁灭
                if not (delay % 3):
                    if me_destroy_index == 0:   # 播放完
                        me_down_sound.play()    # 播放坠落音效
                    screen.blit(me.destroy_images[me_destroy_index], me.rect)  # 绘制被撞图像
                    me_destroy_index = (me_destroy_index + 1) % 4              # 索引+1
                    if me_destroy_index == 0:   # 播放完
                        life_num -= 1
                        me.reset()
                        pygame.time.set_timer(INVINCIBLE_TIME, 3 * 1000)
            # 绘制全屏炸弹数量
            bomb_text = bomb_font.render("× %d" % bomb_num, True, WHITE)
            text_rect = bomb_text.get_rect()
            screen.blit(bomb_image, (10, height - 10 - bomb_rect.height))  # 先画炸弹图片
            screen.blit(bomb_text, (20 + bomb_rect.width, height - 5 - text_rect.height))    # 再画文本
            # 绘制剩余生命数量
            if life_num:
                for i in range(life_num):
                    screen.blit(life_image,
                                (width-10-(i+1)*life_rect.width,
                                 height-10-life_rect.height))
            # 绘制得分
            score_text = score_font.render("Score : %s" % str(score), True, WHITE)
            screen.blit(score_text, (10, 5))
        # 绘制游戏结束画面
        elif life_num == 0:
            # 背景音乐停止
            pygame.mixer.music.stop()
            # 停止全部音效
            pygame.mixer.stop()
            # 停止发放补给
            pygame.time.set_timer(SUPPLY_TIME, 0)
            if not recorded:
                recorded = True
                # 读取历史最高得分
                with open("record.txt", "r") as f:
                    record_score = int(f.read())
                # 如果玩家得分高于历史最高得分,存档
                if score > record_score:
                    with open("record.txt", "w") as f:
                        f.write(str(score))
            # 绘制游戏结束界面
            # 绘制结束画面
            record_score_text = score_font.render("Best : %d" % record_score, True, (255, 255, 255))
            screen.blit(record_score_text, (50, 50))
            gameover_text1 = gameover_font.render("Your Score", True, (255, 255, 255))
            gameover_text1_rect = gameover_text1.get_rect()
            gameover_text1_rect.left, gameover_text1_rect.top = \
                (width - gameover_text1_rect.width) // 2, height // 3
            screen.blit(gameover_text1, gameover_text1_rect)
            gameover_text2 = gameover_font.render(str(score), True, (255, 255, 255))
            gameover_text2_rect = gameover_text2.get_rect()
            gameover_text2_rect.left, gameover_text2_rect.top = \
                (width - gameover_text2_rect.width) // 2, \
                gameover_text1_rect.bottom + 10
            screen.blit(gameover_text2, gameover_text2_rect)
            again_rect.left, again_rect.top = \
                (width - again_rect.width) // 2, gameover_text2_rect.bottom + 50
            screen.blit(again_image, again_rect)
            gameover_rect.left, gameover_rect.top = \
                (width - again_rect.width) // 2, again_rect.bottom + 10
            screen.blit(gameover_image, gameover_rect)
            # 检测用户的鼠标操作
            # 如果用户按下鼠标左键
            if pygame.mouse.get_pressed()[0]:
                # 获取鼠标坐标
                pos = pygame.mouse.get_pos()
                # 如果用户点击“重新开始”
                if again_rect.left < pos[0] < again_rect.right and again_rect.top < pos[1] < again_rect.bottom:
                    # 调用main函数,重新开始游戏
                    main()
                    # 如果用户点击“结束游戏”
                elif gameover_rect.left < pos[0] < gameover_rect.right and \
                        gameover_rect.top < pos[1] < gameover_rect.bottom:
                    # 退出游戏
                    pygame.quit()
                    sys.exit()
        # 绘制暂停按钮
        screen.blit(paused_image, paused_rect)
########################################################################################################################
        # 切换图片,5帧切换一次
        if not(delay % 5):   # 被5整除
            switch_image = not switch_image  # 切换图片
        delay -= 1   # 递减
        if not delay:
            delay = 100
        pygame.display.flip()
        clock.tick(60)  # 一秒钟60次
# 运行
########################################################################################################################
if __name__ == "__main__":
    try:
        main()
    except SystemExit:  # 这是按下 × 的异常,直接忽略
        pass
    except:
        traceback.print_exc()
        pygame.quit()
        input()
########################################################################################################################


myplane.py


import pygame
class MyPlane(pygame.sprite.Sprite):                                       # 继承动画精灵类
    def __init__(self, bg_size):
        pygame.sprite.Sprite.__init__(self)                                # 初始化动画精灵
        self.image1 = pygame.image.load("images/me1.png").convert_alpha()  # 飞机图片1
        self.image2 = pygame.image.load("images/me2.png").convert_alpha()  # 飞机图片2
        self.destroy_images = []
        self.destroy_images.extend([
            pygame.image.load("images/me_destroy_1.png").convert_alpha(),  # 飞机被撞图片1
            pygame.image.load("images/me_destroy_2.png").convert_alpha(),  # 飞机被撞图片2
            pygame.image.load("images/me_destroy_3.png").convert_alpha(),  # 飞机被撞图片3
            pygame.image.load("images/me_destroy_4.png").convert_alpha()   # 飞机被撞图片4
                ])
        self.rect = self.image1.get_rect()                                 # 飞机图片矩形位置
        self.width, self.height = bg_size[0], bg_size[1]                   # 屏幕宽,高
        self.rect.left, self.rect.top = \
            (self.width - self.rect.width) // 2, \
            self.height - self.rect.height - 60                            # 使飞机在正下方
        self.speed = 10                                                    # 飞机速度为10
        self.active = True
        self.invincible = False   # 无敌
        self.mask = pygame.mask.from_surface(self.image1)                  # 标记飞机非透明部分
    def moveUp(self):                                                      # 向上移动的方法
        if self.rect.top > 0:                                              # 飞机矩形坐标上边界 > 0
            self.rect.top -= self.speed                                    # 坐标数值变小,即向上移动
        else:                                                              # 到屏幕顶端
            self.rect.top = 0                                              # 保证飞机不出屏幕
    def moveDown(self):                                                    # 向下移动的方法
        if self.rect.bottom < self.height - 60:
            self.rect.top += self.speed
        else:
            self.rect.bottom = self.height - 60
    def moveLeft(self):
        if self.rect.left > 0:
            self.rect.left -= self.speed
        else:
            self.rect.left = 0
    def moveRight(self):
        if self.rect.right < self.width:
            self.rect.left += self.speed
        else:
            self.rect.right = self.width
    def reset(self):
        self.rect.left, self.rect.top = \
            (self.width - self.rect.width) // 2, \
            self.height - self.rect.height - 60
        self.active = True
        self.invincible = True


enemy.py


import pygame
from random import *
class SmallEnemy(pygame.sprite.Sprite):                                      # 小型敌机类,继承动画精灵类
    def __init__(self, bg_size):
        pygame.sprite.Sprite.__init__(self)                                  # 初始化动画精灵
        self.image = pygame.image.load("images/enemy1.png").convert_alpha()  # 小型敌机图片
        self.destroy_images = []
        self.destroy_images.extend([
            pygame.image.load("images/enemy1_down1.png").convert_alpha(),    # 小型敌机被击落图片1
            pygame.image.load("images/enemy1_down2.png").convert_alpha(),    # 小型敌机被击落图片2
            pygame.image.load("images/enemy1_down3.png").convert_alpha(),    # 小型敌机被击落图片3
            pygame.image.load("images/enemy1_down4.png").convert_alpha()     # 小型敌机被击落图片4
            ])
        self.rect = self.image.get_rect()                                    # 小型敌机矩形位置
        self.width, self.height = bg_size[0], bg_size[1]                     # 屏幕宽,高
        self.speed = 2                                                       # 小型敌机速度为2
        self.active = True                                                   # 初始化在动
        self.rect.left, self.rect.top = \
            randint(0, self.width - self.rect.width), \
            randint(-5 * self.height, 0)                                     # 随机生成小型敌机位置,在屏幕上边界外面
        self.mask = pygame.mask.from_surface(self.image)                     # 标记小型敌机图片非透明部分
    def move(self):                                                          # 小型敌机移动的方法,只能向下移动
        if self.rect.top < self.height:
            self.rect.top += self.speed
        else:                                                                # 出了屏幕下边界
            self.reset()                                                     # 重置
    def reset(self):                                                         # 重置的方法
        self.active = True                                                   # 重置在动
        self.rect.left, self.rect.top = \
            randint(0, self.width - self.rect.width), \
            randint(-5 * self.height, 0)                                     # 重新随机在屏幕上边界外面生成
class MidEnemy(pygame.sprite.Sprite):                                        # 中型敌机类,继承动画精灵类
    energy = 8                                                               # 中型敌机的血量8
    def __init__(self, bg_size):
        pygame.sprite.Sprite.__init__(self)                                  # 初始化动画精灵类
        self.image = pygame.image.load("images/enemy2.png").convert_alpha()  # 中型敌机图片
        self.image_hit = pygame.image.load("images/enemy2_hit.png")\
            .convert_alpha()                                                 # 中型敌机被击中时的图片
        self.destroy_images = []
        self.destroy_images.extend([
            pygame.image.load("images/enemy2_down1.png").convert_alpha(),    # 中型敌机被击落的图片1
            pygame.image.load("images/enemy2_down2.png").convert_alpha(),    # 中型敌机被击落的图片2
            pygame.image.load("images/enemy2_down3.png").convert_alpha(),    # 中型敌机被击落的图片3
            pygame.image.load("images/enemy2_down4.png").convert_alpha()     # 中型敌机被击落的图片4
            ])
        self.rect = self.image.get_rect()                                    # 中型敌机矩形位置
        self.width, self.height = bg_size[0], bg_size[1]                     # 窗口的宽,高
        self.speed = 1                                                       # 中型敌机移动速度
        self.active = True                                                   # 初始化在动
        self.rect.left, self.rect.top = \
            randint(0, self.width - self.rect.width), \
            randint(-10 * self.height, -self.height)                         # 随机生成中型敌机位置,在屏幕上边界外面
        self.mask = pygame.mask.from_surface(self.image)                     # 标记中型敌机图片非透明部分
        self.energy = MidEnemy.energy                                        # 中型敌机的血量为8
        self.hit = False                                                     # 初始化没击中
    """中型敌机移动的方法,只能向下,处理屏幕就重置复位"""
    def move(self):                                                          # 移动的方法,只能向下
        if self.rect.top < self.height:
            self.rect.top += self.speed
        else:                                                                # 出了屏幕底端
            self.reset()                                                     # 重置
    """"重置的方法"""
    def reset(self):                                                         # 重置的方法
        self.active = True                                                   # 重置在动
        self.energy = MidEnemy.energy                                        # 重置血量8
        self.rect.left, self.rect.top = \
            randint(0, self.width - self.rect.width), \
            randint(-10 * self.height, -self.height)                         # 重新随机在屏幕上边界外面生成
class BigEnemy(pygame.sprite.Sprite):                                        # 大型敌机类,继承动画精灵类
    energy = 20                                                              # 大型敌机血量20
    def __init__(self, bg_size):
        pygame.sprite.Sprite.__init__(self)                                  # 初始化动画精灵
        self.image1 = pygame.image.load("images/enemy3_n1.png")\
            .convert_alpha()                                                 # 大型敌机图片1
        self.image2 = pygame.image.load("images/enemy3_n2.png")\
            .convert_alpha()                                                 # 大型敌机图片2
        self.image_hit = pygame.image.load("images/enemy3_hit.png")\
            .convert_alpha()                                                 # 大型敌机被击中时图片
        self.destroy_images = []
        self.destroy_images.extend([
            pygame.image.load("images/enemy3_down1.png").convert_alpha(),    # 大型敌机被击落图片1
            pygame.image.load("images/enemy3_down2.png").convert_alpha(),    # 大型敌机被击落图片2
            pygame.image.load("images/enemy3_down3.png").convert_alpha(),    # 大型敌机被击落图片3
            pygame.image.load("images/enemy3_down4.png").convert_alpha(),    # 大型敌机被击落图片4
            pygame.image.load("images/enemy3_down5.png").convert_alpha(),    # 大型敌机被击落图片5
            pygame.image.load("images/enemy3_down6.png").convert_alpha()     # 大型敌机被击落图片6
            ])
        self.rect = self.image1.get_rect()                                   # 大型敌机矩形位置
        self.width, self.height = bg_size[0], bg_size[1]                     # 屏幕宽,高
        self.speed = 1                                                       # 大型敌机速度为1
        self.active = True                                                   # 初始化在动
        self.rect.left, self.rect.top = \
            randint(0, self.width - self.rect.width), \
            randint(-15 * self.height, -5 * self.height)                     # 随机生成大型敌机位置,在屏幕上边界外面
        self.mask = pygame.mask.from_surface(self.image1)                    # 标记大型敌机图片非透明部分
        self.energy = BigEnemy.energy                                        # 大型敌机血量20
        self.hit = False                                                     # 初始化没击中
    def move(self):                                                          # 移动的方法,只能向下移动
        if self.rect.top < self.height:
            self.rect.top += self.speed
        else:                                                                # 出了屏幕下边界
            self.reset()                                                     # 重置
    def reset(self):                                                         # 重置的方法
        self.active = True                                                   # 重置在动
        self.energy = BigEnemy.energy                                        # 重置血量
        self.rect.left, self.rect.top = \
            randint(0, self.width - self.rect.width), \
            randint(-15 * self.height, -5 * self.height)                     # 重置位置,在屏幕上边界外面


bullet.py


import pygame
class Bullet1(pygame.sprite.Sprite):                                          # 子弹类,继承动画精灵类
    def __init__(self, position):
        pygame.sprite.Sprite.__init__(self)                                   # 初始化动画精灵
        self.image = pygame.image.load("images/bullet1.png").convert_alpha()  # 子弹图片
        self.rect = self.image.get_rect()                                     # 子弹图片的矩形
        self.rect.left, self.rect.top = position                              # 子弹图片矩形位置在哪里
        self.speed = 12                                                       # 子弹速度
        self.active = False                                                   # 初始化子弹在动
        self.mask = pygame.mask.from_surface(self.image)                      # 标记子弹图片非透明部分
    def move(self):                                                           # 子弹移动的方法,只能向上移动
        self.rect.top -= self.speed
        if self.rect.top < 0:                                                 # 子弹到达上边界
            self.active = False                                               # 子弹不动
    def reset(self, position):                                                # 重置的方法
        self.rect.left, self.rect.top = position                              # 重置位置
        self.active = True                                                    # 重置在动
class Bullet2(pygame.sprite.Sprite):                                          # 子弹类,继承动画精灵类
    def __init__(self, position):
        pygame.sprite.Sprite.__init__(self)                                   # 初始化动画精灵
        self.image = pygame.image.load("images/bullet2.png").convert_alpha()  # 子弹图片
        self.rect = self.image.get_rect()                                     # 子弹图片的矩形
        self.rect.left, self.rect.top = position                              # 子弹图片矩形位置在哪里
        self.speed = 14                                                      # 子弹速度
        self.active = False                                                  # 初始化子弹在动
        self.mask = pygame.mask.from_surface(self.image)                      # 标记子弹图片非透明部分
    def move(self):                                                           # 子弹移动的方法,只能向上移动
        self.rect.top -= self.speed
        if self.rect.top < 0:                                                 # 子弹到达上边界
            self.active = False                                               # 子弹不动
    def reset(self, position):                                                # 重置的方法
        self.rect.left, self.rect.top = position                              # 重置位置
        self.active = True


supply.py


import pygame
from random import *
class Bullet_Supply(pygame.sprite.Sprite):
    def __init__(self, bg_size):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.image.load("images/bullet_supply.png").convert_alpha()
        self.rect = self.image.get_rect()
        self.width, self.height = bg_size[0], bg_size[1]
        self.rect.left, self.rect.bottom = \
            randint(0, self.width - self.rect.width), -100
        self.speed = 5
        self.active = False
        self.mask = pygame.mask.from_surface(self.image)
    def move(self):
        if self.rect.top < self.height:
            self.rect.top += self.speed
        else:
            self.active = False
    def reset(self):
        self.active = True
        self.rect.left, self.rect.bottom = \
            randint(0, self.width - self.rect.width), -100
class Bomb_Supply(pygame.sprite.Sprite):
    def __init__(self, bg_size):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.image.load("images/bomb_supply.png").convert_alpha()
        self.rect = self.image.get_rect()
        self.width, self.height = bg_size[0], bg_size[1]
        self.rect.left, self.rect.bottom = \
            randint(0, self.width - self.rect.width), -100
        self.speed = 5
        self.active = False
        self.mask = pygame.mask.from_surface(self.image)
    def move(self):
        if self.rect.top < self.height:
            self.rect.top += self.speed
        else:
            self.active = False
    def reset(self):
        self.active = True
        self.rect.left, self.rect.bottom = \
            randint(0, self.width - self.rect.width), -100


素材:



图像,音频,字体素材太多,就不贴出来,自行下载,下载链接:


https://download.csdn.net/download/qq_39236499/12793963

相关文章
|
4月前
|
存储 人工智能 算法
使用 Python 和 Pygame 制作游戏:第九章到第十章
使用 Python 和 Pygame 制作游戏:第九章到第十章
54 0
使用 Python 和 Pygame 制作游戏:第九章到第十章
|
4月前
|
存储 程序员 对象存储
使用 Python 和 Pygame 制作游戏:第六章到第八章
使用 Python 和 Pygame 制作游戏:第六章到第八章
145 0
|
4月前
|
存储 Shell 程序员
使用 Python 和 Pygame 制作游戏:第一章到第五章
使用 Python 和 Pygame 制作游戏:第一章到第五章
71 0
|
5月前
|
Python
【pyhon】利用pygame实现彩图版飞机大战(附源码 可供大作业练习使用)
【pyhon】利用pygame实现彩图版飞机大战(附源码 可供大作业练习使用)
26 0
|
9月前
|
Python
pygame编写井字棋游戏
pygame编写井字棋游戏
133 0
|
11月前
|
算法 数据可视化 Python
Python|pygame基础之壁球游戏
Python|pygame基础之壁球游戏
129 0
|
12月前
|
Python
通过游戏学Python系列之小兔要上天---手把手教你使用Pygame开发平台跳跃类游戏06之死亡后游戏重新开始
通过游戏学Python系列之小兔要上天---手把手教你使用Pygame开发平台跳跃类游戏06之死亡后游戏重新开始
140 0
|
12月前
|
Python 容器
通过游戏学Python系列之小兔要上天---手把手教你使用Pygame开发平台跳跃类游戏05之滚动屏幕
通过游戏学Python系列之小兔要上天---手把手教你使用Pygame开发平台跳跃类游戏05之滚动屏幕
106 0
|
12月前
|
Python
通过游戏学Python系列之小兔要上天---手把手教你使用Pygame开发平台跳跃类游戏04之跳跃
通过游戏学Python系列之小兔要上天---手把手教你使用Pygame开发平台跳跃类游戏04之跳跃
108 0