使用Pygame制作“青蛙过河”游戏

本篇博客将演示如何使用 Python + Pygame 从零开始编写一款 Frogger 风格的小游戏。Frogger 是一款早期街机经典,玩家需要帮助青蛙穿越车水马龙的马路到达对岸。本示例提供了一个精简原型,包含角色移动汽车生成与移动碰撞检测胜利条件等关键点。希望能为你的 2D 游戏创作带来更多灵感。


1. 前言

Frogger 最早于 1981 年由科乐美(Konami)与世嘉(Sega)联合发行,玩家需要操纵一只小青蛙,穿过公路和河流,躲避疾驰的汽车或其他障碍,到达对岸的安全区。本篇示例中,我们将专注于公路部分的场景,展示如何实现:

  1. 青蛙(Frog) 的移动控制:上下左右移动,每次移动一格或一段距离;
  2. 车辆(Car) 的随机生成与自动移动:从一侧出现并驶向另一侧;
  3. 碰撞检测:如果青蛙与车辆重叠,则游戏结束;
  4. 胜利条件:青蛙成功到达屏幕顶端(或多个安全格)即可通关;
  5. 关卡与难度:可在此示例基础上控制车辆速度、数量等,增强挑战性。

2. 环境准备

  1. Python 3.x

  2. Pygame 库:若尚未安装,可在命令行执行:

    bash 复制代码
    pip install pygame
  3. 桌面操作系统:Windows、macOS 或大部分 Linux 都能正常运行 Pygame。


3. 设计思路

  1. 地图/场景

    • 采用固定大小的屏幕,高度可分为若干"车道"或"安全区";
    • 最上方为"目标区域",中间若干车道,各车道上车辆从左到右或从右到左移动;
    • 最下方为青蛙的初始位置,玩家需向上移动到目标区域。
  2. 青蛙(Frog)

    • 记录其 (x, y) 位置或网格坐标。
    • 通过方向键(或 WASD)每次移动一个格子高度/宽度。
    • 若超出屏幕边界,则保持在可行范围内。
  3. 车辆(Car)

    • 不断从某侧随机生成车辆,具有一定速度和方向;
    • 随帧更新车的位置,若超出屏幕另一端则移除。
    • 可有多条车道,每条车道车辆朝同一方向行驶,速度可不相同。
  4. 碰撞检测

    • 每帧检查青蛙与所有车辆的矩形是否重叠。若重叠,游戏失败。
  5. 胜利判定

    • 如果青蛙到达屏幕顶部(或设置的终点区域),判定胜利。

4. 完整示例代码

将以下代码保存为 frogger.py 并运行。你可以根据需求对屏幕大小、车道数、车辆速度、青蛙移动距离等做个性化修改或扩展。

python 复制代码
import pygame
import sys
import random

# 初始化 Pygame
pygame.init()

# ---------------------
# 全局参数
# ---------------------
WIDTH, HEIGHT = 600, 600     # 游戏窗口大小
FPS = 30                     # 帧率

# 颜色定义
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 200, 0)
RED   = (255, 0, 0)
GRAY  = (100, 100, 100)
BLUE  = (0, 0, 255)

# 窗口与时钟
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("简易 Frogger - Pygame 示例")
clock = pygame.time.Clock()
font = pygame.font.SysFont("arial", 32)

# 其他配置
LANE_COUNT = 4               # 车道数量 (示例中只演示几条车道)
LANE_HEIGHT = 60             # 每条车道的高度
START_Y = HEIGHT - 50        # 青蛙起始垂直位置
FROG_SIZE = 40               # 青蛙的宽高
FROG_MOVE = 60               # 青蛙每次移动距离(与车道高度差不多)

# 车辆配置
CAR_HEIGHT = 40
CAR_WIDTH  = 60
CAR_INTERVAL = 90            # 两辆车的最小水平间隔
CAR_SPEED_RANGE = (4, 7)     # 车辆速度随机区间
SPAWN_INTERVAL = 60          # 多久(帧)生成一辆新车


# ---------------------
# 青蛙类
# ---------------------
class Frog:
    def __init__(self):
        self.x = WIDTH // 2 - FROG_SIZE // 2
        self.y = START_Y
        self.width = FROG_SIZE
        self.height = FROG_SIZE

    def move_up(self):
        self.y -= FROG_MOVE
        if self.y < 0:
            self.y = 0

    def move_down(self):
        self.y += FROG_MOVE
        if self.y + self.height > HEIGHT:
            self.y = HEIGHT - self.height

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

    def move_right(self):
        self.x += FROG_MOVE
        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 Car:
    def __init__(self, lane_index, direction):
        """
        lane_index: 第几条车道(从上往下数 or 约定)
        direction: 车辆行驶方向: 1 表示从左往右, -1 表示从右往左
        """
        self.lane_index = lane_index
        self.direction = direction
        self.width = CAR_WIDTH
        self.height = CAR_HEIGHT
        # 车辆初始 y 坐标
        self.y = (lane_index + 1) * LANE_HEIGHT
        # 根据方向设定 x
        if direction == 1:
            self.x = -self.width
        else:
            self.x = WIDTH
        self.speed = random.randint(*CAR_SPEED_RANGE)

    def update(self):
        self.x += self.speed * self.direction

    def is_off_screen(self):
        return (self.direction == 1 and self.x > WIDTH) or (self.direction == -1 and self.x + self.width < 0)

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

