news 2026/2/26 16:25:41

2601C++,超级马丽奥介绍

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
2601C++,超级马丽奥介绍

前言

在我童年的回忆中,有两个游戏是我最想复刻的,其中一个就是超级马里奥.
上大学后学会了编程,做过俄罗斯方块,扫雷,贪吃蛇,飞机大战,坦克大战,打砖块经典游戏,但是一直没有从头到尾做完一个超级马里奥,因为超级马里奥比前这些游戏相比要稍微复杂一些,之前找过几个别人的实现,都有大几千行以上.

几年前我在youtube看到一个大佬的视频,他用了非常简洁的思路,借助现代C++的语法,只用2000行就做了一个超级马里奥(用clang-format将大括号换行后只有1800行).

这里

我迫不及待地学习了一遍,当时也记录了一些文档,前几天有人要我推荐项目,我马上想到它,然后我顺便把前的文档重新清理和补充了一下,构成此文,按介绍把该项目推荐给大家.

根据理解,该代码是作者一气呵成的,并未做故意优化,所以如果要优化,可更为精简.优化可当作作业去做,我也总结了一些优化思路放这里,我抛了8点优化建议,大家可参考.

该约2000行的C++项目不仅完整恢复了初代马里奥核心玩法,更是一个精心设计软件工程示例.无论你是否要学习游戏编程,学习该项目的源码都能带给你意外的收获.

对不想学习游戏编程的人:
1,理解软件设计的艺术:剖析一个经典游戏的实现,可见优秀代码如何像乐高一样模块化,可扩展,该设计思想同样适合网络开发,移动应用乃至系统软件.
2,提升代码阅读能力:读高质量的,注释幽默的代码是一个享受,它能帮你培养"代码审美",在未来审核同事代码或学习新框架事半功倍.
3,查看游戏开发的幕后:了解游戏背后的检测冲突,物理模拟,动画系统等机制,能让你以更深度的视角欣赏游戏,甚至变成"硬核玩家"时的谈资.

对未来想从事游戏你:
1,入门2D游戏开发的绝佳教材:该项目覆盖了游戏循环,管理资源,实例组件,检测冲突,动画系统核心概念,代码量适中,非常适合按第一个深入研究游戏项目.
2,学习现代C++实践:项目大量使用灵针,标准库算法,常数式等现代C++特性,并展示了面向对象设计在游戏中的实际应用.
3,取得可复用的架构模板:你可直接借鉴其架构(如MapManager,Animation,实例继承体系)到自己的2D平台游戏中,大幅降低起步难度.
4,理解性能与可维护性的平衡:分析代码中哪些地方为了性能而妥协,哪些地方为了可读性而抽象,你能积累宝贵的工程平衡经验.

下面我简单地从架构和实现两个层面解析此项目的优点.

一,架构优点

1.清晰的类层次

基类与继承类:Enemy抽象基类,定义了敌人共有的接口(update,draw,die).GoombaKoopa按具体继承类,实现各自的行为逻辑.
该设计符合开闭原则,方便扩展新的敌人类型.
多态运用:游戏主循环std::shared_ptr<Enemy>容器统一管理所有敌人,利用虚函数动态调用具体类的更新和绘画方法.

2.模块分工显式

1,地图管理:MapManager类负责地图数据的加载,检测冲突,粒子效果硬币动画,与游戏实例逻辑完全解耦.
2,动画系统:动画类封装了精灵动画的帧切换,速度控制和绘画,可复用马里奥,敌人等多个对象.
3,实例独立:Mario,Mushroom,Goomba,Koopa等各自管理自身状态,位置,速度和渲染,统一的接口与地图和交互系统通信.

3.现代C++``管理资源

灵针:Enemy继承std::enable_shared_from_this,使用std::shared_ptr管理敌人生命期,避免泄漏内存,并安全地传递指针.
常数集中:Global.hpp集中定义了所有游戏常数(如重力,速度,大小等),方便调整保持一致性.

4.数据驱动设计

地图草图:关卡设计图像文件(LevelSketch*.png)定义,不同颜色代表不同地图元素(砖块,问号块,管道等).该数据与代码分离的方式使得易于修改和扩展关卡设计.
颜色地图:读取草图像素颜色决定生成蘑菇还是硬币,实现灵活的关卡配置.

5.视图跟随与帧率独立

视图跟随:根据马里奥水平位置动态调整视点,保证马里奥总是在屏幕中央(除边界外).
时间管理:使用std::chrono计算增量时间,实现与帧率无关的游戏循环,确保在不同硬件游戏速度一致.

二,实现优点

1.精细的检测冲突系统

