【03】做一个精美的打飞机小游戏,规划游戏项目目录-分门别类所有的资源-库-类-逻辑-打包为可玩的exe-练习python打包为可执行exe-优雅草卓伊凡-持续更新-分享源代码和游戏包供游玩-1.0.2版本

简介: 【03】做一个精美的打飞机小游戏,规划游戏项目目录-分门别类所有的资源-库-类-逻辑-打包为可玩的exe-练习python打包为可执行exe-优雅草卓伊凡-持续更新-分享源代码和游戏包供游玩-1.0.2版本

【03】做一个精美的打飞机小游戏,规划游戏项目目录-分门别类所有的资源-库-类-逻辑-打包为可玩的exe-练习python打包为可执行exe-优雅草卓伊凡-持续更新-分享源代码和游戏包供游玩-1.0.2版本

背景

之前卓伊凡在AE特效制作处博文已经完整介绍了本款游戏的素材开发,本文开始把素材利用起来放进去,本游戏命名为鹰击长空,Eagles strike across the sky,简称名字ESAS!自从卓伊凡找到了人生的方向,每天就是不停的工作学习工作学习,拒接一切享乐,这就是道,感谢各位看官,涨粉也是对卓伊凡的鼓励。

章节内容03

【03】做一个精美的打飞机小游戏,规划游戏项目目录-分门别类所有的资源-库-类-逻辑-打包为可玩的exe-练习python打包为可执行exe

内容概要

·规划游戏项目目录
·打包为可玩的exe-练习python打包为可执行exe

开源源代码下载地址

https://gitee.com/youyacao/esas

游戏运行包

https://youyacao.lanzouq.com/i60sA2lht5mh

完善飞机大战小游戏-换上制作的特效序列png图片-加入boss机

规划目录结构

常规用python开发游戏我们需要建立以下这样的目录

my_game_project/
├── assets/               // 游戏资源文件(图像、音效、字体等)
│   ├── images/
│   │   ├── player.png
│   │   ├── enemy.png
│   │   └── background.jpg
│   ├── sounds/
│   │   ├── background.mp3
│   │   └── hit.wav
│   └── fonts/
│       ├── main.ttf
│       └── secondary.ttf
├── config/               // 配置文件
│   └── settings.py
├── data/                 // 数据文件(如保存文件)
│   └── scores.json
├── docs/                 // 文档
│   └── README.md
├── src/                  // 源代码
│   ├── __init__.py
│   ├── main.py          // 主程序入口
│   ├── game.py          // 游戏主逻辑
│   ├── player.py        // 玩家类
│   ├── enemy.py         // 敌人类
│   ├── settings.py      // 游戏设置
│   └── utils.py         // 辅助函数
├── tests/                // 单元测试
│   ├── __init__.py
│   ├── test_game.py
│   ├── test_player.py
│   └── test_enemy.py
└── requirements.txt      // 项目依赖

目录结构解释:

  • assets/:存放游戏资源文件,包括图像、音效和字体等。
  • config/:存放配置文件,如游戏设置和参数。
  • data/:存放数据文件,如保存文件、分数记录等。
  • docs/:存放项目文档,如 README 文件。
  • src/:存放源代码,包括游戏主逻辑、玩家类、敌人类、游戏设置和辅助函数等。
  • tests/:存放单元测试文件,用于测试游戏的各个模块。
  • requirements.txt:记录项目依赖的库和版本信息。

目前我们就开始把已有资源进行归类,由于此前我们都是用的一个文件 显然就是不合理的,根据目前已有资源和内容我们应该规划为:

planegame/
├── main.py                # 主程序入口
├── assets/
│   ├── png/
│   │   ├── boss00.png     # BOSS 动画帧
│   │   ├── ...
│   │   ├── player_100.png # 玩家动画帧
│   │   ├── ...
│   │   ├── enemy_10.png   # 敌人动画帧
│   │   ├── ...
│   │   ├── bullet0.png    # 子弹动画帧
│   │   ├── ...
│   │   ├── explosion00.png # 爆炸动画帧
│   │   ├── ...
│   └── sounds/
│       ├── bullet.wav     # 子弹发射音效
│       ├── boss.wav       # BOSS 出现背景音乐
│       └── ...
├── src/
│   ├── __init__.py        # 使 src 成为一个包
│   ├── game.py            # 游戏逻辑代码
│   ├── sprites.py         # 精灵类定义
│   └── utils.py           # 辅助函数和常量
└── README.md              # 项目说明文档

