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

使用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 库:若尚未安装,可在命令行执行:
    pip install pygame
    
  3. 桌面操作系统:Windows、macOS 或大部分 Linux 都能正常运行 Pygame。

3. 设计思路

  1. 地图/场景

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

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

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

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

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

4. 完整示例代码

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

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. 运行效果

image.png


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

相关文章:

  • 吴晓波 历代经济变革得失@简明“中国经济史” - 读书笔记
  • 基于遗传优化GRNN和Hog特征提取的交通标志识别算法matlab仿真
  • Java 泛型<? extends Object>
  • Redis代金卷(优惠卷)秒杀案例-单应用版
  • 32. C 语言 安全函数( _s 尾缀)
  • 联想拯救者R720笔记本外接显示屏方法,显示屏是2K屏27英寸
  • Upscayl-官方开源免费图像AI增强软件
  • DIFY源码解析
  • 事务03之MVCC机制
  • JAVA篇12 —— 泛型的使用
  • SAP SD学习笔记28 - 请求计划(开票计划)之2 - Milestone请求(里程碑开票)
  • maven如何不把依赖的jar打包到同一个jar?
  • EigenLayer联合Cartesi:打造面向主流用户的DeFi、AI等新用例
  • tomcat核心组件及原理概述
  • 【算法】回溯算法专题① ——子集型回溯 python
  • 【hot100】刷题记录(8)-矩阵置零
  • 芯片AI深度实战:AI大模型知识图谱
  • 新能源算力的崛起与困局:AI时代的能源革命走向何方?
  • curope python安装
  • 文件系统分析
  • 命令模式 - 命令模式的设计思想
  • html基本结构和常见元素
  • tkinter-TinUI-xml实战(11)文本阅读、编辑器
  • 使用PyTorch实现逻辑回归:从训练到模型保存与性能评估
  • Web服务器启动难题:Spring Boot框架下的异常处理解析
  • 第29章 航天系统工程与星骗计划