1,单元格冲突:map_collision方法基于网格检测冲突,返回一个二进制``向量表示每一行的冲突情况,同时支持返回冲突单元格的坐标.
2,多冲突类型:可指定需要检测的单元格类型(砖块,问号块,管道等),并分别处理不同冲突结果(如析构砖块,激活问号块).
3,动态冲突盒:马里奥的冲突盒根据其状态(大小,蹲下)动态调整,确保检测冲突准确.

2.平滑的物理运动

1,加速度模拟:马里奥的移动带加速度减速度,按键响应有惯性,释放按键逐渐减速,手感接近原版游戏.
2,跳转蓄力:jump_timer实现长按跳转键跳得更高的效果,增加操作深度.
3,重力与最大速度:垂直速度重力影响,并限制最大下落速度,避免穿透.

3.丰富的状态管理

马里奥状态:包括正常,蹲下,死亡,成长,无敌等多种状态,growth_timer,invincible_timer计时器控制状态持续时间,逻辑清晰.
敌人状态:Koopa有遍历,龟壳静止,龟壳滑动三个状态,状态转换自然,行为符合经典设置.

4.动画系统

1,通用动画类:动画类封装了帧动画核心逻辑,支持设置帧宽,纹理路径,动画速度,翻转等,可复用所有需要动画的对象.
2,动画速度与运动同步:马里奥遍历动画的速度与其水平速度成正比,动画更自然.

5.视觉反馈粒子效果

1,砖块粒子:顶碎砖块时生成四向飞溅的粒子,增加破坏的视觉表现.
2,硬币弹出:问号块中的硬币以跳转动画渲染,增强收集感.
3,精灵闪烁:无敌状态成长状态下的精灵闪烁,直观提示玩家当前状态.

6.代码可读性与注释

幽默注释:作者在关键逻辑处添加了大量幽默且详细的注释,不仅解释代码意图,还共享了开发中的趣事和漏洞修复经历,极大提升了代码的可读性和趣味性.
清晰函数命名:方法名如get_hit_box,add_brick_particles,map_collision直观表达了功能.

7.标准库的充分利用

算法容器:大量使用std::all_of,std::remove_if,std::min,std::max标准算法,使代码简洁高效.
向量操作:利用std::vector存储敌人,蘑菇,粒子等动态集合,并使用eraseremove惯用法清理死亡对象.

8.管理资源优化

1,按需加载纹理:每个对象构造器中加载自己的纹理,避免全局重复加载.
2,纹理切换:根据马里奥状态实时切换纹理,而不是预加载所有纹理,节省内存.

三,优化建议:让代码更精简高效

尽管当前代码已可流畅运行,但若以更高标准审视,仍有不少可优化的地方.以下列举若干优化点,涉及性能,可维护性,精简代码等方面,并附上具体的改进思路.

1.纹理重复加载->纹理缓存

问题:在Mario::draw,Goomba::die,Koopa::die等函数中,频繁调用texture.loadFromFile.每次绘画都可能触发磁盘I/O,严重浪费性能.
改进:使用一个全局纹理管(如TextureManager单例),在初化游戏预加载所有纹理,后续按串标识取得.如:

classTextureManager{std::unordered_map<std::string,sf::Texture>textures;public:sf::Texture&get(conststd::string&name){autoit=textures.find(name);if(it==textures.end()){sf::Texture tex;tex.loadFromFile("Resources/Images/"+name+".png");textures[name]=std::move(tex);it=textures.find(name);}returnit->second;}};

Mario等类中,只需存储纹理引用或指针,绘画时直接使用.

2.检测冲突优化性能

问题:MapManager::map_collision每次都会遍历整个地图单元格,即使只有一小部分在视图内.当地图较大时,成本随地图面积线性增长.
改进:引入空间分割(如网格空间索引).按若干块()划分地图,只检测与玩家冲突的盒相交的块.如:

