展开菜单
首页 精品内容 本月促销 装机必备 Windows macOS软件 IOS软件 Android AI PDF教程 专题
全部分类

当前位置:

首页 > 编程开发 > Python版本童年游戏冒险岛实现过程

Python版本童年游戏冒险岛实现过程

项目概述 今天要聊的这个项目,是一个挺有意思的玩意儿——Super Pirate Maker。它本质上是一个用 Python 和 Pygame 打造的横版闯关游戏,但它的特别之处在于,它把“玩”和“造”结合在了一起。玩家不仅能扮演海盗在关卡里冒险,还能摇身一变,用内置的编辑器亲手设计自己的冒险地图。

项目概述

今天要聊的这个项目,是一个挺有意思的玩意儿——Super Pirate Maker。它本质上是一个用 Python 和 Pygame 打造的横版闯关游戏,但它的特别之处在于,它把“玩”和“造”结合在了一起。玩家不仅能扮演海盗在关卡里冒险,还能摇身一变,用内置的编辑器亲手设计自己的冒险地图。这种“自给自足”的游戏体验,在技术实现上其实有不少门道。

项目架构

先来看看它的整体骨架。项目采用了非常清晰的模块化设计,每个文件各司其职,这种结构对于学习和维护来说都相当友好:

Python冒险岛游戏/
├── code/
│   ├── main.py        # 游戏主入口 & 状态切换
│   ├── level.py       # 关卡逻辑实现
│   ├── editor.py      # 关卡编辑器
│   ├── sprites.py     # 游戏角色与精灵
│   ├── settings.py    # 全局配置常量
│   ├── support.py     # 工具函数库
│   ├── menu.py        # 编辑器菜单系统
│   └── timer.py       # 计时器工具
├── audio/             # 游戏音效
├── graphics/          # 游戏资源图片
│   ├── player/        # 玩家角色动画帧
│   ├── enemies/       # 敌人精灵图
│   ├── terrain/        # 地形砖块
│   ├── items/         # 道具(金币、钻石等)
│   └── palm/          # 棕榈树装饰
└── font/              # 游戏字体

核心配置 (settings.py)

游戏的所有全局配置都集中在一个地方管理,这种做法能有效避免“魔法数字”满天飞。从窗口大小到动画速度,再到编辑器里能用的所有物件,都一目了然:

# 基础配置
TILE_SIZE = 64
WINDOW_WIDTH = 1280
WINDOW_HEIGHT = 720
ANIMATION_SPEED = 8

# 编辑器图块数据 - 定义了19种游戏对象
EDITOR_DATA = {
    0: {'style': 'player', 'type': 'object', ...},      # 玩家出生点
    2: {'style': 'terrain', 'type': 'tile', ...},      # 地形砖块
    3: {'style': 'water', 'type': 'tile', ...},        # 水面
    4-6: {'style': 'coin', ...},                        # 金币/银币/钻石
    7-10: {'style': 'enemy', ...},                      # 敌人(尖刺/牙齿/贝壳)
    11-18: {'style': 'palm', ...},                      # 棕榈树
}

# 层级系统 - 实现前后景深效果
LEVEL_LAYERS = {
    'clouds': 1,
    'ocean': 2,
    'bg': 3,
    'water': 4,
    'main': 5
}

双模式系统

这个游戏最核心的设计,莫过于编辑器模式闯关模式之间的无缝切换。这可不是简单的场景跳转,背后有一套完整的机制在支撑。

状态切换流程

主控类负责管理模式的切换状态。默认进入编辑模式,当玩家按下切换键(比如回车)时,会触发一个平滑的过渡:

class Main:
    def __init__(self):
        self.editor_active = True  # 默认进入编辑模式
        self.editor = Editor(self.land_tiles, self.switch)
        
    def toggle(self):
        """切换游戏模式"""
        self.editor_active = not self.editor_active
        if self.editor_active:
            self.editor.editor_music.play()
    
    def switch(self, grid=None):
        """创建新关卡并切换"""
        self.transition.active = True
        if grid:
            self.level = Level(grid, self.switch, asset_dict, self.level_sounds)

过渡动画效果

为了让切换不显得生硬,项目采用了一个圆形缩放的过渡动画。这个动画会逐渐扩大一个黑色圆形遮罩覆盖整个屏幕,然后在切换完成后再收索消失,视觉上非常流畅:

class Transition:
    def display(self, dt):
        if self.active:
            self.border_width += 1000 * dt * self.direction
            if self.border_width >= self.threshold:
                self.direction = -1
                self.toggle()  # 切换模式
            
            if self.border_width < 0:
                self.active = False
                self.direction = 1
            # 绘制圆形遮罩
            pygame.draw.circle(self.display_surface, 'black', 
                              self.center, self.radius, int(self.border_width))

关卡编辑器 (editor.py)

编辑器是整个项目的亮点,它提供了一个完整的所见即所得的创作环境。你可以像玩沙盒游戏一样,用鼠标点点拖拖,就搭建出一个可玩的关卡。

核心数据结构

编辑器的核心是一个字典,用来存储画布上每个网格位置放置了什么对象。同时,它还管理着视角的平移(拖拽地图):

class Editor:
    def __init__(self, land_tiles, switch):
        self.canvas_data = {}      # 画布数据
        self.origin = vector()     # 视角偏移
        self.pan_active = False    # 拖拽状态
        
    def get_current_cell(self, obj=None):
        """根据鼠标位置计算当前网格坐标"""
        distance_to_origin = vector(mouse_pos()) - self.origin
        col = int(distance_to_origin.x / TILE_SIZE)
        row = int(distance_to_origin.y / TILE_SIZE)
        return col, row

智能邻居检测

为了让地形看起来更自然,编辑器实现了一个“智能邻居检测”功能。当你放置一块地形砖时,它会自动检查周围八个方向是否有其他地形,然后选择正确的瓦片图片来拼接,让地形的边缘看起来是连贯的,而不是一块块孤立的方块。

def check_neighbors(self, cell_pos):
    """检测8个方向的邻居,自动匹配地形瓦片"""
    NEIGHBOR_DIRECTIONS = {
        'A': (0,-1), 'B': (1,-1), 'C': (1,0), 'D': (1,1),
        'E': (0,1),  'F': (-1,1), 'G': (-1,0), 'H': (-1,-1)
    }
    
    for cell in local_cluster:
        if cell in self.canvas_data:
            for name, side in NEIGHBOR_DIRECTIONS.items():
                neighbor_cell = (cell[0] + side[0], cell[1] + side[1])
                if neighbor_cell in self.canvas_data:
                    if self.canvas_data[neighbor_cell].has_terrain:
                        self.canvas_data[cell].terrain_neighbors.append(name)

资源导入系统

编辑器需要加载大量的图片资源。这里用了两个工具函数,一个将文件夹内所有图片导入为列表,另一个则导入为字典(以文件名为键),方便后续按名称调用:

def imports(self):
    # 瓦片资源
    self.land_tiles = import_folder_dict('../graphics/terrain/land')
    
    # 动画资源
    self.animations = {}
    for key, value in EDITOR_DATA.items():
        if value['graphics']:
            graphics = import_folder(value['graphics'])
            self.animations[key] = {
                'frame index': 0,
                'frames': graphics,
                'length': len(graphics)
            }

关卡逻辑 (level.py)

精灵分组管理

进入闯关模式后,游戏世界开始运转。为了高效地进行碰撞检测和渲染,所有游戏对象(精灵)被分到了不同的组里:

class Level:
    def __init__(self, grid, switch, asset_dict, audio):
        # 精灵分组
        self.all_sprites = CameraGroup(0, 2)           # 所有精灵
        self.coin_sprites = pygame.sprite.Group()       # 硬币组
        self.shell_sprites = pygame.sprite.Group()     # 贝壳敌人组
        self.damage_sprites = pygame.sprite.Group()    # 可造成伤害的敌人
        self.collision_sprites = pygame.sprite.Group() # 碰撞体积组

关卡构建

关卡是如何从编辑器保存的数据“变”出来的呢?答案就在这个构建函数里。它遍历编辑器生成的网格数据字典,根据每个位置上的数字代号,实例化对应的游戏对象:

def build_level(self, grid, asset_dict, jump_sound):
    for layer_name, layer in grid.items():
        for pos, data in layer.items():
            match data:
                case 0:  # 玩家
                    self.player = Player(pos, asset_dict['player'], ...)
                case 2:  # 地形
                    Generic(pos, asset_dict['land'][data], [...])
                case 4: Coin('gold', ...)      # 金币
                case 7: Spikes(...)            # 尖刺陷阱
                case 8: Tooth(...)             # 牙齿敌人
                case 9: Shell(orientation='left', ...)
                case 10: Shell(orientation='right', ...)

物理与碰撞

横版游戏的手感,很大程度上取决于物理和碰撞处理的细腻程度。这里的实现思路很经典:先水平移动并检测碰撞,再处理垂直移动和重力,最后分别解决两个方向上的碰撞:

def move(self, dt):
    # 水平移动
    self.pos.x += self.direction.x * self.speed * dt
    self.hitbox.centerx = round(self.pos.x)
    self.collision('horizontal')
    
    # 垂直移动 + 重力
    self.direction.y += self.gra vity * dt
    self.pos.y += self.direction.y * self.speed * dt

def collision(self, direction):
    for sprite in self.collision_sprites:
        if sprite.rect.colliderect(self.hitbox):
            if direction == 'horizontal':
                # 水平碰撞处理
                self.hitbox.right = sprite.rect.left if self.direction.x > 0 else self.hitbox.right
            else:
                # 垂直碰撞处理
                self.hitbox.bottom = sprite.rect.top if self.direction.y > 0 else self.hitbox.bottom

玩家角色 (sprites.py)

玩家状态机

玩家的动作和动画不是随便播放的,而是由一个简单的状态机控制。根据垂直速度判断是在跳跃、下落,还是根据水平速度判断是在奔跑或 idle(待机):

class Player(Generic):
    def get_status(self):
        """根据运动状态更新动画状态"""
        if self.direction.y < 0:
            self.status = 'jump'      # 上升
        elif self.direction.y > 1:
            self.status = 'fall'      # 下落
        else:
            self.status = 'run' if self.direction.x != 0 else 'idle'

输入控制

控制逻辑很直观,就是监听键盘按键,改变角色的移动方向和状态,并在跳跃时播放音效:

def input(self):
    keys = pygame.key.get_pressed()
    if keys[pygame.K_d]:
        self.direction.x = 1
        self.orientation = 'right'
    elif keys[pygame.K_a]:
        self.direction.x = -1
        self.orientation = 'left'
    
    if keys[pygame.K_w] and self.on_floor:  # 跳跃
        self.direction.y = -2
        self.jump_sound.play()

敌人系统

牙齿敌人 (Tooth)

这个敌人有自己的巡逻 AI。它会一直朝一个方向走,直到撞墙或者走到平台边缘,然后自动掉头:

class Tooth(Generic):
    def move(self, dt):
        right_gap = self.rect.bottomright + vector(1,1)
        right_block = self.rect.midright + vector(1,0)
        
        if self.direction.x > 0:  # 向右移动
            floor_sprites = [sprite for sprite in self.collision_sprites 
                           if sprite.rect.collidepoint(right_gap)]
            wall_sprites = [sprite for sprite in self.collision_sprites 
                          if sprite.rect.collidepoint(right_block)]
            if wall_sprites or not floor_sprites:
                self.direction.x *= -1
                self.orientation = 'left'

贝壳敌人 (Shell)

贝壳敌人更“高级”一些,它会周期性地打开贝壳,发射珍珠攻击玩家。攻击的时机被巧妙地绑定在动画的特定帧上:

class Shell(Generic):
    def animate(self, dt):
        if int(self.frame_index) == 2 and self.status == 'attack' and not self.has_shot:
            pearl_direction = vector(-1,0) if self.orientation == 'left' else vector(1,0)
            Pearl(self.rect.center + offset, pearl_direction, 
                  self.pearl_surf, [self.groups()[0], self.damage_sprites])
            self.has_shot = True

相机系统

为了让玩家始终处于画面中心,游戏实现了一个相机跟随系统。它计算玩家位置与屏幕中心的偏移量,然后在绘制所有精灵时应用这个偏移,营造出镜头跟随的效果。同时,它还按照预设的层级顺序绘制,确保前景、背景关系正确:

class CameraGroup(pygame.sprite.Group):
    def custom_draw(self, player):
        # 相机跟随玩家
        self.offset.x = player.rect.centerx - WINDOW_WIDTH / 2
        self.offset.y = player.rect.centery - WINDOW_HEIGHT / 2
        
        # 按层级绘制
        for sprite in self:
            for layer in LEVEL_LAYERS.values():
                if sprite.z == layer:
                    offset_rect = sprite.rect.copy()
                    offset_rect.center -= self.offset
                    self.display_surface.blit(sprite.image, offset_rect)

游戏资源管理

工具函数 (support.py)

资源加载是游戏启动的重要一环。下面这两个工具函数非常实用,一个负责加载文件夹内所有图片到列表,另一个则加载到字典(以文件名作为键),后者在需要按名称索引资源时特别方便:

def import_folder(path):
    """导入文件夹中的所有图片"""
    surface_list = []
    for folder_name, sub_folders, img_files in walk(path):
        for image_name in img_files:
            full_path = path + '/' + image_name
            image_surf = pygame.image.load(full_path).convert_alpha()
            surface_list.append(image_surf)
    return surface_list

