飞机大战是个什么样的小游戏呢?
-
首先我们需要有一个自己的飞机,它可以在画面上进行上下左右移动,我们通过方向键来控制它的移动,我们的飞机要发射子弹,用来击打敌机,我们用空格键来控制子弹的发射
-
然后需要设置敌机,随机出现在画面上,以一定的速度向下移动 敌机和我们自己的飞机相撞时游戏结束
-
游戏结束时统计得分,击落一只敌机得10分
至此,我们一个飞机大战的小游戏就设计完成了!那么,要如何实现呢?
上完整代码:
python
# air_shoot.py
# 飞机大战小游戏
import pygame
import random
import sys
# 初始化 Pygame
pygame.init()
# 屏幕大小
WIDTH, HEIGHT = 480, 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("plane war")
# 颜色
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
# 时钟(控制帧率)
clock = pygame.time.Clock()
# 字体
font = pygame.font.SysFont("simhei", 32) # 如果报错,改为 None 或 "Arial"
small_font = pygame.font.SysFont("simhei", 24)
# 玩家飞机
class Player(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.Surface((50, 40))
self.image.fill(GREEN)
self.rect = self.image.get_rect()
self.rect.centerx = WIDTH // 2
self.rect.bottom = HEIGHT - 10
self.speed = 5
def update(self):
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT] and self.rect.left > 0:
self.rect.x -= self.speed
if keys[pygame.K_RIGHT] and self.rect.right < WIDTH:
self.rect.x += self.speed
if keys[pygame.K_UP] and self.rect.top > 0:
self.rect.y -= self.speed
if keys[pygame.K_DOWN] and self.rect.bottom < HEIGHT:
self.rect.y += self.speed
def shoot(self):
bullet = Bullet(self.rect.centerx, self.rect.top)
all_sprites.add(bullet)
bullets.add(bullet)
# 敌机
class Enemy(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.Surface((40, 30))
self.image.fill(RED)
self.rect = self.image.get_rect()
self.rect.x = random.randint(0, WIDTH - self.rect.width)
self.rect.y = random.randint(-100, -40)
self.speed = random.randint(2, 5)
def update(self):
self.rect.y += self.speed
if self.rect.top > HEIGHT:
self.kill() # 移出屏幕后删除
# 子弹
class Bullet(pygame.sprite.Sprite):
def __init__(self, x, y):
super().__init__()
self.image = pygame.Surface((5, 10))
self.image.fill(WHITE)
self.rect = self.image.get_rect()
self.rect.centerx = x
self.rect.bottom = y
self.speed = -10
def update(self):
self.rect.y += self.speed
if self.rect.bottom < 0:
self.kill()
# 显示文字
def draw_text(surf, text, font, x, y, color=WHITE):
img = font.render(text, True, color)
rect = img.get_rect()
rect.midtop = (x, y)
surf.blit(img, rect)
# 游戏结束画面
def show_game_over(score):
screen.fill(BLACK)
draw_text(screen, "GAME OVER", font, WIDTH//2, HEIGHT//2 - 50, RED)
draw_text(screen, f"SCORE: {score}", small_font, WIDTH//2, HEIGHT//2)
draw_text(screen, "press R restart, Q quit", small_font, WIDTH//2, HEIGHT//2 + 50)
pygame.display.flip()
waiting = True
while waiting:
clock.tick(30)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_r:
waiting = False
if event.key == pygame.K_q:
pygame.quit()
sys.exit()
# 主游戏函数
def game():
global all_sprites, bullets, enemies
all_sprites = pygame.sprite.Group()
bullets = pygame.sprite.Group()
enemies = pygame.sprite.Group()
player = Player()
all_sprites.add(player)
score = 0
enemy_spawn_rate = 30 # 帧数(越小越密集)
running = True
while running:
clock.tick(60)
current_frame = pygame.time.get_ticks() // 1000 * 60 # 当前帧数(粗略)
# 事件处理
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
# 按键射击(长按连续发射)
keys = pygame.key.get_pressed()
if keys[pygame.K_SPACE]:
if len(bullets) < 5: # 限制子弹数量
player.shoot()
# 生成敌机
if random.randint(1, enemy_spawn_rate) == 1:
enemy = Enemy()
all_sprites.add(enemy)
enemies.add(enemy)
# 更新所有精灵
all_sprites.update()
# 子弹击中敌机
hits = pygame.sprite.groupcollide(enemies, bullets, True, True)
for hit in hits:
score += 10
# 玩家与敌机碰撞
if pygame.sprite.spritecollide(player, enemies, False):
running = False
# 绘制
screen.fill(BLACK)
all_sprites.draw(screen)
draw_text(screen, f"score: {score}", small_font, 60, 10)
pygame.display.flip()
# 游戏结束
show_game_over(score)
# 主循环(支持重玩)
while True:
game()
🛩️ 游戏整体结构
这个游戏使用了 Pygame 框架 和 面向对象编程(OOP) 的方式来组织代码。主要分为以下几个部分:
- 初始化设置
- 定义游戏对象类(玩家、敌机、子弹)
- 游戏主循环
- 碰撞检测与得分
- 游戏结束界面
- 支持重玩机制
✅ 第一部分:导入模块和初始化
python
import pygame
import random
import sys
pygame:核心游戏库。random:用于生成随机位置、速度等。sys:用于安全退出程序。
python
pygame.init()
初始化所有 Pygame 的模块(如声音、显示、字体等),这是使用 Pygame 的第一步。
python
WIDTH, HEIGHT = 480, 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("飞机大战")
- 设置窗口大小为 480×600 像素。
- 创建一个显示窗口,并设置标题为"飞机大战"。
python
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
定义颜色常量。Pygame 中颜色用 RGB 元组表示:
(255, 255, 255)是白色(0, 0, 0)是黑色(255, 0, 0)是红色(敌机)(0, 255, 0)是绿色(玩家)
python
clock = pygame.time.Clock()
创建一个时钟对象,用来控制游戏帧率(FPS),防止运行过快或过慢。
python
font = pygame.font.SysFont("simhei", 32)
small_font = pygame.font.SysFont("simhei", 24)
创建字体对象,用于在屏幕上绘制文字。
"simhei"是黑体,支持中文。- 如果系统没有这个字体,可以用
'Arial'或None替代。
✅ 第二部分:定义游戏角色类
🎮 1. 玩家飞机类 Player
python
class Player(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.Surface((50, 40))
self.image.fill(GREEN)
self.rect = self.image.get_rect()
self.rect.centerx = WIDTH // 2
self.rect.bottom = HEIGHT - 10
self.speed = 5
- 继承自
pygame.sprite.Sprite------ 这是 Pygame 中所有可移动对象的基础类。 image:角色的外观,这里是一个绿色矩形(50宽 × 40高)。rect:角色的位置和边界框。- 初始位置:水平居中,底部距离屏幕底边 10 像素。
speed:移动速度。
python
def update(self):
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT] and self.rect.left > 0:
self.rect.x -= self.speed
if keys[pygame.K_RIGHT] and self.rect.right < WIDTH:
self.rect.x += self.speed
if keys[pygame.K_UP] and self.rect.top > 0:
self.rect.y -= self.speed
if keys[pygame.K_DOWN] and self.rect.bottom < HEIGHT:
self.rect.y += self.speed
每一帧调用一次
update()方法:
- 获取当前按下的按键状态。
- 控制方向键移动。
- 加入边界判断,不让飞机飞出窗口。
python
def shoot(self):
bullet = Bullet(self.rect.centerx, self.rect.top)
all_sprites.add(bullet)
bullets.add(bullet)
发射子弹的方法:
- 在飞机顶部中心创建一颗子弹。
- 把它加入总精灵组
all_sprites和子弹组bullets,以便更新和绘制。
👾 2. 敌机类 Enemy
python
class Enemy(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.Surface((40, 30))
self.image.fill(RED)
self.rect = self.image.get_rect()
self.rect.x = random.randint(0, WIDTH - self.rect.width)
self.rect.y = random.randint(-100, -40)
self.speed = random.randint(2, 5)
- 红色矩形代表敌机。
- 出现在屏幕上方(y 为负值),从不同 x 位置随机出现。
- 下落速度随机(2~5像素/帧)。
python
def update(self):
self.rect.y += self.speed
if self.rect.top > HEIGHT:
self.kill() # 移出屏幕后删除
敌机持续下落,一旦完全移出屏幕底部就自动销毁(
kill()),避免内存泄漏。
🔫 3. 子弹类 Bullet
python
class Bullet(pygame.sprite.Sprite):
def __init__(self, x, y):
super().__init__()
self.image = pygame.Surface((5, 10))
self.image.fill(WHITE)
self.rect = self.image.get_rect()
self.rect.centerx = x
self.rect.bottom = y
self.speed = -10 # 负数表示向上飞
- 白色小矩形表示子弹。
- 从玩家飞机顶部发射。
- 向上飞行(
speed = -10)。
python
def update(self):
self.rect.y += self.speed
if self.rect.bottom < 0:
self.kill() # 子弹飞出屏幕顶端就销毁
✅ 第三部分:辅助函数
🖋️ 显示文字函数
python
def draw_text(surf, text, font, x, y, color=WHITE):
img = font.render(text, True, color)
rect = img.get_rect()
rect.midtop = (x, y)
surf.blit(img, rect)
封装了一个通用的文字绘制函数:
surf:要画在哪(通常是screen)text:要显示的文字font:字体对象(x, y):文字左上角坐标blit():把文字图像画到屏幕上
💀 游戏结束画面
python
def show_game_over(score):
screen.fill(BLACK)
draw_text(screen, "游戏结束", font, WIDTH//2, HEIGHT//2 - 50, RED)
draw_text(screen, f"得分: {score}", small_font, WIDTH//2, HEIGHT//2)
draw_text(screen, "按 R 重新开始,Q 退出", small_font, WIDTH//2, HEIGHT//2 + 50)
pygame.display.flip()
waiting = True
while waiting:
clock.tick(30)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_r:
waiting = False
if event.key == pygame.K_q:
pygame.quit()
sys.exit()
显示"游戏结束"界面并等待用户选择:
- 填黑背景,显示得分。
- 提示按 R 重玩,Q 退出。
- 使用一个循环等待输入,直到用户决定。
✅ 第四部分:主游戏函数 game()
python
def game():
global all_sprites, bullets, enemies
all_sprites = pygame.sprite.Group()
bullets = pygame.sprite.Group()
enemies = pygame.sprite.Group()
player = Player()
all_sprites.add(player)
score = 0
enemy_spawn_rate = 30 # 每30帧左右生成一架敌机
running = True
初始化游戏状态:
- 创建三个精灵组:
all_sprites:所有要绘制和更新的对象bullets:所有子弹enemies:所有敌机
- 添加玩家
- 得分从 0 开始
python
while running:
clock.tick(60) # 锁定60 FPS
# 事件处理
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
主循环每秒运行约 60 次(由
clock.tick(60)控制)。处理退出事件。
python
keys = pygame.key.get_pressed()
if keys[pygame.K_SPACE]:
if len(bullets) < 5: # 限制最多5发子弹
player.shoot()
检测是否按下空格键,如果是且子弹不多于5个,则发射。
python
# 生成敌机
if random.randint(1, enemy_spawn_rate) == 1:
enemy = Enemy()
all_sprites.add(enemy)
enemies.add(enemy)
随机生成敌机(大约每 30 帧生成一架)。
python
all_sprites.update()
更新所有精灵的位置(包括玩家、敌机、子弹)。
python
# 子弹击中敌机
hits = pygame.sprite.groupcollide(enemies, bullets, True, True)
for hit in hits:
score += 10
groupcollide()自动检测两组精灵之间的碰撞:
- 子弹打中敌机 → 双方都销毁(
True, True) - 每消灭一个敌机加 10 分
python
# 玩家与敌机碰撞
if pygame.sprite.spritecollide(player, enemies, False):
running = False
如果玩家碰到任何敌机(即使只是擦边),游戏结束。
python
# 绘制画面
screen.fill(BLACK)
all_sprites.draw(screen)
draw_text(screen, f"得分: {score}", small_font, 60, 10)
pygame.display.flip()
清屏 → 画所有精灵 → 显示得分 → 刷新屏幕
python
show_game_over(score) # 游戏结束后显示结束画面
✅ 第五部分:支持重复游戏
python
while True:
game()
主循环外再套一层
while True,这样每次游戏结束后都可以重新开始。
🧠 总结:游戏运行流程图
开始游戏
↓
初始化 Pygame 和变量
↓
进入 game() 函数
↓
创建玩家和精灵组
↓
主循环:
→ 处理事件(退出、按键)
→ 玩家移动/射击
→ 随机生成敌机
→ 更新所有精灵位置
→ 检测碰撞(子弹打敌机、玩家撞敌机)
→ 绘制画面和得分
↓
玩家被撞 → 结束主循环
↓
调用 show_game_over()
↓
等待用户按 R 或 Q
→ 按 R:回到 game() 重新开始
→ 按 Q:退出程序
🚀 后续扩展建议
你可以基于这个框架继续添加功能:
| 功能 | 实现思路 |
|---|---|
| 添加音效 | 使用 pygame.mixer.Sound() 播放射击、爆炸音效 |
| 使用图片代替方块 | pygame.image.load("player.png") |
| 添加爆炸动画 | 碰撞时播放一系列图片 |
| 生命值系统 | 玩家可承受多次撞击 |
| 道具掉落 | 敌机死亡时随机掉落加速、多子弹等道具 |