std::vector<unsignedchar>MapManager::map_collision_fast(constsf::FloatRect&hitbox){intleft_chunk=hitbox.left/CHUNK_SIZE;intright_chunk=(hitbox.left+hitbox.width)/CHUNK_SIZE;//仅遍历相关块中的`单元格`}

3.清除代码重复

问题:Mario::update中多次出现类似的检测冲突代码块(水平冲突,垂直冲突,地面检测),每次都需要调用map_collision并检查std::all_of.

改进:取一个私有助手函数,统一处理检测冲突与响应.如:

boolMario::check_collision(constsf::FloatRect&hitbox,std::vector<Cell>types,sf::Vector2i&out_cell){autocollision=map_manager.map_collision(types,hitbox);//统一处理冲突结果}

4.管理资源集中化

问题:每个实例(Mario,Goomba,Koopa,Mushroom)都在自己的构造器加载纹理,导致可以多次加载相同纹理(如地下/地上版本).
改进:将所有纹理路径集中到配置文件中,由ResourceManager统一加载和管理.同时使用引用计数,确保同一纹理只加载一次.

5.使用精灵表(SpriteSheet)减少纹理切换

问题:每个动画帧使用单独的图片文件,导致渲染时需要频繁绑定不同纹理,降低GPU效率.
改进:在一张大图合并同一角色的所有动画帧(精灵表),在动画类中用纹理矩形(sf::IntRect)定位.这样只需绑定一次纹理即可绘画所有帧.

6.敌人状态机重构

问题:Koopa类使用多个布尔变量(state,flipped,no_collision_dying)表示状态,逻辑分散在更新的各个条件分支中,难以维护.
改进:用状态模式(StatePattern)或枚举+状态函数表.如:

enumclassKoopaState{Walking,Shell,Sliding,Dying};void(Koopa::*state_handlers[4])()={&Koopa::update_walking,...};

7.减少临时容器分配

问题:map_collision返回std::vector<unsignedchar>,每次调用都会在堆上分配内存.在游戏循环频繁调用可能导致内存片段额外成本.
改进:改用静态线本存储(线本)的容器,或输出``参数传递预分配的内存.如:

voidmap_collision(conststd::vector<Cell>&types,constsf::FloatRect&hitbox,std::vector<unsignedchar>&out){out.clear();//填充`出`}

8.使用对象池管理动态实例

问题:频繁创建和析构敌人,蘑菇,粒子等对象,导致动态分配内存成本.
改进:实现简单对象池(对象池),预分配一定数量的对象,需要时从池中取出,析构时放回池中.尤其适合粒子效果(brick_particles,question_block_coins).

四,总结

超级马里奥Bros项目不仅是个可运行的游戏,更是一个值得学习的C++游戏编程示例.你可在其基础上轻松添加新关卡,新敌人新功能,体现了良好的软件工程实践.

增加了CMakeLists.txt,可直接编译,无须单独安装``SFML,地址在此:
这里

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/23 15:29:21

5分钟快速上手:Portfolio Performance投资组合管理终极指南

5分钟快速上手&#xff1a;Portfolio Performance投资组合管理终极指南 【免费下载链接】portfolio Track and evaluate the performance of your investment portfolio across stocks, cryptocurrencies, and other assets. 项目地址: https://gitcode.com/gh_mirrors/por/p…

作者头像 李华
网站建设 2026/2/11 18:21:56

Fashion-MNIST实战指南:从数据加载到模型部署的完整流程

Fashion-MNIST实战指南&#xff1a;从数据加载到模型部署的完整流程 【免费下载链接】fashion-mnist fashion-mnist - 提供了一个替代MNIST的时尚产品图片数据集&#xff0c;用于机器学习算法的基准测试。 项目地址: https://gitcode.com/gh_mirrors/fa/fashion-mnist F…

作者头像 李华
网站建设 2026/2/26 10:50:10

BIP39助记词生成终极指南:安全实践与多链支持

BIP39助记词生成终极指南&#xff1a;安全实践与多链支持 【免费下载链接】bip39 A web tool for converting BIP39 mnemonic codes 项目地址: https://gitcode.com/gh_mirrors/bi/bip39 BIP39助记词生成技术是加密货币领域的重要基石&#xff0c;它将复杂的加密私钥转换…

作者头像 李华
网站建设 2026/2/26 13:03:39

ISNet红外小目标检测终极指南:如何实现精准目标识别

ISNet红外小目标检测终极指南&#xff1a;如何实现精准目标识别 【免费下载链接】ISNet CVPR2022 ISNet: Shape Matters for Infrared Small Target Detection 项目地址: https://gitcode.com/gh_mirrors/is/ISNet 在红外图像处理领域&#xff0c;小目标检测一直是一个具…

作者头像 李华
网站建设 2026/2/24 20:04:03

语音识别加速革命:3倍速实时翻译技术深度解析

语音识别加速革命&#xff1a;3倍速实时翻译技术深度解析 【免费下载链接】whisper-ctranslate2 Whisper command line client compatible with original OpenAI client based on CTranslate2. 项目地址: https://gitcode.com/gh_mirrors/wh/whisper-ctranslate2 在当今…

作者头像 李华
网站建设 2026/2/25 2:36:52

5分钟学会跨平台歌单迁移:免费工具完全指南

5分钟学会跨平台歌单迁移&#xff1a;免费工具完全指南 【免费下载链接】GoMusic 迁移网易云/QQ音乐歌单至 Apple/Youtube/Spotify Music 项目地址: https://gitcode.com/gh_mirrors/go/GoMusic 还在为不同音乐平台的歌单无法互通而烦恼吗&#xff1f;GoMusic这款专业的…

作者头像 李华