def import_folder_dict(path):
    """导入为字典,键为文件名"""
    surface_dict = {}
    for folder_name, sub_folders, img_files in walk(path):
        for image_name in img_files:
            full_path = path + '/' + image_name
            surface_dict[image_name.split('.')[0]] = pygame.image.load(full_path).convert_alpha()
    return surface_dict

游戏操作指南

编辑器模式

操作功能
鼠标左键放置选中对象
鼠标右键切换菜单选项
鼠标中键切换前景/背景
滚轮缩放/拖拽地图
Enter进入闯关模式
ESC保存并退出

闯关模式

按键功能
A/D左右移动
W/空格跳跃
ESC返回编辑器

技术亮点

  1. 零外部依赖 - 仅使用 Pygame 标准库,环境配置极其简单。
  2. 模块化架构 - 代码低耦合、高内聚,易于理解和扩展。
  3. 自动地形拼接 - 编辑器能智能检测邻居,自动生成正确的地形瓦片,提升创作效率。
  4. 状态机设计 - 玩家和敌人的行为状态管理清晰,逻辑分明。
  5. 相机系统 - 实现了平滑的视角跟随,增强了游戏沉浸感。
  6. 编辑器一体化 - 提供了真正的所见即所得编辑体验,降低了关卡创作门槛。

运行方式

想自己跑起来看看?步骤非常简单:

# 1. 安装 Python 3.10+
# 2. 安装依赖
pip install pygame

# 3. 运行游戏
cd code
python main.py

项目部分效果截图

Python版本童年游戏冒险岛实现过程

Python版本童年游戏冒险岛实现过程

Python版本童年游戏冒险岛实现过程

总结

总的来说,Super Pirate Maker 这个项目完整地展示了一个小型游戏从架构设计到功能实现的全过程。它的代码结构清晰,功能模块划分明确,并且实现了一些在游戏开发中非常实用的技巧,比如状态机、智能瓦片拼接和相机系统。无论你是刚入门想了解游戏开发流程的新手,还是希望深入研究 Pygame 某个模块的开发者,这个项目都提供了一个相当不错的范本,值得花时间细细琢磨。

本文内容来源于互联网,如有侵权请联系删除。
作者最新文章
编程开发 Python
相关文章 更多
精品专题 更多
本月促销

正软商城本月促销专区,汇集办公、设计、安全、影音、系统工具及AI软件等正版软件优惠活动,提供限时折扣、特价授权和优惠购买信息,活动库存及价格以页面实时展示为准。

装机必备

正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

Windows

正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

macOS软件

正软商城macOS软件专区,精选适用于Mac电脑的办公、设计、影音、效率、开发和系统工具,提供软件功能介绍、macOS兼容版本、正版授权及购买下载服务。

IOS软件

正软商城iOS软件专区,精选适用于iPhone和iPad的办公、学习、影音、设计、效率及AI应用,提供功能介绍、适用设备、系统要求和正版获取方式等信息。

AI

正软商城AI软件专区,汇集AI写作、AI绘画、AI视频、AI办公、AI编程、AI翻译、智能客服和数据分析等人工智能工具,提供功能介绍、适用平台、收费方式及正版购买信息。

PDF教程

正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

Mac软件 更多
灵活计算器
灵活计算器

灵活计算器是一款笔记式算数应用,支持实时计算、动态关联和云端同步功能。记录、整理和输出之间的过渡会更自然,适合长期写作、做笔记或持续沉淀个人内容。

赤友清理大师
赤友清理大师

赤友清理大师是一款为 Mac 设计的智能清理优化工具,可精准扫描垃圾、大文件、重复文件等,释放磁盘空间。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

极度公式
极度公式

极度公式是一款跨平台专业LaTeX公式识别编辑软件,支持OCR公式识别和多平台编辑。和使用说明,避免使用,享受完整功能与稳定支持。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

图几
图几

图几是一款适用于 macOS 的截图、标注与美化工具,支持离线操作保障隐私。界面整理和高频系统操作被放到一起考虑,桌面或窗口内容一多时,管理起来会更省心。

密码键盘
密码键盘

密码键盘是一款兼具安全性与便捷性的高效密码管理器。日常使用里的持续防护和信息管理会更突出,适合把安全控制放进长期使用流程中的场景。

思源笔记
思源笔记

思源笔记是一款本地笔记软件,提供所见即所得的编辑方式,为长文写作带来顺滑的体验。记录、整理和输出之间的过渡会更自然,适合长期写作、做笔记或持续沉淀个人内容。

