pygame飞机大战 小游戏

运行效果

飞机大战

代码

# 先导入系统模块
import sys
# 随机模块
import random

# 再导入第三方模块
import pygame
import pygame.locals


# 背景图片路径
IMG_BACKGROUND = "res/img_bg_level_1.jpg"
# 敌机图片路径 元组
IMG_ENEMYPLANE = ("res/img-plane_1.png", "res/img-plane_2.png", "res/img-plane_3.png", "res/img-plane_4.png",
                  "res/img-plane_5.png", "res/img-plane_6.png", "res/img-plane_7.png")
# 玩家飞机图片路径
IMG_PLAYER_PLANE = "res/hero2.png"
# 子弹图片
IMG_BULLET = "res/bullet_13.png"


class Model(object):
    """提供基础模型"""
    # 窗口对象
    window = None

    def __init__(self, img_path, x, y):
        # 图片对象
        self.img = pygame.image.load(img_path)
        # x坐标
        self.x = x
        # y坐标
        self.y = y

    def display(self):
        # 将要显示的对象添加到窗体中, 并指定其坐标
        Model.window.blit(self.img, (self.x, self.y))


class Game(object):
    """游戏整体控制"""
    # 窗口宽度
    WINDOW_WIDTH = 512
    # 窗口高度
    WINDOW_HEIGHT = 768
    # 窗体标题
    WINDOW_TITLE = "Plane Battle v1.0"
    # 小图标路径
    APP_ICON = "res/app.ico"

    def __init__(self):
        # 窗体对象
        self.window = None
        # 背景对象
        self.background = None
        # 敌机对象
        self.enemy_planes = list()
        # 玩家对象
        self.player_plane = None

    def run(self):
        """运行入口, 整体游戏控制"""
        # 框架初始化
        self.frame_init()
        # 模型初始化
        self.model_init()
        # 构造反复执行的机制, 刷新窗体、使窗体保持在屏幕上
        while True:
            # 背景移动
            self.background.move()
            # 显示背景
            self.background.display()

            for enemy_plane in self.enemy_planes:
                # 敌机下降
                enemy_plane.move()
                # 显示敌机(加载贴图)
                enemy_plane.display()

            # 显示玩家
            self.player_plane.display()
            # 把敌机列表传给玩家飞机, 好进行子弹与敌机的碰撞检测
            self.player_plane.collision_checking(self.enemy_planes)
            # 刷新窗体
            pygame.display.update()
            # 事件监听
            self.event_init()

    def frame_init(self):
        """窗体初始化"""
        # 设置窗体对象
        self.window = pygame.display.set_mode((Game.WINDOW_WIDTH, Game.WINDOW_HEIGHT))
        # 将窗口对象传给Model类属性
        Model.window = self.window
        # 左上小图标对象
        app_img = pygame.image.load(Game.APP_ICON)
        # 设置窗体图标
        pygame.display.set_icon(app_img)
        # 设置窗体标题文本
        pygame.display.set_caption(Game.WINDOW_TITLE)

    def model_init(self):
        """初始化窗体中的对象"""
        # 背景对象
        self.background = Background(IMG_BACKGROUND, 0, 0)
        for _ in IMG_ENEMYPLANE:
            # 加入多加敌机到 敌机列表中
            self.enemy_planes.append(EnemyPlane())
        # 玩家对象
        self.player_plane = PlayerPlane(IMG_PLAYER_PLANE, PlayerPlane.PLAYERPLANE_X, PlayerPlane.PLAYERPLANE_Y)

    def event_init(self):
        """事件监听"""
        # 获取事件列表中的每一个事件
        for event in pygame.event.get():
            # 判断事件类别是否为退出事件
            if event.type == pygame.locals.QUIT:
                # 退出程序
                sys.exit()
            # 当事件类别是鼠标移动动作时
            if event.type == pygame.locals.MOUSEMOTION:
                # 获取鼠标坐标位置
                position = pygame.mouse.get_pos()
                # 根据鼠标的位置设置玩家飞机的位置
                self.player_plane.x = position[0] - PlayerPlane.PLAYERPLANE_WIDTH / 2
                self.player_plane.y = position[1] - PlayerPlane.PLAYERPLANE_HEIGHT / 2 + 5
        # 获取鼠标是否按下的状态
        mouse_state = pygame.mouse.get_pressed()
        # 判断是否按下鼠标左键
        if mouse_state[0] == 1:
            # 获取鼠标坐标位置
            position = pygame.mouse.get_pos()
            # 初始化子弹位置
            self.player_plane.bullets.append(
                Bullet(IMG_BULLET, position[0] - Bullet.BULLET_WIDTH / 2,
                       position[1] - Bullet.BULLET_HEIGHT - 30))
            # 当玩家按下鼠标左键时, 才开始游戏
            self.player_plane.start_game = True


