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

news2025/2/4 20:26:35

本篇博客将演示如何使用 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.coloradmin.cn/o/2291964.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深度解读 Docker Swarm

一、引言 随着业务规模的不断扩大和应用复杂度的增加,容器集群管理的需求应运而生。如何有效地管理和调度大量的容器,确保应用的高可用性、弹性伸缩和资源的合理分配,成为了亟待解决的问题。Docker Swarm 作为 Docker 官方推出的容器集群管理工具,正是在这样的背景下崭露头…

8、面向对象:类、封装、构造方法

一、类 1、定义 类&#xff1a;对现实世界中事物的抽象。Student 对象&#xff1a;现实世界中具体的个体。张三、李四 这些具体的学生 面向对象的特征&#xff1a;抽象、封装、继承、多态 OOP: Object Oriented Programming&#xff08;面向对象编程&#xff09; 类和对象…

STM32 旋转编码器

旋转编码器简介 旋转编码器&#xff1a;用来测量位置、速度或旋转方向的装置&#xff0c;当其旋转轴旋转时&#xff0c;其输出端可以输出与旋转速度和方向对应的方波信号&#xff0c;读取方波信号的频率和相位信息即可得知旋转轴的速度和方向 类型&#xff1a;机械触点式/霍尔传…

git基础使用--4---git分支和使用

文章目录 git基础使用--4---git分支和使用1. 按顺序看2. 什么是分支3. 分支的基本操作4. 分支的基本操作4.1 查看分支4.2 创建分支4.3 切换分支4.4 合并冲突 git基础使用–4—git分支和使用 1. 按顺序看 -git基础使用–1–版本控制的基本概念 -git基础使用–2–gti的基本概念…

【算法】回溯算法专题③ ——排列型回溯 python

目录 前置小试牛刀回归经典举一反三总结 前置 【算法】回溯算法专题① ——子集型回溯 python 【算法】回溯算法专题② ——组合型回溯 剪枝 python 小试牛刀 全排列 https://leetcode.cn/problems/permutations/description/ 给定一个不含重复数字的数组 nums &#xff0c;返…

Vue2.x简介

Vue2.x简介 Vue2.x的版本介绍Vue2.x的两大组件库 Vue2.x的版本介绍 Vue2.x是vue.js的第二个主要版本&#xff0c;最初版发布于2016 年&#xff0c;最终版发布于2023年12月24日&#xff08;版本号&#xff1a;2.7.16&#xff0c;版本名&#xff1a;Swan Song&#xff08;绝唱&a…

FFmpeg:多媒体处理的瑞士军刀

FFmpeg&#xff1a;多媒体处理的瑞士军刀 前言 FFmpeg 是一个功能强大且跨平台的开源多媒体框架&#xff0c;广泛应用于音视频处理领域。 它由多个库和工具组成&#xff0c;能够处理各种音视频格式&#xff0c;涵盖编码、解码、转码、流处理等多种操作。 无论是专业视频编辑…

【深度分析】DeepSeek大模型技术解析:从架构到应用的全面探索

深度与创新&#xff1a;AI领域的革新者 DeepSeek&#xff0c;这个由幻方量化创立的人工智能公司推出的一系列AI模型&#xff0c;不仅在技术架构上展现出了前所未有的突破&#xff0c;更在应用领域中开启了无限可能的大门。从其混合专家架构&#xff08;MoE&#xff09;到多头潜…

python学opencv|读取图像(五十五)使用cv2.medianBlur()函数实现图像像素中值滤波处理

【1】引言 在前述学习过程中&#xff0c;已经探索了取平均值的形式进行图像滤波处理。 均值滤波的具体的执行对象是一个nXn的像素核&#xff0c;对这个像素核内所有像素点的BGR值取平均值&#xff0c;然后把这个平均的BGR值直接赋给像素核中心位置的核心像素点&#xff0c;由…

OpenAI 再战机器人领域,重组机器人团队

OpenAI重组机器人团队&#xff1f;大家是不是和小编一样&#xff0c;听到这个消息后&#xff0c;脑子里瞬间浮现出科幻电影里机器人满街跑的场景&#xff1f;今天咱们就来看看背后的故事吧~ 作为人工智能领域的领头羊&#xff0c;OpenAI一直以来都在探索和扩展AI技术的深度和广…

