飞机大战是一款经典的竖版飞行射击游戏,玩家控制一架战机击落不断来袭的敌机。这款游戏虽然规则简单,但它几乎涵盖了游戏开发中所有核心概念:游戏主循环、精灵(Sprite)管理、碰撞检测、事件处理、动画效果、音效播放、分数系统等。通过完成这个项目,你将掌握使用Pygame开发2D游戏的完整流程。
本文将从零开始,手把手教你使用Python和Pygame库开发一个完整的飞机大战游戏。全文共分为10个部分,每一部分都有详细的代码和注释。整个教程代码长达数百行,但逻辑清晰,每一步都有详尽解释。即使你是第一次接触游戏开发,跟着教程一步一步做也能完成一个可玩的游戏。
最终游戏效果预览:
玩家用鼠标或键盘控制战机上下左右移动
按空格键或鼠标左键发射子弹
敌机会源源不断地从屏幕顶部随机位置出现,并向底部移动
子弹击中敌机后,敌机会爆炸消失,玩家增加10分
战机碰到敌机则游戏结束,游戏停止
屏幕上显示实时分数
游戏结束后按“R”键可以重新开始
第一部分:准备工作与Pygame入门
1.1 什么是Pygame
Pygame是一个专门为游戏开发设计的Python库,它封装了底层的SDL(Simple DirectMedia Layer),提供了图像、声音、事件处理、碰撞检测等游戏开发所需的核心功能。Pygame让开发者可以专注于游戏逻辑,而不必关心底层细节。
1.2 环境搭建
首先,确保你的电脑已经安装了Python(版本3.6以上)。打开终端(Windows用cmd或PowerShell,Mac/Linux用Terminal),输入以下命令检查Python版本:
python --version
如果未安装Python,请前往python.org下载安装。安装时记得勾选“Add Python to PATH”。
接着,安装Pygame库:
pip install pygame
安装完成后,验证是否安装成功:
python -c "import pygame; print(pygame.version.ver)"
如果能正常输出Pygame的版本号(如“2.5.0”),说明安装成功。
1.3 创建第一个Pygame窗口
在进入飞机大战开发前,先了解Pygame最基础的窗口程序。以下是完整的代码,后面每一行都有详细注释:
import pygame # 导入pygame库
import sys # 导入系统库,用于退出程序
# 1. 初始化Pygame
# pygame.init()会初始化所有导入的pygame模块(包括display、font、mixer等)
# 如果不调用这一句,使用其他pygame功能会报错
pygame.init()
# 2. 设置游戏窗口大小常量
# 定义宽度和高度,方便后续修改
SCREEN_WIDTH = 480 # 窗口宽度(像素)
SCREEN_HEIGHT = 700 # 窗口高度(像素)
# 3. 创建游戏窗口
# pygame.display.set_mode()创建显示表面(Surface)
# 参数是一个元组(width, height),表示窗口大小
# 这个函数返回一个Surface对象,代表整个窗口
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
# 4. 设置窗口标题
# 窗口标题会显示在窗口的标题栏上
pygame.display.set_caption("飞机大战")
# 5. 创建时钟对象
# 时钟对象用于控制游戏的帧率(FPS)
# 后面用clock.tick(帧数)来设定游戏每秒刷新多少次
clock = pygame.time.Clock()
# 6. 设置游戏主循环
# 这是一个无限循环,游戏运行时一直执行
# 所有游戏逻辑(事件处理、更新、绘制)都在这个循环里
running = True # 控制循环的变量
while running:
# -------- 事件处理 --------
# pygame.event.get()获取所有发生的事件(键盘按键、鼠标点击、窗口关闭等)
# 遍历这些事件,一一处理
for event in pygame.event.get():
if event.type == pygame.QUIT:
# 如果用户点击了窗口右上角的“X”关闭按钮
running = False # 退出主循环
# -------- 绘制 --------
# screen.fill(color)用指定颜色填充整个窗口
# 参数是RGB颜色,从0到255
# 如果不填充,上一帧的画面会残留,导致“拖影”效果
screen.fill((0, 0, 0)) # 黑色背景
# -------- 刷新显示 --------
# pygame.display.flip()将缓冲区的内容显示到屏幕上
# 所有绘制操作都是先在后台缓冲区绘制,然后一次性显示,这样画面不会闪烁
pygame.display.flip()
# -------- 控制帧率 --------
# clock.tick(60)控制游戏每秒最多循环60次
# 这样游戏在不同性能的电脑上运行速度一致(不会太快或太慢)
clock.tick(60)
# 退出游戏,关闭窗口
pygame.quit()
sys.exit()
运行这段代码:保存为.py文件并运行,会看到一个黑色的窗口,点击关闭按钮可以退出程序。
http://wgywbxw.cn/
需要理解的概念:
第二部分:理解游戏精灵
2.1 什么是精灵(Sprite)
在游戏开发中,“精灵”是指游戏中可以独立移动、绘制和相互交互的图形对象。例如:玩家飞机、敌方飞机、子弹、爆炸效果等都是精灵。
Pygame提供了一个pygame.sprite.Sprite类,作为所有精灵的基类。我们只需要继承这个类,就可以利用Pygame内置的碰撞检测、组管理等强大功能。
2.2 创建玩家飞机精灵
下面我们创建一个简单的玩家飞机精灵,用矩形表示飞机(后续可以换成图片)。每一步都有详细注释。
import pygame
import sys
pygame.init()
SCREEN_WIDTH = 480
SCREEN_HEIGHT = 700
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("飞机大战")
clock = pygame.time.Clock()
# ------------------- 定义玩家飞机类 -------------------
# 继承自pygame.sprite.Sprite,这样它就拥有了精灵的基本功能
class Player(pygame.sprite.Sprite):
def __init__(self):
"""初始化玩家飞机"""
# 必须调用父类的构造函数,否则Sprite的初始化不会执行
super().__init__()
# 创建一个简单的矩形作为飞机的图像(Surface)
# 参数(width, height),这里用50x50的正方形
self.image = pygame.Surface((50, 50))
# 填充颜色,这里用蓝色
self.image.fill((0, 0, 255))
# 获取图像的矩形区域(Rect)
# Rect对象有x, y, width, height属性,以及center, left, right, top, bottom等便捷属性
self.rect = self.image.get_rect()
# 设置飞机的初始位置:屏幕中间靠下
# centerx = 屏幕宽度的中心
self.rect.centerx = SCREEN_WIDTH // 2
# bottom = 离屏幕底部10像素
self.rect.bottom = SCREEN_HEIGHT - 10
# 水平移动速度
self.speed = 5
# 左移标记(按左箭头为True,释放为False)
self.moving_left = False
# 右移标记
self.moving_right = False
def update(self):
"""更新玩家位置,每帧调用一次"""
# 如果左移标记为True,向左移动
if self.moving_left:
self.rect.x -= self.speed
# 如果右移标记为True,向右移动
if self.moving_right:
self.rect.x += self.speed
# 边界限制:防止飞出屏幕左右两侧
# 如果飞机的左边缘超出屏幕左边界,拉回来
if self.rect.left < 0:
self.rect.left = 0
# 如果飞机的右边缘超出屏幕右边界,拉回来
if self.rect.right > SCREEN_WIDTH:
self.rect.right = SCREEN_WIDTH
# ------------------- 创建玩家飞机实例 -------------------
# 创建一个Player对象,它就是一个精灵
player = Player()
# ------------------- 主游戏循环 -------------------
running = True
while running:
# ---------- 事件处理 ----------
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# 键盘按下事件
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
# 左箭头按下,设置左移标记为True
player.moving_left = True
if event.key == pygame.K_RIGHT:
# 右箭头按下,设置右移标记为True
player.moving_right = True
# 键盘释放事件
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
# 左箭头释放,停止左移
player.moving_left = False
if event.key == pygame.K_RIGHT:
# 右箭头释放,停止右移
player.moving_right = False
# ---------- 更新 ----------
# 调用update方法,更新玩家位置
player.update()
# ---------- 绘制 ----------
# 清空屏幕
screen.fill((0, 0, 0))
# 把玩家飞机绘制到屏幕上
# screen.blit(source, dest) 将一个Surface绘制到另一个Surface上
# player.image是要绘制的图像,player.rect是绘制的位置
screen.blit(player.image, player.rect)
# 刷新显示
pygame.display.flip()
# 控制帧率
clock.tick(60)
pygame.quit()
sys.exit()
代码详解:
继承Sprite类:class Player(pygame.sprite.Sprite)让Player成为一个精灵
self.image:代表精灵的“图像”,是一个Surface对象
self.rect:代表精灵的位置和碰撞箱,是一个Rect对象
update()方法:每帧调用一次,用于更新精灵的位置或状态
screen.blit(player.image, player.rect):把精灵绘制到屏幕上