从同一代码库为GBA和PC制作游戏
摘要
一位开发者详细介绍了从单一代码库为GBA e-reader和PC构建游戏的过程和挑战,以缓解e-reader卡制造中的问题。
<p><a href="https://lobste.rs/s/xvkvhh/making_game_for_gba_pc_from_same_codebase">评论</a></p>
查看缓存全文
缓存时间: 2026/09/21 16:27
# 为GBA和PC开发同一代码库的游戏
来源:https://mattgreer.dev/blog/making-a-game-for-gba-and-pc/
我为何以及如何为两个截然不同的平台开发游戏
如今我已开启第三次电子阅读器开发之旅。但这次我变得更加老练,因此采取了不同的做法——我将为PC平台同步开发下一款GBA/电子阅读器游戏。以下是原因和部分实现方式。
## 受制造工艺拖累的电子阅读器发行
我在首批电子阅读器游戏(https://www.retrodotcards.com/series-one)上非常幸运,但当时并未意识到这点。我设法找到了能印制高质量卡片的印刷商,更重要的是,这些卡片在电子阅读器中扫描效果极佳。
GBA电子阅读器通过读取印在卡牌上的点阵条带获取数据,其原理类似二维码。这类点阵对印刷精度要求极高,若不符合苛刻的扫描标准就无法被正确识别。关于电子阅读器的详细介绍,请参阅我此前为该设备开发纸牌游戏的文章(https://mattgreer.dev/blog/cramming-solitaire-onto-a-nintendo-ereader-card/)。
由于这些卡片扫描效果良好,我以为已攻克最大难题,便迫不及待地开始制作下一款电子阅读器游戏《像素小狗》(https://retrodotcards.com/pixel-pup)。我们已完成电子阅读器版本的所有开发,甚至已完成卡片印刷,却最终取消了发行。合作的印刷商更换了设备(包括硬件和软件),导致新印刷的卡片无法正常扫描。这个故事的细节很复杂,但以上便是基本梗概。
扫描效果欠佳的《像素小狗》电子阅读器卡片 :( 印制电子阅读器卡片本就困难重重,要印制成可销售的产品更是难上加难。印刷公司通常不承接这类精密业务——为何要为小众客户投入大量额外精力?毕竟他们的主流客户印制名片、书籍、菜单等产品根本无需这般苛刻的工艺。此前我遇到的印刷商愿意配合测试并满足我的特殊需求已属幸运...但这也是有限度的。当他们更换印刷机后,自然不愿再为调试我的卡片投入过多资源。如今我已联系全国十余家印刷商,无人愿意承接这项特殊印刷需求。我完全理解他们的立场。
因此我们最终将《像素小狗》作为标准GBA游戏发行(https://retrodotcards.itch.io/pixel-pup),对于未来电子阅读器游戏的开发方向,我仍感迷茫。
但我始终对电子阅读器情有独钟,仍希望开发一款能充分发挥这款独特设备潜力的游戏——实现任天堂未曾探索的可能性。
## 多方下注的策略
尽管困难重重,我决定最终启动这款电子阅读器野心之作。同时我将继续探索卡片制造方案。希望在游戏收尾阶段能找到可行的量产方式。但现实可能是...坦白说,大概率难以实现。
这款名为《Eridin》的游戏是一款融合创新机制的幻想题材回合制策略游戏。以下展示早期概念图与截图,随着开发推进这些设计还将大幅调整...
《Eridin》早期截图/概念图(最后的截图仅供参考,实际电子阅读器的整合方式将有所不同。该图仅为初期头脑风暴时制作)
我决定将这款游戏同时开发为GBA/电子阅读器版本与PC版本。最坏情况下至少能发行PC版。关键在于找到平衡点,使游戏能兼顾电子阅读器与PC平台的特性。换言之,如果PC版本仅为照搬电子阅读器模式而强行植入"卡片扫描",这将显得华而不实且令人厌倦(这种担忧完全合理)。我认为已找到平衡两者的良策,后续会随着开发进程逐步揭秘。
当然也可选择数字发行电子阅读器卡片,我正在考量几种方案。其中最具创意的是利用即将推出的GB-Link设备(https://www.crowdsupply.com/gblink/gblink-usb-v2)。目前我尚未确定是否会采用该方案,但这个设想本身已足够有趣。
## 为两个差异巨大的平台编写同一款游戏
为实现跨平台开发,我采用C语言编写核心代码:GBA端使用DevKitPro和libtonc开发(与《像素小狗》开发方式相同),PC端则基于SDL2构建。
首先我从《像素小狗》的引擎中提取核心模块,构建了抽象API层。该设计受电子阅读器内置的游戏API启发。例如在精灵图处理上,我在`sprites.h`头文件中定义了如下接口:
```
#include "sprites.h"
static const struct SpriteDef mySpriteDef = { ... };
...
int spriteHandle = sprites_load(&mySpriteDef);
sprites_pos(spriteHandle, 10, 20);
```
随后分别为不同平台实现`sprites.gba.c`和`sprites.sdl.c`:
```
// sprites.gba.c
int sprites_load(const struct SpriteDef *def) {
struct LogicalSprite *ls = getfreeLogicalSprite();
loadTilesIntoVram(def, ls);
loadPalette(def, ls);
setupOAMEntries(def, ls);
return ls->handle;
}
// sprites.sdl.c
int sprites_load(const struct SpriteDef *def) {
struct SDLSprite *sp = sprites[spriteCount++];
sp->texture = IMG_LoadTexture(renderer, def->file);
return sp->handle;
}
```
(以上为简化示例代码,实际实现更复杂)
每个平台的Makefile会分别引入通用文件和平台特定文件。我尽可能减少平台差异代码的编写。当完成精灵图、背景、字体、音频等基础模块后,发现引擎绝大部分代码都与平台无关。目前游戏本身仅有少量平台专属文件,且数量极少。当然开发尚处早期,这种情况可能会改变 :)
## 保持GBA视觉风格
PC版本仍将采用GBA原生分辨率240x160,但会通过放大技术避免在现代显示屏上显得过小。PC版整体将保持GBA游戏质感,类似近期发布的《Pipistrello and the Cursed Yoyo》(https://store.steampowered.com/app/2870350/Pipistrello_and_the_Cursed_Yoyo/),后者也是具有GBA美学的现代游戏。
不过PC版将增加更多人性化设计、视觉特效,整体体验更佳。这让我联想到受经典《毁灭战士》《异教徒》启发的现代第一人称射击游戏,例如《REKKR》(https://store.steampowered.com/app/1715690/REKKR_Sunken_Land/)。《REKKR》比经典《毁灭战士》更现代化,它用现代技术重塑我们记忆中的经典体验,而非完全复刻30年前的模样。
举个简单例子:PC版通过亚像素技术平滑滚动画面。
GBA版的地图滚动显得生硬,而PC版则丝滑流畅。
这是因为PC版以更高分辨率渲染(本视频中为1200x800,缩放比例可调),利用"亚像素"技术精确定位元素。同时PC版不受GBA版60帧/秒的帧率限制,可充分发挥硬件性能实现更高帧率,带来更流畅的动画与更舒适的操作手感。这个帧率差异是平台特性区别最大的方面,我已成功将其隐藏在日常开发流程中,未来可能会专门撰写技术分析。
## 结语
感谢您耐心阅读至此!我将继续全力推进《Eridin》的开发。若想关注项目进展,欢迎访问我的Bluesky主页(https://bsky.app/profile/retrodotcards.com)。
相似文章
在iPhone上编程GBA游戏
一位作者记录了如何完全在iPhone上编程Game Boy Advance游戏,使用了iSH、Textastic、Delta和gba bootstrap等工具,最终制作了一款名为TO THE TOWER的短小游戏。
为什么我在2024年用Zig编写了一个Game Boy Advance游戏
一位开发者解释了为什么他们选择Zig编程语言来创建Game Boy Advance游戏,强调了Zig的交叉编译能力及其对嵌入式编程的适用性。
从零开始的反编译项目:Claude Code与2001年GBA游戏的51%
文章详细介绍了使用Claude Code启动一个2001年GBA游戏的反编译项目,实现了51%的反编译并发现了一个隐藏的彩蛋。
将我1993年的Amiga游戏移植到Godot,使用LLM解读68000汇编代码
一位工程师描述了他将1993年的Amiga游戏'Babylonian Twins'移植到Godot的过程,使用Claude Fable 5 LLM来辅助读取和翻译68000汇编代码,结合个人历史与AI驱动开发。
为 Windows XP 构建 Principia
一篇详细的技术博客文章,讲述了通过创建自定义交叉编译工具链,为 Windows XP 构建开源游戏 Principia 的过程。