资源文件夹改为assets ,对应代码中也修改,

建立 main.py # 主程序入口 文件,并且内容如下:

import pygame
from src.game import Game
def main():
    pygame.init()
    game = Game()
    game.run()
    pygame.quit()
if __name__ == "__main__":
    main()

新建src目录,下面新建game.py,写入游戏的主逻辑

import pygame
from src.sprites import Player, Enemy, Bullet, Boss, Explosion
import random
import os
import sys
class Game:
    def __init__(self):
        self.screen_width = 720
        self.screen_height = 1280
        self.screen = pygame.display.set_mode((self.screen_width, self.screen_height))
        pygame.display.set_caption("鹰击长空-Eagles strike across the sky-优雅草央千澈")
        self.clock = pygame.time.Clock()
        self.running = True
        self.all_sprites = pygame.sprite.Group()
        self.all_enemies = pygame.sprite.Group()
        self.bullets = pygame.sprite.Group()
        self.player = Player()
        self.all_sprites.add(self.player)
        self.all_sprites.add(self.bullets)
        self.boss_spawned = False
        self.boss_spawn_time = 10000  # 10秒后生成BOSS
        self.load_sounds()
    def load_sounds(self):
        self.bullet_sound = pygame.mixer.Sound(os.path.join("assets", "sounds", "bullet.wav"))
    def run(self):
        while self.running:
            self.events()
            self.update()
            self.draw()
            self.clock.tick(60)
    def events(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                self.running = False
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE:
                    self.player.shoot()
    def update(self):
        self.all_sprites.update()
        self.all_enemies.update()
        # 生成敌人
        if random.randint(1, 100) < 5:
            enemy = Enemy()
            self.all_enemies.add(enemy)
            self.all_sprites.add(enemy)
        # 检测碰撞
        hits = pygame.sprite.groupcollide(self.all_enemies, self.bullets, True, True)
        for hit in hits:
            explosion = Explosion(hit.rect.center)
            self.all_sprites.add(explosion)
        # 检测 BOSS 是否生成
        if not self.boss_spawned and pygame.time.get_ticks() > self.boss_spawn_time:
            boss = Boss()
            self.all_sprites.add(boss)
            self.all_enemies.add(boss)
            self.boss_spawned = True
            pygame.mixer.music.load(os.path.join("assets", "sounds", "boss.wav"))
            pygame.mixer.music.play(-1)
    def draw(self):
        self.screen.fill((0, 0, 0))
        self.all_sprites.draw(self.screen)
        pygame.display.flip()

下一步,新建sprites.py 文件夹 定义游戏中的所有精灵类,如 Player, Enemy, Bullet, Boss, Explosion均放在此处,

对了有人不知道什么是精灵类,

扩展知识

在游戏开发中,“精灵类”(Sprite)是指游戏中的可视对象,通常用于表示角色、物品、背景等。精灵类的主要职责是管理和渲染这些可视对象,并处理它们的属性和行为。它是2D游戏开发中的一个重要概念。以下是关于精灵类的一些详细介绍:

精灵类的属性

  • 图像:精灵通常由一幅或多幅图像组成,用于在屏幕上显示。
  • 位置:精灵在屏幕上的坐标位置(x, y)。
  • 大小:精灵的宽度和高度。
  • 速度:精灵的移动速度和方向。
  • 动画帧:如果精灵是动画的,可以包含多个帧来创建动画效果。

精灵类的行为

  • 移动:根据速度和方向更新位置。
  • 绘制:在游戏的每一帧中将精灵绘制到屏幕上。
  • 碰撞检测:检测与其他精灵或环境的碰撞。
  • 动画更新:如果是动画精灵,根据时间或事件更新动画帧。

把精灵类代码归纳到本文件:

import pygame
import random
import os
class Boss(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.frames = [pygame.image.load(os.path.join("assets", "png", f"boss{i:02d}.png")).convert_alpha() for i in range(10)]
        self.frame = 0
        self.image = self.frames[self.frame]
        self.rect = self.image.get_rect(center=(360, -100))
        self.last_update = pygame.time.get_ticks()
        self.frame_rate = 100
        self.health = 100
        self.move_direction = 1
        self.move_speed = 2
        self.shoot_delay = 1000
        self.last_shot = pygame.time.get_ticks()
    def update(self):
        self.rect.y += 2
        if self.rect.top > 0:
            self.rect.x += self.move_speed * self.move_direction
            if self.rect.right > 720 or self.rect.left < 0:
                self.move_direction *= -1
        now = pygame.time.get_ticks()
        if now - self.last_update > self.frame_rate:
            self.last_update = now
            self.frame = (self.frame + 1) % len(self.frames)
            self.image = self.frames[self.frame]
        if now - self.last_shot > self.shoot_delay:
            self.last_shot = now
            self.shoot()
    def shoot(self):
        bullet = Bullet(self.rect.centerx, self.rect.bottom)
        self.bullets.add(bullet)
class Player(pygame.sprite.Sprite):
    # 类似于 Boss 类的定义
    pass
class Bullet(pygame.sprite.Sprite):
    # 类似于 Boss 类的定义
    pass
class Enemy(pygame.sprite.Sprite):
    # 类似于 Boss 类的定义
    pass
class Explosion(pygame.sprite.Sprite):
    # 类似于 Boss 类的定义
    pass

新建辅助函数文件utils.py

import pygame
import os
def load_image(filename):
    return pygame.image.load(os.path.join("assets", "png", filename)).convert_alpha()
def load_sound(filename):
    return pygame.mixer.Sound(os.path.join("assets", "sounds", filename))

整理完毕 运行

报错,

这个错误表明 Python 无法找到 src 模块。这通常是由于 Python 解释器无法正确识别 src 目录为一个包。以下是一些可能的解决方案:

确保 src 目录包含 init.py 文件:

init.py 文件可以是空的,但它的存在告诉 Python 这个目录是一个包。
确保 src 目录下有一个 init.py 文件。

也就是说我必须建立 init.py 文件,哪怕为空,ok建立好了再次运行

继续报错,这个是因为 Player 对象没有 image 属性。在 Pygame 中,pygame.sprite.Sprite 类要求每个精灵对象必须有一个 image 属性,因为 draw 方法会使用这个属性来绘制精灵。

让我们检查 Player 类的定义,确保它正确地设置了 image 属性。

修改game.py

# src/game.py
import pygame
from src.sprites import Player, Enemy, Bullet, Boss, Explosion
import random
import os
import sys
# 加载图像
player_frames = []
for i in range(12):  # 假设有12帧,从player_100.png到player_111.png
    frame = pygame.image.load(os.path.join("assets", "png", f"player_{100 + i:03d}.png")).convert_alpha()
    frame = pygame.transform.scale(frame, (150, 150))  # 调整为150x150像素
    player_frames.append(frame)
class Game:
    def __init__(self):
        self.screen_width = 720
        self.screen_height = 1280
        self.screen = pygame.display.set_mode((self.screen_width, self.screen_height))
        pygame.display.set_caption("鹰击长空-Eagles strike across the sky-优雅草央千澈")
        self.clock = pygame.time.Clock()
        self.running = True
        self.all_sprites = pygame.sprite.Group()
        self.all_enemies = pygame.sprite.Group()
        self.bullets = pygame.sprite.Group()
        self.player = Player()
        self.all_sprites.add(self.player)
        self.all_sprites.add(self.bullets)
        self.boss_spawned = False
        self.boss_spawn_time = 10000  # 10秒后生成BOSS
        self.load_sounds()
    def load_sounds(self):
        self.bullet_sound = pygame.mixer.Sound(os.path.join("assets", "sounds", "bullet.wav"))
    def run(self):
        while self.running:
            self.events()
            self.update()
            self.draw()
            self.clock.tick(60)
    def events(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                self.running = False
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE:
                    self.player.shoot()
    def update(self):
        self.all_sprites.update()
        self.all_enemies.update()
        # 生成敌人
        if random.randint(1, 100) < 5:
            enemy = Enemy()
            self.all_enemies.add(enemy)
            self.all_sprites.add(enemy)
        # 检测碰撞
        hits = pygame.sprite.groupcollide(self.all_enemies, self.bullets, True, True)
        for hit in hits:
            explosion = Explosion(hit.rect.center)
            self.all_sprites.add(explosion)
        # 检测 BOSS 是否生成
        if not self.boss_spawned and pygame.time.get_ticks() > self.boss_spawn_time:
            boss = Boss()
            self.all_sprites.add(boss)
            self.all_enemies.add(boss)
            self.boss_spawned = True
            pygame.mixer.music.load(os.path.join("assets", "sounds", "boss.wav"))
            pygame.mixer.music.play(-1)
    def draw(self):
        self.screen.fill((0, 0, 0))
        self.all_sprites.draw(self.screen)
        pygame.display.flip()

然后几经折腾,基本上就是 类没有初始化之类的问题,或者 Enemy 类的 init 方法中,enemy_frames 未被定义。同样地,boss_frames 和 bullet_frames 也会遇到类似的问题,经过了 1个小时的处理,终于好了

处理好了以后可以正常运行了终于,成功了,

由于文章篇幅问题,我们开始进行打包工作,python 游戏 项目 如何 直接打包为可执行exe

要将一个 Python 游戏项目打包为可执行的 EXE 文件,可以使用 PyInstaller 这个工具:

安装 PyInstaller

首先,你需要安装 PyInstaller。你可以通过 pip 来安装:

pip install pyinstaller

安装成功

项目主文件是 main.py

使用 PyInstaller 打包项目

进入你的项目目录,然后运行以下命令:

pyinstaller --onefile main.py

直接执行,在卓伊凡的目录下,

这个命令将生成一个单独的 EXE 文件。--onefile 选项表示将所有内容打包到一个文件中,ok 现在分享蓝奏云

直接成功 15993 INFO: Copying bootloader EXE to G:\clone\esas\dist\main.exe
15995 INFO: Copying icon to EXE

想必通过此文,也知道python项目如何打包exe了吧

目录
打赏
0
30
31
9
202
分享
相关文章
【03】仿站技术之python技术,看完学会再也不用去购买收费工具了-修改整体页面做好安卓下载发给客户-并且开始提交网站公安备案-作为APP下载落地页文娱产品一定要备案-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
【03】仿站技术之python技术,看完学会再也不用去购买收费工具了-修改整体页面做好安卓下载发给客户-并且开始提交网站公安备案-作为APP下载落地页文娱产品一定要备案-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
85 13
【03】仿站技术之python技术,看完学会再也不用去购买收费工具了-修改整体页面做好安卓下载发给客户-并且开始提交网站公安备案-作为APP下载落地页文娱产品一定要备案-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
【02】做一个精美的打飞机小游戏,python开发小游戏-鹰击长空—优雅草央千澈-持续更新-分享源代码和游戏包供游玩-记录完整开发过程-用做好的素材来完善鹰击长空1.0.1版本
【02】做一个精美的打飞机小游戏,python开发小游戏-鹰击长空—优雅草央千澈-持续更新-分享源代码和游戏包供游玩-记录完整开发过程-用做好的素材来完善鹰击长空1.0.1版本
89 7
|
1月前
|
【01】整体试验思路,如何在有UID的情况下获得用户手机号信息,python开发之理论研究试验,如何通过抖音视频下方的用户的UID获得抖音用户的手机号-本系列文章仅供学习研究-禁止用于任何商业用途-仅供学习交流-优雅草卓伊凡
【01】整体试验思路,如何在有UID的情况下获得用户手机号信息,python开发之理论研究试验,如何通过抖音视频下方的用户的UID获得抖音用户的手机号-本系列文章仅供学习研究-禁止用于任何商业用途-仅供学习交流-优雅草卓伊凡
184 82
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
70 8
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
66 7
【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
【02】整体试验思路,在这之前我们发现sec_uid,sec_uid是什么和uid的关系又是什么?相互如何转换?python开发之理论研究试验,如何通过抖音视频下方的用户的UID获得抖音用户的手机号-本系列文章仅供学习研究-禁止用于任何商业用途-仅供学习交流-优雅草卓伊凡
【02】整体试验思路,在这之前我们发现sec_uid,sec_uid是什么和uid的关系又是什么?相互如何转换?python开发之理论研究试验,如何通过抖音视频下方的用户的UID获得抖音用户的手机号-本系列文章仅供学习研究-禁止用于任何商业用途-仅供学习交流-优雅草卓伊凡
75 6
|
10月前
|
如何使用Python实现“猜数字”游戏
本文介绍了使用Python实现“猜数字”游戏的过程。游戏规则是玩家在给定范围内猜一个由计算机随机生成的整数,猜对则获胜。代码中,首先导入random模块生成随机数,然后在循环中获取玩家输入并判断大小,提供猜小、猜大提示。通过增加猜测次数限制、难度选择、优化输入提示和图形化界面等方式可优化游戏。这篇文章旨在帮助初学者通过实际操作学习Python编程。
389 2
Python实现猜数字游戏
Python实现猜数字游戏
178 0
用python写出一个猜数字游戏
用python写出一个猜数字游戏
110 4
|
10月前
|
用 Python 写一个猜数字游戏并运行它
用 Python 写一个猜数字游戏并运行它
53 0