Turing Complete-1位开关

要求如下&#xff1a; 我的思考&#xff1a; 把输入1当作控制信号&#xff0c;把输入2当作输出信号。 通过非门和开关使输入2形成双通道输出&#xff0c; 通道一为输出输入2取反。 通道二为输出输入2本身。 通过输入1来控制两个通道的开闭。

树莓派pico入坑笔记,睡眠

关于树莓派pico和circuitpython的更多玩法&#xff0c;请看树莓派pico专栏 关于在 CircuitPython 中使用警报和浅/深度睡眠的更多信息&#xff0c;请参阅此学习指南。 树莓派pico支持浅睡眠和深度睡眠&#xff0c;其中深度睡眠唤醒后将从boot.py开始运行 支持按时间唤醒和引…

数据库 - Sqlserver - SQLEXPRESS、由Windows认证改为SQL Server Express认证进行连接 (sa登录)

本文讲SqlServer Express版本在登录的时候&#xff0c; 如何由Windows认证&#xff0c;修改为Sql Server Express认证。 目录 1&#xff0c;SqlServer Express的Windows认证 2&#xff0c;修改为混合认证 3&#xff0c;启用sa 用户 4&#xff0c;用sa 用户登录 下面是详细…

中间件漏洞之CVE-2024-53677

目录 什么是struts&#xff1f;CVE-2024-53677简介影响版本复现环境搭建漏洞利用修复 什么是struts&#xff1f; 在早期的 Java Web 开发中&#xff0c;代码往往混乱不堪&#xff0c;难以维护和扩展。比如&#xff0c;一个简单的用户登录功能&#xff0c;可能在不同的 Java 类…

Python玄学

过年期间无聊的看了看DY直播&#xff0c;也是迷上玄学了。突然想着为啥要自己掐指算&#xff0c;我这&#x1f437;脑哪记得到那么多东西啊。然后&#xff0c;就捣鼓捣鼓了一些玩意儿。留个纪念。 注&#xff1a;就是一个玄学推动学习&#xff0c;部分内容不必当真&#xff0c;…

16.1.STM32F407ZGT6-CAN基础概念

参考&#xff1a; https://blog.csdn.net/sunlight_vip/article/details/128639144 前言&#xff1a; 学习总结CAN的知识点&#xff1a; 1.can是什么&#xff0c;历史由来和背景 2.can的物理层&#xff0c;链路层 3.初始化的流程和关键点 4.波特率怎么设置 5.can id怎么过滤 6…

【论文笔记】Fast3R:前向并行muti-view重建方法

众所周知&#xff0c;DUSt3R只适合做稀疏视角重建&#xff0c;与sapnn3r的目的类似&#xff0c;这篇文章以并行的方法&#xff0c;扩展了DUSt3R在多视图重建中的能力。 abstract 多视角三维重建仍然是计算机视觉领域的核心挑战&#xff0c;尤其是在需要跨不同视角实现精确且可…

使用VCS对Verilog/System Verilog进行单步调试的步骤

Verilog单步调试&#xff1a; System Verilog进行单步调试的步骤如下&#xff1a; 1. 编译设计 使用-debug_all或-debug_pp选项编译设计&#xff0c;生成调试信息。 我的4个文件&#xff1a; 1.led.v module led(input clk,input rst_n,output reg led );reg [7:0] cnt;alwa…

[ESP32:Vscode+PlatformIO]新建工程 常用配置与设置

2025-1-29 一、新建工程 选择一个要创建工程文件夹的地方&#xff0c;在空白处鼠标右键选择通过Code打开 打开Vscode&#xff0c;点击platformIO图标&#xff0c;选择PIO Home下的open&#xff0c;最后点击new project 按照下图进行设置 第一个是工程文件夹的名称 第二个是…

如何使用 DeepSeek API 结合 VSCode 提升开发效率

引言 在当今的软件开发领域&#xff0c;API 的使用已经成为不可或缺的一部分。DeepSeek 是一个强大的 API 平台&#xff0c;提供了丰富的功能和数据&#xff0c;可以帮助开发者快速构建和优化应用程序。而 Visual Studio Code&#xff08;VSCode&#xff09;作为一款轻量级但功…