当前位置: 首页 > article >正文

使用Pygame制作“太空侵略者”游戏

1. 前言

在 2D 游戏开发中,“太空侵略者”是一款入门难度适中、却能覆盖多种常见游戏机制的项目:

  • 玩家控制飞船(Player)左右移动,发射子弹。
  • 敌人(Enemy)排列成一行或多行,从屏幕顶端缓慢移动或左右移动逼近玩家。
  • 当敌人被击中时,会被销毁并加分。若敌人到达玩家所在行或玩家被碰撞,则游戏结束。

在本篇中,我们将使用 Python + Pygame 实现一个简化版本的 Space Invaders,涵盖:玩家移动、子弹发射、敌人生成与移动、碰撞检测、计分与游戏结束逻辑等。


2. 开发环境

  1. Python 3.x
  2. Pygame
    如果尚未安装,可在命令行执行:
    pip install pygame
    
  3. 桌面系统:Windows、macOS 或大多数 Linux 系统都可正常运行。

确认 import pygame 无报错即可开始。


3. 游戏思路与关键点

  1. 玩家(Player)

    • 以飞船形象出现在屏幕下方,可左右移动(受屏幕边界限制)。
    • 按空格键或其他按键发射子弹。子弹往上移动,离开屏幕后可回收。
  2. 敌人(Enemy)

    • 可一次性生成若干敌人(如 3 行 × 6 列),排列在屏幕上方。
    • 敌人整体移动:
      • 可以先左右移动,到达边界后整体往下一行移动;
      • 或者在一定频率向玩家方向缓慢下降。
    • 当敌人到达玩家所在行(或接近底部),游戏结束。
  3. 子弹(Bullet)

    • 玩家发射的子弹以固定速度向上移动;
    • 敌人若与子弹发生碰撞,则敌人被销毁,玩家得分,子弹也随之消失。
  4. 碰撞检测

    • Rect 或基于距离的判断:当子弹矩形与敌人矩形重叠时,判定击中。
    • 当敌人矩形与玩家矩形重叠,或敌人到达屏幕下方,则游戏结束。
  5. 游戏循环

    • 每帧:处理输入事件(玩家移动、发射)、更新玩家位置、子弹与敌人位置,检测碰撞、绘制画面。
    • 当所有敌人消灭或玩家阵亡,即可结束游戏并显示结果。

4. 完整示例代码

以下示例保存为 space_invaders.py 并运行即可。请根据自己的需求调节画面尺寸、敌人数量、速度等参数。

import pygame
import sys
import random

# 初始化 Pygame
pygame.init()

# ---------------------
# 全局配置
# ---------------------
WIDTH, HEIGHT = 600, 600
FPS = 60

# 颜色
BLACK  = (0, 0, 0)
WHITE  = (255, 255, 255)
GREEN  = (0, 255, 0)
RED    = (255, 0, 0)
YELLOW = (255, 255, 0)

# 创建窗口
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Space Invaders - Pygame 示例")
clock = pygame.time.Clock()

# 字体
font = pygame.font.SysFont("arial", 24)

# ---------------------
# 玩家类
# ---------------------
class Player:
    def __init__(self):
        self.width = 40
        self.height = 40
        self.x = (WIDTH - self.width) // 2
        self.y = HEIGHT - 60
        self.speed = 5
        self.color = GREEN

    def draw(self, surface):
        pygame.draw.rect(surface, self.color, (self.x, self.y, self.width, self.height))

    def move_left(self):
        self.x -= self.speed
        if self.x < 0:
            self.x = 0

    def move_right(self):
        self.x += self.speed
        if self.x + self.width > WIDTH:
            self.x = WIDTH - self.width

    def get_rect(self):
        return pygame.Rect(self.x, self.y, self.width, self.height)

# ---------------------
# 敌人类
# ---------------------
class Enemy:
    def __init__(self, x, y):
        self.width = 30
        self.height = 30
        self.x = x
        self.y = y
        self.speed_x = 2   # 水平移动速度
        self.speed_y = 20  # 到达边界后往下移动的距离
        self.color = RED

    def draw(self, surface):
        pygame.draw.rect(surface, self.color, (self.x, self.y, self.width, self.height))

    def update(self, enemies):
        """
        水平移动敌人群,若到达左右边界,则整体向下移动
        """
        self.x += self.speed_x
        # 检测边界
        if self.x < 0 or self.x + self.width > WIDTH:
            # 改变方向,并让所有敌人往下移动 speed_y
            for e in enemies:
                e.speed_x = -e.speed_x
                e.y += e.speed_y
            return

    def get_rect(self):
        return pygame.Rect(self.x, self.y, self.width, self.height)

# ---------------------
# 子弹类
# ---------------------
class Bullet:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.radius = 5
        self.speed = 7
        self.color = YELLOW

    def update(self):
        self.y -= self.speed  # 向上移动

    def draw(self, surface):
        pygame.draw.circle(surface, self.color, (int(self.x), int(self.y)), self.radius)

    def get_rect(self):
        return pygame.Rect(self.x - self.radius, self.y - self.radius,
                           self.radius * 2, self.radius * 2)

# ---------------------
# 工具函数
# ---------------------
def create_enemies(rows=3, cols=6):
    """
    生成敌人列表,分布在屏幕上方
    """
    enemies = []
    gap_x = 60
    gap_y = 50
    start_x = 50
    start_y = 50
    for row in range(rows):
        for col in range(cols):
            x = start_x + col * gap_x
            y = start_y + row * gap_y
            enemy = Enemy(x, y)
            enemies.append(enemy)
    return enemies