class Background(Model):
    """背景"""
    def display(self):
        """装载上下两张图片到窗体中"""
        # 将要显示的对象添加到窗体中, 并指定其坐标
        Model.window.blit(self.img, (self.x, self.y))
        Model.window.blit(self.img, (self.x, self.y - Game.WINDOW_HEIGHT))

    def move(self):
        """背景移动"""
        # 当纵轴的值小于等于屏幕高度时:
        if self.y <= Game.WINDOW_HEIGHT:
            # 移动图片
            self.y += 1
        else:
            # 图片归位
            self.y = 0


class PlayerPlane(Model):
    """玩家飞机"""
    # 玩家飞机的宽度
    PLAYERPLANE_WIDTH = 120
    # 玩家飞机的高度
    PLAYERPLANE_HEIGHT = 78
    # 玩家飞机的初始位置
    PLAYERPLANE_X = 200
    PLAYERPLANE_Y = 500

    def __init__(self, img, x, y):
        super().__init__(img, x, y)
        # 子弹列表对象
        self.bullets = list()
        # 需要删除的子弹列表
        self.remove_bullets = list()
        # 玩家是否开始游戏标志
        self.start_game = False

    def collision_checking(self, enemy_list):
        """子弹的显示, 还有子弹与敌机的碰撞检测"""
        for bullet in self.bullets:
            # 子弹移动
            bullet.move()
            # 子弹显示
            bullet.display()
            # 当子弹飞出屏幕时:
            if bullet.y < -Bullet.BULLET_HEIGHT:
                # 将这个子弹添加到待删除子弹的列表
                self.remove_bullets.append(bullet)
            # 子弹没有飞出屏幕
            else:
                # 子弹矩形
                bullet_rect = pygame.locals.Rect(bullet.x, bullet.y, Bullet.BULLET_WIDTH, Bullet.BULLET_HEIGHT)

                for enemy in enemy_list:
                    # 敌机矩形
                    enemy_rect = pygame.locals.Rect(enemy.x, enemy.y, EnemyPlane.ENEMYPLANE_WIDTH, EnemyPlane.ENEMYPLANE_HEIGHT)

                    # 两个矩形碰撞检测
                    if pygame.Rect.colliderect(bullet_rect, enemy_rect):
                        # 子弹碰撞敌机后, 敌机归位到屏幕上方
                        enemy.enemy_plane_init()
                        # 子弹加入删除列表
                        self.remove_bullets.append(bullet)
                        # 一颗子弹只能撞击 一架敌机, 退出for循环
                        break
        # 玩家飞机矩形
        player_rect = pygame.locals.Rect(self.x, self.y, PlayerPlane.PLAYERPLANE_WIDTH,
                                         PlayerPlane.PLAYERPLANE_HEIGHT)

        for enemy in enemy_list:
            # 敌机矩形
            enemy_rect = pygame.locals.Rect(enemy.x, enemy.y, EnemyPlane.ENEMYPLANE_WIDTH,
                                            EnemyPlane.ENEMYPLANE_HEIGHT)
            # 玩家飞机与敌机碰撞检测
            if pygame.Rect.colliderect(player_rect, enemy_rect):
                # 一开始游戏时, 玩家按下鼠标左键, 才能判断玩家飞机与敌机碰撞检测, 再退出游戏
                if self.start_game:
                    # 退出程序
                    sys.exit()

        # 根据 待删除子弹的列表 删除子弹列表中的对象
        for bullet in self.remove_bullets:
            self.bullets.remove(bullet)
        else:
            # 删除完后, 需要将 待删除列表清空
            self.remove_bullets.clear()


class Bullet(Model):
    """子弹"""
    # 子弹的宽度
    BULLET_WIDTH = 20
    # 子弹的高度
    BULLET_HEIGHT = 29
    # 子弹间的移动速度
    BULLET_SPEED = 8

    def move(self):
        """子弹移动"""
        self.y -= Bullet.BULLET_SPEED


class EnemyPlane(Model):
    """敌机"""
    # 敌机的宽度
    ENEMYPLANE_WIDTH = 100
    # 敌机的高度
    ENEMYPLANE_HEIGHT = 68
    # 敌机移动速度
    ENEMYPLANE_SPEED = 4

    def __init__(self):
        self.enemy_plane_init()

    def enemy_plane_init(self):
        """初始化敌机"""
        # 敌机归到窗口上方
        self.y = 0 - EnemyPlane.ENEMYPLANE_HEIGHT
        # 敌机横坐标随机出现
        self.x = random.randint(0, Game.WINDOW_WIDTH - EnemyPlane.ENEMYPLANE_WIDTH)
        # 贴图随机
        self.img = pygame.image.load(IMG_ENEMYPLANE[random.randint(0, 6)])

    def move(self):
        # 当敌机没有下降出屏幕高度时
        if self.y <= Game.WINDOW_HEIGHT:
            # 移动敌机
            self.y += EnemyPlane.ENEMYPLANE_SPEED
        else:
            self.enemy_plane_init()


if __name__ == '__main__':
    Game().run()

打包成exe文章链接

记一次pygame小程序打包成exe

图片素材地址

链接: https://pan.baidu.com/s/1mMeJfSqEjSgMATxU6SXfZg
提取码: 9cge

©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页