# ---------------------
# 主函数
# ---------------------
def main():
    frog = Frog()
    cars = []
    frame_count = 0
    running = True
    game_won = False

    while running:
        clock.tick(FPS)
        frame_count += 1

        # 1) 处理事件
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_UP:
                    frog.move_up()
                elif event.key == pygame.K_DOWN:
                    frog.move_down()
                elif event.key == pygame.K_LEFT:
                    frog.move_left()
                elif event.key == pygame.K_RIGHT:
                    frog.move_right()

        # 若青蛙到达顶部,则判定胜利
        if frog.y <= 0:
            game_won = True
            running = False

        # 2) 生成车辆
        # 每间隔 SPAWN_INTERVAL 帧,在随机车道生成一辆车
        if frame_count % SPAWN_INTERVAL == 0:
            lane = random.randint(0, LANE_COUNT - 1)
            direction = random.choice([1, -1])
            # 为了减少车辆撞到一起, 可以简单判断该车道上最后一辆车的位置
            # 这里示例不做太多控制, 只是随机生成
            car = Car(lane, direction)
            cars.append(car)

        # 3) 更新车辆位置
        for c in cars:
            c.update()

        # 移除离开屏幕的车辆
        cars = [c for c in cars if not c.is_off_screen()]

        # 4) 检测碰撞
        frog_rect = frog.get_rect()
        for c in cars:
            if frog_rect.colliderect(c.get_rect()):
                # 撞车 -> 游戏结束
                running = False
                break

        # 5) 绘制场景
        screen.fill(BLACK)

        # 绘制"终点区域" (顶部)
        pygame.draw.rect(screen, BLUE, (0, 0, WIDTH, LANE_HEIGHT))

        # 绘制车道(用灰色背景)
        for i in range(1, LANE_COUNT + 1):
            y = i * LANE_HEIGHT
            pygame.draw.rect(screen, GRAY, (0, y, WIDTH, LANE_HEIGHT))

        # 绘制青蛙
        pygame.draw.rect(screen, GREEN, frog_rect)

        # 绘制车辆 (红色方块)
        for c in cars:
            pygame.draw.rect(screen, RED, c.get_rect())

        # 提示文本
        text_surface = font.render("Reach the Blue Zone!", True, WHITE)
        screen.blit(text_surface, (10, 10))

        pygame.display.flip()

    # 游戏结束画面
    game_over(game_won)

def game_over(won):
    screen.fill(BLACK)
    if won:
        msg = "You Win! Frog Safely Crossed!"
    else:
        msg = "Game Over! The Frog got hit!"

    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. 青蛙移动

    • 每次按键向上下左右移动一个格子的距离(FROG_MOVE)。
    • 防止青蛙越过屏幕边缘时,需要进行边界限制。
  2. 车道与车辆

    • 通过 LANE_COUNT 指定有多少条车道,每条车道的高度相同。
    • 每隔 SPAWN_INTERVAL 帧随机在任意车道生成一辆车,其方向可以是 从左往右从右往左
    • 车辆在每帧自动更新位置,若移出屏幕则移除。
  3. 碰撞检测

    • 获取青蛙和车辆的 Rect 判断是否 colliderect。若重叠则游戏结束。
  4. 胜利判定

    • 当青蛙到达屏幕最上方(y <= 0),判定成功过马路,游戏结束并显示胜利界面。
  5. 可扩展之处

    • 增加更多车道、修改每条车道车辆速度;
    • 为每条车道设置不同的方向或汽车密度;
    • 调整关卡难度:车辆越来越多、移动速度增快;
    • 添加额外障碍或奖励机制。

5. 运行效果

相关推荐
(・Д・)ノ4 分钟前
python打卡day27
开发语言·python
小oo呆1 小时前
【学习心得】Jupyter 如何在conda的base环境中其他虚拟环境内核
python·jupyter·conda
小白学大数据2 小时前
Scrapy框架下地图爬虫的进度监控与优化策略
开发语言·爬虫·python·scrapy·数据分析
浊酒南街2 小时前
TensorFlow之微分求导
人工智能·python·tensorflow
立秋67892 小时前
用Python绘制梦幻星空
开发语言·python·pygame
alpszero2 小时前
YOLO11解决方案之对象裁剪探索
人工智能·python·计算机视觉·yolo11
白云千载尽3 小时前
相机、雷达标定工具,以及雷达自动标定的思路
python·自动驾驶·ros
咕噜咕噜啦啦3 小时前
python爬虫实战训练
爬虫·python
盛夏绽放3 小时前
Python字符串常用内置函数详解
服务器·开发语言·python
我想睡觉2613 小时前
Python训练营打卡DAY27
开发语言·python·机器学习