在Linux终端里敲了一天的命令,趁着构建任务的空档,我把终端窗口拉大,敲下moon-buggy两个词,屏幕上立刻出现一辆用ASCII字符拼出来的月球车,在滚动的坑洼地形里蹦跳腾挪。这画面可比网页小恐龙硬核得多——它是最早那批纯终端跑酷游戏之一,名字叫moon-buggy,中文圈子里习惯叫它“月球车跑酷”。最近我在一台KeyarchOS服务器上把这玩意儿从源码重新编译了一遍,装的正是moon-buggy-1.0.51-13这个版本,过程意外地顺利,从下载到开玩只花了五分钟左右。这篇就把完整流程、容易踩的几个坑和基本玩法都整理出来,给同样在无图形界面环境里折腾的朋友一份参考。
1. 先说清楚:moon-buggy到底是个什么“跑酷”
1.1 一个比浏览器小恐龙年长很多的前辈
很多人第一次接触“字符跑酷”是在Chrome断网时那只小恐龙,但其实早在网页还没普及的年代,moon-buggy就已经在单位终端、机房字符界面里跑得很欢了。它是上世纪90年代诞生的经典终端游戏,用curses字符界面实现,整个画面完全由字母、符号和光标控制序列构成:一辆月球车从左向右行驶,前方随机生成深浅不一、坡度各异的陨石坑,玩家的任务就是控制车辆跳过去。
它和现代跑酷游戏的核心逻辑几乎一模一样:节奏感、时机判断、速度控制。区别在于,moon-buggy没有音效、没有贴图、没有光影,只有终端字符刷新和键盘监听。但恰恰是这种极简,让它成了一个能在任何有ncurses库的Linux系统上跑起来的小程序,连显卡驱动都不需要。
标题里的1.0.51-13这个版本号,拆开看是两层意思:源码版本主干是1.0.51,后面的-13通常是发行版打包时加的release号,表示这个源码版本被打了第13次补丁包。源码编译时你通常只会看到moon-buggy-1.0.51这一个目录名,后面那个数字不影响编译流程,但会影响你在软件源里看到的包名。
1.2 KeyarchOS这种服务器系统,和它真的合得来
KeyarchOS是定位服务器场景的操作系统,默认环境往往比较精简,很多时候你只能用SSH远程登录,桌面干脆就不存在。这种场景下,想找点不依赖图形界面的娱乐方式,moon-buggy是非常合适的选择:它需要的东西就两样——一个能跑Linux的终端、一个ncurses库。你不需要安装任何桌面组件,不需要声卡,更不需要GPU,甚至远程终端软件的窗口只有80列宽也照样能玩。
换个角度看,在KeyarchOS上装moon-buggy的过程本身也是一次小型环境自检:编译它需要gcc、make和ncurses头文件,这些恰恰是很多软件部署的基础。把这套工具链捋顺了,后面再编译别的开源软件就会顺手很多。所以这个项目看着是个游戏,实际上更像是拿一个小而完整的C程序,把一台服务器的编译环境、依赖管理和文件权限体系整体过了一遍。
1.3 装这个老古董,除了怀旧还剩什么实际价值
有人会问,都什么年代了还在终端里玩字符游戏?我这个人的看法是,它的价值不只是怀旧。
第一个价值是“可玩性”。moon-buggy的地形是随机生成的,难度会随行驶距离逐渐提升,每次开局都不一样。你会在不知不觉中琢磨跳跃的最佳时机,学会用刹车和油门控制车速,这些判断过程本身很上头。
第二个价值是“可学性”。moon-buggy的源码体量很小,一个中等水平的程序员花半天就能读完。它展示了如何在终端里做实时刷新、如何用curses库处理键盘输入、如何管理游戏状态。想入门字符界面编程的人,把它的源码当教材比看干巴巴的文档有意思得多。
第三个价值是“可移植性”。它对硬件几乎没有任何要求,一台老旧的小内存云主机、一台没有显卡的物理服务器,都能流畅跑起来。对于运维人员来说,在极其受限的环境里能跑起来的东西,往往才是最值得信赖的调试工具和消遣方式。
2. 动手前的准备:环境确认与依赖梳理
2.1 先花十秒确认KeyarchOS环境
我在开始之前做的第一件事,是确认这台机器到底是什么内核、什么架构。虽然是同一系列系统,但不同批次推送的内核版本、预装软件可能差得挺远。两步命令就能看清楚:
cat /etc/os-release uname -m第一条会显示系统的名称、版本ID和系统架构;第二条给出CPU架构,常见输出是x86_64。只要确认是Linux系统,并且能联网下载源码包,后面的流程基本就通用。如果你的KeyarchOS是ARM架构,比如云上的鲲鹏实例,编译过程本身没有区别,上课用的命令一模一样。
另外我建议顺手看一眼编译器是否已经存在:
gcc --version make --version如果这两条命令有输出,说明开发工具链已经在机器上了,可以跳过下一节里的工具链安装步骤,直接进入依赖检查阶段。很多服务器初始环境会预装基础编译器,但头文件未必齐全,所以还得接着看。
2.2 编译工具链和curses依赖,缺一不可
moon-buggy的源码是用C语言写的,整个安装过程其实就是一个标准的三步曲:configure检测环境、make编译、make install安装。这三个步骤分别依赖编译器gcc、构建工具make,以及一个特别关键的开发库——ncurses。
ncurses是终端字符界面的基础库,负责处理光标移动、字符加粗、颜色显示和键盘原始输入。moon-buggy运行时要调它,编译时也需要它的头文件curses.h。所以光有运行库还不够,开发包必须一起装上。在RPM系的系统里,包名叫ncurses-devel;在Debian系里,叫libncurses-dev。如果你的KeyarchOS自带的是yum或dnf,执行:
sudo dnf install -y gcc make ncurses-devel如果提示找不到dnf,就试试yum。极少数极简环境连包管理器都没有,那也可以直接用ncurses的源码自己编译,但那种情况很少,一般轮不到你遇到。装完之后可以用一个简单的办法验证头文件是否就位:
ls /usr/include/ncurses.h看到这个文件存在,就说明编译期的依赖基本齐了。
2.3 软件源直装和源码编译,两条路怎么选
安装moon-buggy有两条路:第一条是看看系统的软件源里有没有现成包,直接装;第二条是下载源码自己编译。
先说第一条。有些发行版的源里确实收录了moon-buggy,可以试试:
dnf search moon-buggy如果搜到了,sudo dnf install -y moon-buggy之后就能直接玩。但默认软件源收录的娱乐类游戏非常少,尤其服务器版本的系统更是精简到极致,大概率搜不到。就算搜到了,版本也可能不是自己想要的。
所以我这次选择的是源代码编译路线。原因很实在:版本可控、路径可控,还能借机会把编译环境完整地验证一遍。而且moon-buggy的源码包很小,configure加make加起来占用CPU的时间也就几十秒,完全不比从网上拉一个二进制包慢多少。这条路的唯一前提是把上一节说的依赖装好,之后就一路顺畅了。
3. 完整实操:从下载源码到跑起来
3.1 把源码包搞到机器上
源码编译的第一步是拿到源码包。moon-buggy的源码在上游发布页能下载到,文件名一般是moon-buggy-1.0.51.tar.gz。在服务器上下载的方式很简单,复制下载链接后直接用wget拉下来:
wget https://你的实际下载地址/moon-buggy-1.0.51.tar.gz如果服务器的外网访问受限,也可以在本地电脑上先下载好,再用scp传到服务器:
scp ./moon-buggy-1.0.51.tar.gz user@服务器地址:/tmp/传完之后在服务器上统一整理一下目录,我习惯把这类折腾用的源码放在用户目录下的src文件夹里:
mkdir -p ~/src && cd ~/src tar zxf /tmp/moon-buggy-1.0.51.tar.gz cd moon-buggy-1.0.51解压完成后,先看一眼目录里有什么:
ls -l你会看到一个configure可执行脚本、一堆.c和.h源码文件、一个Makefile.in模板,还有README和NEWS之类的文档。有这个configure脚本在,就说明这是一个标准的GNU autotools工程,编译流程很规整。
3.2 configure与make:编译其实没那么玄乎
进入源码目录后,第一步是执行环境检测:
./configure --prefix=/usr/local--prefix参数的意思是告诉安装脚本:可执行文件放到/usr/local/bin,库文件和帮助文档放到对应子目录。这样做的好处是尽量不碰系统自己的/usr/bin,以后想卸载也容易。如果你不指定,默认大概率也是/usr/local,但显式写出来更稳妥。
configure执行时会刷出一大堆checking for ...的信息,不用逐条看。它主要在做三件事:检测编译器是否存在、检测curses库及其头文件是否存在、检查本机架构和特性的兼容性。如果最后没有报错,并且你能看到config.status和Makefile这两个文件生成,就说明检测通过了。
接下来就可以编译:
makemoon-buggy的源码很小,编译过程通常半分钟以内就结束了。你会看到一条条gcc编译命令在屏幕上滚动,生产出一堆.o目标文件,最后链接成可执行文件。如果中途没有红色报错,就成功了大半。这里有一个值得记住的原则:make阶段如果出现错误,百分之八九十是缺开发头文件,先把依赖补齐再重新make,不要想太多。
3.3 安装后的两个扫尾动作
编译完成后,用root权限安装:
sudo make install这条命令会把moon-buggy可执行文件放进/usr/local/bin,同时把帮助手册复制到/usr/local/share/man目录。装完之后先确认一下文件确实在:
which moon-buggy如果输出/usr/local/bin/moon-buggy,说明安装路径正确,直接敲moon-buggy就能启动。
但这里有个很容易被忽略的细节:moon-buggy会把历史最高分写到一个系统级的分数文件里。如果安装完之后直接用普通用户跑,某些版本会因为分数文件不存在或目录不可写,在退出游戏时报一个“无法保存成绩”的提示。游戏能玩,但体验会脏一点。我的做法是提前把分数文件建好,并把权限放给games组:
sudo mkdir -p /var/games sudo touch /var/games/moon-buggy.scores sudo chgrp games /var/games/moon-buggy.scores sudo chmod 664 /var/games/moon-buggy.scores不同发行版对分数文件的默认路径不一样,有的在/var/lib/games/下面。你也可以先跑一次游戏,退出时看报错信息里写的是哪个路径,再对它做同样处理。这一步不属于“必须做”,但做了之后,老玩家的最佳纪录才能稳稳当当地保存下来。
3.4 第一次启动:你该怎么操作这辆月球车
一切就绪后,敲下moon-buggy,终端会立刻进入游戏界面。你会看到一辆字符拼成的月球车在屏幕上行驶,前方是一片逐渐逼近的月面地形,坑的宽度和坡度每次都在变。游戏的核心操作就几个键,记住之后基本不用看说明:
- 空格键:让月球车跳跃
- f键:加速,提升车速
- b键:刹车,降低车速
- q键:退出游戏
跳跃的时机是这个游戏的全部精髓。按下空格后,月球车并不是原地起跳,而是会先保持一段滑行,再开始腾空。车速越快,跳跃的弧线越长,落地时对姿态的要求也越高。我的体会是,过窄坑时小跳一下最稳,过宽坑则必须靠足够的速度把整个坑跨过去,速度不够就会一头栽进坑底。
加速是一把双刃剑。按住f能把车速提上去,让跳跃距离变大,但车速太快时遇到连续坑会很被动,可能第一坑刚落地第二个坑就在脸上了。刹车也不是万能的,速度太低时跳跃距离大幅缩短,面对宽坑只能干瞪眼。所以这个游戏的乐趣恰恰在于:每个坑都要求你在“冲”和“稳”之间找一个实时平衡点。
游戏里如果车头撞到坑沿、或者车辆落地时姿态太差,都会直接结束本局,屏幕上会显示本次得分和历史最高分。如果你想挑战更好的成绩,重新开局再来就是一秒钟的事。
3.5 进阶玩法:难度、颜色和其它启动参数
moon-buggy并不是只能默默跑,它其实自带一些启动参数,可以通过moon-buggy --help查看。不同打包版本的参数略有差异,但常见的选项基本围绕几个方向:颜色显示开关、初始难度、地形变化速度等。比如某些版本支持--color让地形的字符带上颜色,眼睛会舒服一些;有些版本支持调整初始速度,让新手不至于一上来就手忙脚乱。
我不建议一上来就把难度调得太夸张。这个游戏的体量本来就不大,它的挑战性是随着你行进的里程慢慢增加的:开头几个坑比较温和,到了后来坑会越来越密集、形状越来越刁钻。先原汁原味地玩几盘,搞清楚跳跃的节奏,再用参数开特色玩法,体验会好很多。
另外提一句,游戏对终端窗口大小比较敏感。如果窗口太窄,画面刷新会变形,甚至会看到字符被截断。我实测下来,终端宽度至少要有80列,高度能有24行以上,体验才能完整。SSH登录时,多数终端软件默认就是这个尺寸,但如果窗口开太小,记得先把窗口拉大再进入游戏。
4. 踩坑记录:安装和运行时那些妖问题
4.1 configure死在curses检测上怎么办
按照正常流程走,最容易卡住的地方就是configure阶段的依赖检测。常见场景是这样的:你兴冲冲地执行./configure,结果屏幕最后几行出现类似“cannot find -lcurses”或者“configure: error: ... curses ... not found”的提示,直接退出。
出现这个问题的原因很简单:机器上没装ncurses的开发包,或只装了运行时库,头文件不在编译器的检索路径里。解决办法就是回第2章把ncurses-devel装上。装完之后不要急着重跑configure,先把当前目录下残留的检测缓存清掉,否则某些场景可能识别不到新装的库:
make clean rm -f config.cache config.status ./configure --prefix=/usr/local这里有个细节:有的精简系统里curses库的符号名是libncurses,但configure脚本检测的是-lcurses。如果你确认ncurses已经安装,检测仍然失败,可以手动在/usr/lib64/(或对应的lib目录)下建一个软链接:
sudo ln -s /usr/lib64/libncurses.so /usr/lib64/libcurses.so不过这个属于非常规操作,遇到报错时先参照报错信息把包补齐才是正路。
4.2 make期间报curses.h找不到
比configure失败更让人头大的,是configure顺利通过、make的时候突然冒出一句:
curses.h: No such file or directory这种报错说明编译器的头文件检索路径里没有curses.h。原因还是开发包没装齐。检查一下:
ls /usr/include/ncurses.h如果没有这个文件,直接补装ncurses-devel。补装后要记得重新执行configure,让检测信息刷新,否则Makefile里可能还残留旧的编译选项。另外,如果你的系统把头文件放在/usr/include/ncursesw/而不是/usr/include/,某些老版本configure脚本可能因为搜索路径不同而找不到。这时可以温柔地在include目录下建一个指向ncursesw目录的软链接,或者手动把-I/usr/include/ncursesw加进CFLAGS里重跑,别嫌麻烦,这一步折腾清楚后编译就是秒过。
4.3 画面乱码或刷新异常
我最初在一台远程服务器上玩的时候,遇到过整个屏幕的字符上下跳动、地形局部重叠的情况。排查下来,多数不是程序问题,而是终端环境问题。moon-buggy依赖终端对光标定位控制序列的支持,如果终端模拟器兼容性一般,或者终端类型配置不对,画面就会变得没法看。
一个比较有效的办法是把终端类型明确设为xterm-256color,在SSH终端软件里手动指定即可。如果你用的是手机端SSH客户端,建议换一个功能完整一点的终端模式,并在连接设置里打开“终端类型为xterm”之类的选项。
另外,远程连接时网络延迟太高也会让画面刷新看着卡顿。moon-buggy的刷新是逐帧进行的,字符内容本身很小,正常网络下不会有明显延迟,但如果你隔着很远的网络用4G玩,偶尔画面撕裂也算正常现象,别怪系统。
4.4 按键失灵、卡死、退不出去
按键没反应是终端游戏里比较闹心的问题。我自己遇到过的几个典型场景:
一是焦点问题。远程桌面或多个窗口叠在一起时,键盘事件传到了别的窗口,点击一下终端窗口再玩就好。
二是输入法抢占问题。在桌面Linux上,某些输入法会把空格和英文字母吞掉,导致游戏收不到按键。玩之前把输入法切到英文模式,或者干脆关掉,问题立刻消失。
三是终端软件转发问题。部分终端模拟器自定义了按键映射,比如某些快捷键会拦截b、f、空格。此时换成终端默认配置,或者换一个普通的终端模拟器,按键就恢复正常了。
万一游戏卡死、q键也没反应,直接按Ctrl+C强制结束,然后检查终端环境。moon-buggy本身没有复杂的网络交互,卡死的概率很低,大多数卡住都是终端连接断流导致的,重连一次就会好。
| 现象 | 直接原因 | 解决方向 |
|---|---|---|
| configure报找不到curses | 未安装ncurses开发包 | 安装ncurses-devel后重新configure |
| make报curses.h缺失 | 头文件不在搜索路径 | 补装开发包,必要时直连头文件路径 |
| 画面乱码/跳动 | 终端类型或宽度不兼容 | 终端类型改为xterm,拉大窗口 |
| 按键无响应 | 输入法或终端按键映射干扰 | 切英文输入法,更换终端模拟器 |
| 成绩无法保存 | 分数文件权限不足 | 提前创建分数文件并放权给games组 |
4.5 卸载与残留清理
如果你哪天决定不玩了,卸载moon-buggy其实很简单。前提是你还留着当时的源码目录。在源码目录里执行:
sudo make uninstall这条命令会根据安装时的记录,把/usr/local/bin/moon-buggy和对应的手册文件清理掉。如果你已经删了源码目录,那就手动删掉可执行文件:
sudo rm -f /usr/local/bin/moon-buggy sudo rm -f /usr/local/share/man/man6/moon-buggy.6.gz分数文件按需清理。moon-buggy的运行不依赖额外服务,也没有后台进程,删完之后系统里不会残留什么“服务痕迹”,干净得很。这也是这个小程序的好处:来去自如,不给你添堵。
最后分享一点我自己的体会。这种字符游戏放在今天看,画面确实简陋到不行,但它逼着你去理解终端到底是怎么工作的:字符如何定位、刷新如何完成、键盘输入如何被程序监听。装完moon-buggy之后,我顺手把源码翻了一遍,意外地梳理清了不少之前模糊的curses概念。后来我又在一台更精简的无桌面环境里按同一套流程复现了一次,依然是四条命令解决问题。如果你平时也整天泡在命令行里,我建议你花五分钟装一个,不纯是为了摸鱼,而是这种“用最简单工具造出完整乐趣”的感觉,本身就挺值得体验一回的。