def main():
    player = Player()
    enemies = create_enemies(rows=3, cols=6)
    bullets = []

    score = 0
    running = True
    while running:
        clock.tick(FPS)

        # 1) 处理事件
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE:
                    # 发射子弹
                    bullet_x = player.x + player.width // 2
                    bullet_y = player.y
                    bullets.append(Bullet(bullet_x, bullet_y))

        # 键盘输入
        keys = pygame.key.get_pressed()
        if keys[pygame.K_LEFT]:
            player.move_left()
        if keys[pygame.K_RIGHT]:
            player.move_right()

        # 2) 更新子弹位置并检测越界
        for b in bullets[:]:
            b.update()
            if b.y + b.radius < 0:
                bullets.remove(b)

        # 3) 更新敌人群位置
        for e in enemies:
            e.update(enemies)

        # 4) 碰撞检测:子弹与敌人
        for b in bullets[:]:
            b_rect = b.get_rect()
            for e in enemies[:]:
                e_rect = e.get_rect()
                if b_rect.colliderect(e_rect):
                    # 撞击 -> 敌人消失、子弹消失、得分
                    enemies.remove(e)
                    bullets.remove(b)
                    score += 10
                    break  # 该子弹已被移除,无需再检测其它敌人

        # 5) 检测敌人是否到达玩家或超越底部 -> 游戏结束
        for e in enemies:
            # 若敌人越过玩家所在 y,或者直接与玩家重叠
            if e.y + e.height > player.y:
                running = False

        # 6) 如果敌人全部消灭 -> 获胜 or 提示
        if not enemies:
            # 可以自定义下一波敌人或结束游戏
            running = False

        # 7) 绘制
        screen.fill(BLACK)
        # 绘制玩家、敌人、子弹
        player.draw(screen)
        for e in enemies:
            e.draw(screen)
        for b in bullets:
            b.draw(screen)

        # 显示得分
        score_surface = font.render(f"Score: {score}", True, WHITE)
        screen.blit(score_surface, (10, 10))

        pygame.display.flip()

    game_over(score)

def game_over(score):
    # 游戏结束界面
    screen.fill(BLACK)
    msg = f"Game Over! Your Score: {score}"
    label = font.render(msg, True, WHITE)
    rect = label.get_rect(center=(WIDTH // 2, HEIGHT // 2))
    screen.blit(label, rect)
    pygame.display.flip()
    pygame.time.wait(3000)
    pygame.quit()
    sys.exit()

if __name__ == "__main__":
    main()

主要逻辑解析

  1. Player(玩家)

    • 只有左右移动逻辑,且在碰撞边界时保持在范围内。
    • 按空格键发射子弹(Bullet 对象),存入列表。
  2. Enemy(敌人)

    • 通过 create_enemies() 一次性生成多个敌人,按行列布局排列在上方。
    • 每帧都执行 update(),在水平方向移动;若检测到超出左右边界,就整体往下一行,并反转移动方向。
  3. Bullet(子弹)

    • 每帧向上移动,若飞出屏幕则被移除;
    • 碰撞到敌人后,敌人与子弹都被移除并加分。
  4. 碰撞检测

    • 使用 Rectcolliderect 方法判断子弹与敌人是否重叠。
    • 当任意敌人到达玩家所在行或越过玩家,则游戏结束。
  5. 游戏结束

    • 当敌人列表为空时,玩家成功消灭全部敌人,也退出游戏循环;
    • 或者当敌人到达玩家区域,表示玩家失败。
    • 最后进入 game_over() 界面做简单提示后退出。

5. 运行效果

image.png
在这里插入图片描述


6. 总结

通过本篇文章,你已经学会了如何使用 Pygame 编写一个简易版的 Space Invaders 游戏:从玩家移动与射击,到敌人群体移动与下落,再到碰撞检测与游戏结束逻辑,都得到了体现。


http://www.kler.cn/a/527933.html

相关文章:

  • 【学习笔记】深度学习网络-正则化方法
  • Mysql的主从复制及扩展功能
  • Autogen_core源码:_agent_instantiation.py
  • 【搞定offer】远程医疗:健康科技领域,搞定医疗offer
  • FreeRTOS从入门到精通 第十五章(事件标志组)
  • 网站结构优化:加速搜索引擎收录的关键
  • (即插即用模块-特征处理部分) 十九、(NeurIPS 2023) Prompt Block 提示生成 / 交互模块
  • leetcode 844 比较含退格的字符串
  • 利用 AMD Instinct™ MI300X 提升计算流体动力学性能
  • cf1000(div.2)
  • 微服务实战 原生态实现服务的发现与调用_如何发现应用的服务调用问题
  • 从 UTC 日期时间字符串获取 Unix 时间戳:C 和 C++ 中的挑战与解决方案
  • P1158
  • 19 压测和常用的接口优化方案
  • Python从0到100(八十六):神经网络-ShuffleNet通道混合轻量级网络的深入介绍
  • 【4Day创客实践入门教程】Day3 实战演练——桌面迷你番茄钟
  • 1/31每日
  • 事务02之锁机制
  • Linux中部署Yolov5详解
  • 嵌入式知识点总结 Linux驱动 (八)-Linux设备驱动
  • H. Mad City
  • 深度学习编译器的演进:从计算图到跨硬件部署的自动化之路
  • 《大数据时代“快刀”:Flink实时数据处理框架优势全解析》
  • 翻译: Dario Amodei 关于DeepSeek与出口管制一
  • (二)QT——按钮小程序
  • 本地运行大模型效果及配置展示