Go 版 raycast 风格 3D 迷宫:融合
- raycast-game — 画面与操作:墙壁 / 天花板 / 地板 / 俯仰 / 视高 / 视野的 DDA 光线投射渲染,按键布局完全一致
- term-maze-3d — 迷宫玩法:随机迷宫、自由探索
Go 实现,零第三方图像库,仅依赖 eiannone/keyboard(按键)与 x/sys/unix(终端尺寸)。同一份源码提供两套构建:
| 构建 | 目标 | 音频 | 画面节拍 | 生成并行 | 视频解码 |
|---|---|---|---|---|---|
| 默认(Linux) | 桌面 Linux | 优先 ffplay |
60fps | 最多 16 核 | ffmpeg,优先 -hwaccel auto 显卡硬解 |
-tags termux |
Termux(Android) | 优先 termux-media-player |
40fps | 最多 4 核 | ffmpeg 软解 |
两者都只要求 ffmpeg(仅 mp4 需要),图片/GIF 用 Go 标准库。
- 墙壁使用 DDA 光线投射 + 边缘描边:竖直边
|、水平边_(俯仰时/\)、转角· - 天花板留空,地板用
.填充,地平线随俯仰 / 视高偏移 - 画面自适应终端尺寸:终端缩小或放大,游戏画面跟着缩放,不会出现乱码
- 巨型随机迷宫,默认 1000×1000,递归回溯生成,所有通路互相连通,绝不封死道路、没有孤岛
- 生成后再随机拆墙(braiding)打通大量回环,随便逛都不会被堵住
- 无出口、无胜利画面,纯自由探索;玩家出生点固定在迷宫左上角
- 生成提速:一次开传奇数格棋盘空间,命中率恒定,大尺寸迷宫数百毫秒内完成
- 渲染提速:列缓冲 / 行缓冲 / 帧缓冲跨帧复用,零每帧分配;光线给 512 步上限防长走廊卡顿
- 生成提速:彩蛋墙改为 1024 张图案池(图案由种子派生、随种子可重现),1501² 大图不再为每格存一张 8×8 图案,生成内存从约 25MB 降到不足 1MB;600² 以上按核数并行挖通道,小图自动串行
- 帧率:Linux 版 60fps、Termux 版 40fps;画面增量重绘,只在内容变化时才发送该行,画面静止时一字节都不写(状态行只保留开机按键提示与「小地图开/关」「视野」等瞬时信息,不显示 FPS/坐标)
- 硬件利用:画面由终端自身(GPU 加速的文本渲染)绘制,游戏只喂字节流;Linux 版额外让 ffmpeg 用
-hwaccel auto走显卡解码视频,失败自动回退软解 - 画面稳定:终端尺寸每 100ms 采样一次并保持稳定,弹出软键盘/瞬时抖动不会导致画面来回跳动;尺寸真正变化时清屏一次,不乱码
- 按键:
1右转、3左转 - 移动/转向即时响应:每按一次键立刻走一步(按住可连续移动),松开后做 250ms 的平滑滑动衔接,不依赖终端按键自动重复,Linux 桌面终端上也顺滑
- 开局通道固定打通:出生点北、东两侧始终有三条可行走路径,不会开局顶着墙
- 退出(
q或 Ctrl-C)会完整恢复终端回显与行模式,退出后照常输入 - 小地图为玩家周围区域的局部视图(占用屏幕左上的 1/4),成本与迷宫大小无关
| 按键 | 功能 |
|---|---|
| 2 / 8 | 前进 / 后退 |
| 4 / 6 | 向左 / 向右平移 |
| 1 / 3 | 向左 / 向右旋转 |
| 5 / 0 | 摄像头往上 / 往下 |
| 7 / 9 | 抬头 / 低头 |
| + / - | 增加 / 减少视野 |
| % | 开关小地图(左上角占屏幕 1/4) |
| / | 进入底部命令终端(见下) |
| q | 退出 |
按 / 进入底部悬浮的命令行(收起时约占屏幕 1/3):输入命令、回车执行,↑/↓ 翻命令历史,输出区用 PgUp/PgDn 或 Ctrl+U/Ctrl+D 滚动(底部状态行会显示可见范围),ESC 返回游戏。动画期间不节流、缓动滑入/滑出,收放平滑。同样支持管道与逻辑连接:|(管道)、&&/||、;、单/双引号与反斜杠转义,结构如 sh。命令只对本游戏内置命令生效,外部命令一律拒绝并提示未知命令(用 help 查看全部可用命令)。
| 命令 | 功能 |
|---|---|
| help | 显示全部命令帮助 |
| clear | 清空命令历史 |
| where | 位置 / 楼层 / 朝向 / 俯仰 / 高度 / 视野 |
| home | 回出生点 |
| tp x y | 传送到指定坐标(墙与越界会拒绝) |
| seed | 显示当前地图种子 |
| fov [值|wide|normal|+|-] | 视野 0.5~5,默认 1 |
| height [值|high|low|ground|+|-] | 视高 -5~5,默认 0 |
| reset | 重置俯仰与视高 |
| spin [on|off] | 视角自动旋转(游戏内任意键停止) |
| flip | 上下翻转视角 |
| party | 轮换墙体 ASCII 样式 |
| floorinfo | 当前楼层信息 |
| space|space close | 200×200 平地模式 / 返回迷宫 |
| door [x y|open|close [all]|list] | 放门 / 开合 / 列出(小地图 D,关门挡路) |
| bookmark [名] | 标记当前位置 |
| goto [名] | 传送到书签(跨楼层会重建该楼层) |
| elevator [楼层|home|list] | 电梯换层,种子固定可重现 |
| edit / edit off | 进入/退出编辑模式(Q 退出) |
| img load <文件> [x y] | 贴图片到墙面:.png/.jpg/.gif 自动转彩色 ASCII(真彩背景),其余当文本画;缺省自动找玩家附近的墙放置 |
| img list / remove | list 同时列出 ~/ 下的图片文件与已贴图 / 卸载贴图 |
| video play <文件> [x y] | 墙面播放:.mp4 用 ffmpeg 抽帧转 ASCII 真彩 10fps 且带音轨(音频优先 ffplay,其次 termux-media-player;只有 ffmpeg 一个必需外部工具,且仅 mp4 需要);.gif/.png/.jpg 纯 Go 标准库解码;文本格式帧之间用 --- 行分隔。可同时播放多个视频 |
| video stop [id] | 停止播放(省略 id 停止全部,含音轨) |
| video remove <id|all> / img remove <id|all> | 删除贴墙视频/图片 |
| video list | 查看正在播放的视频(同时列出 ~/ 下的 gif/mp4) |
| save [名] | 存为 ~/名.rmap(RAMAP,含楼层/玩家/门/地图) |
| load [名] | 载入 ~/名.rmap |
| file <路径> | 识别文件:本游戏存档 / ELF / 未知 |
编辑模式按键:2/8/4/6 或方向键移动光标、0空地 1墙 空格切换、D放门、G抓取、P放置、Q退出。where | seed 等内置命令可参与管道;save smoke && file smoke.rmap 同级联执行。存档只写入 ~ 目录,不执行任何外部命令。
游戏内按 空格 跳跃(抛物线带重力,跳跃中不可再起跳)。地图生成时约 9% 的墙会随机变成彩蛋墙:每面墙随机从十余种形状族(实心/环形菱形、圆、方框、十字、沙漏、四角、X 斜带等)抽取一个严格左右+上下对称的 8×8 像素画,用 ASCII 特殊字符(& ; ~ % / = $ ^ ! * ?)直接画在墙面上;每次重建地图(reset/elevator)图案都会重新随机,且随迷宫种子可重现。彩蛋墙不阻挡任何操作,小地图显示 %。贴图与视频以 ASCII 直接呈现在墙面上(真实图片/视频按亮度降采样成 .·:;!%#@ 字符画,每格一真彩背景色,配 256 色/真彩终端即可看到彩色画面),凡是贴了图或视频的墙,小地图统一从 # 变为 I。
依赖:Go 1.22+;ffmpeg 仅 mp4 贴图/视频需要。Linux 用 apt install golang ffmpeg(Fedora dnf、Arch pacman),Termux 用 pkg install golang ffmpeg。
cd term-maze-raycast
# Linux 版(产物命名:平台-名称-版本)
GOOS=linux CGO_ENABLED=0 go build -o linux-$(go env GOARCH)-term-maze-raycast-1.0.0 .
# Termux 版(Android/arm64;在 Termux 里可省略 GOOS/GOARCH)
GOOS=android GOARCH=arm64 CGO_ENABLED=0 go build -tags termux -o termux-arm64-term-maze-raycast-1.0.0 .
BIN=./linux-amd64-term-maze-raycast-1.0.0 # Termux 版换成 termux-arm64-...
$BIN # 默认 1000×1000
$BIN 600 # 生成 601×601(自动归一为奇数)
$BIN 2000 # 更大尺寸
$BIN -s world # 启动即读 ~/world.rmap
$BIN --save=~/a.rmap # 也可用 --save / --save= / -s= / -s路径小地图中:四周用 | 围边、# 墙壁、P 玩家、空格空地(显示玩家周围区域,占屏幕左上的 1/4)。