Office 365 简体中文
Office 365 简体中文

一款文字处理软件,一种订阅式的跨平台办公软件,基于云平台提供多种服务,通过将 Excel 和 Outlook 等应用与 OneDrive 和 Microsoft Teams 等强大的云服务相结合,Office 365 可让任何人使用任何设备随时随地创建和共享内容。

WALTR PRO
WALTR PRO

WALTR是一款电脑至iOS文件传输转换工具,操作简单,快速实现文件识别与传送。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

CodeExpander
CodeExpander

CodeExpander 是一款快捷短语输入增强工具,通过键入缩写自动展开为自定义文段,提升工作效率。任务管理和过程控制会更完整,持续下载、批量同步或需要稳定传输流程的场景会更适合它。

Mountain Duck
Mountain Duck

Mountain Duck 是一款能将多个网盘挂载到本地的工具,像本地磁盘一样使用网盘。清理链路的完整性会更好一些,做应用卸载、残留处理和空间整理时,通常能少走很多手动排查步骤。

Menuist
Menuist

Menuist 是一款面向 macOS 的 Finder 右键菜单增强工具,主要用来补充新建文件、快捷导航等常用操作,让日常文件管理和访问路径时更高效、更顺手。

Mole
Mole

Mole 是一款专为 Mac 设计的深度清理优化工具,涵盖缓存清理、应用管理及实时状态监控等功能。清理链路的完整性会更好一些,做应用卸载、残留处理和空间整理时,通常能少走很多手动排查步骤。

WINDOWS 更多
Windows 10
Windows 10

Windows 10 是一款微软推出的经典操作系统,拥有硬件兼容性与多任务处理能力。它更偏向把系统状态查看和常用调节动作放在一起,适合需要持续观察和微调设备状态的场景。

极度公式
极度公式

极度公式是一款跨平台专业LaTeX公式识别编辑软件,支持OCR公式识别和多平台编辑。和使用说明,避免使用,享受完整功能与稳定支持。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

密码键盘
密码键盘

密码键盘是一款兼具安全性与便捷性的高效密码管理器。日常使用里的持续防护和信息管理会更突出,适合把安全控制放进长期使用流程中的场景。

思源笔记
思源笔记

思源笔记是一款本地笔记软件,提供所见即所得的编辑方式,为长文写作带来顺滑的体验。记录、整理和输出之间的过渡会更自然,适合长期写作、做笔记或持续沉淀个人内容。

傲梅轻松备份
傲梅轻松备份

傲梅轻松备份是一款专业易用的数据备份软件,为重要数据提供安全保障。日常使用里的持续防护和信息管理会更突出,适合把安全控制放进长期使用流程中的场景。

Office 365 简体中文
Office 365 简体中文

一款文字处理软件,一种订阅式的跨平台办公软件,基于云平台提供多种服务,通过将 Excel 和 Outlook 等应用与 OneDrive 和 Microsoft Teams 等强大的云服务相结合,Office 365 可让任何人使用任何设备随时随地创建和共享内容。

Wise Folder Hider Pro
Wise Folder Hider Pro

Wise Folder Hider Pro 是一款专业级文件和文件夹隐藏加密软件,为私密数据添加多重保护。高频操作更强调就近处理,浏览、整理和跨目录移动文件时,来回切换和重复点击都会少很多。

WALTR PRO
WALTR PRO

WALTR是一款电脑至iOS文件传输转换工具,操作简单,快速实现文件识别与传送。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

CodeExpander
CodeExpander

CodeExpander 是一款快捷短语输入增强工具,通过键入缩写自动展开为自定义文段,提升工作效率。任务管理和过程控制会更完整,持续下载、批量同步或需要稳定传输流程的场景会更适合它。

PinStack
PinStack

PinStack是一款轻量级的Windows平台剪贴板管理工具,优化您的剪贴板使用体验。它更偏向把系统状态查看和常用调节动作放在一起,适合需要持续观察和微调设备状态的场景。

Mountain Duck
Mountain Duck

Mountain Duck 是一款能将多个网盘挂载到本地的工具,像本地磁盘一样使用网盘。清理链路的完整性会更好一些,做应用卸载、残留处理和空间整理时,通常能少走很多手动排查步骤。

Seer
Seer

Seer是一款在Win平台下的空格键功能增强效率工具,只需轻敲空格键,就能预览几乎任何格式的文件。它更适合把零散的小功能集中起来使用,处理高频琐碎任务时会更省事。