2026-04-03 22:48:39
最近小孩在学 C++(信奥),学了堆语法以后不知道干嘛,学了一年也只会对着黑窗口打印内容,正反馈太弱了,不像其他语言,学个几天就能做出漂亮的东西来,恰巧他对开发游戏感兴趣,我扫了一眼现在 C++ 的游戏开发框架,都太复杂了,SDL 概念琐碎,SFML 使用麻烦,所以我写了个针对初学者的游戏库,只有一个头文件 GameLib.h 零依赖,拷贝到代码目录 include 就能用,十行代码就能出个小 demo:

本着简化一切的思想,使用起来比 PyGame 还要简单:
#include "GameLib.h"
int main() {
GameLib game;
game.Open(640, 480, "My Game", true);
int x = 320, y = 240;
while (!game.IsClosed()) {
if (game.IsKeyDown(KEY_LEFT)) x -= 3;
if (game.IsKeyDown(KEY_RIGHT)) x += 3;
if (game.IsKeyDown(KEY_UP)) y -= 3;
if (game.IsKeyDown(KEY_DOWN)) y += 3;
game.Clear(COLOR_BLACK);
game.FillCircle(x, y, 15, COLOR_CYAN);
game.DrawText(10, 10, "Up/Down/Left/Right to move!", COLOR_WHITE);
game.Update();
game.WaitFrame(60);
}
return 0;
}
就这么几行代码,没有 SDL 里反锁的像素格式,消息机制,各种乱七八糟 SDL_ 开头的对象,也没有初始化就需要 500 行代码的 DirectX 那么麻烦,所有复杂的东西藏起来,只留下做游戏的乐趣。
编译:
g++ main.cpp -o game.exe
不需要加任何编译参数,很多初学者连命令行编译都不懂(比如我家小孩),只会直接在 DevC++ 里点编译+运行,让他们像用其他库一样添加一些类似 -ld3d9x 之类编译参数,可能直接就劝退一大群人,因此这个库完全使用默认编译参数,所有依赖都是动态库自己手工加载。
运行就能用方向键控制小球移动:

几行代码迅速看到反馈。
为什么做这个库呢?
市面上的游戏库(SDL、SFML、raylib)都很好,但对于刚接触 C++ 的初学者来说:
GameLib 的目标是零门槛:把 GameLib.h 拷到项目文件夹,写一个 .cpp 文件,点编译,游戏就跑起来了。
它专门为 Dev C++(很多学校编程课在用的 IDE)设计,兼容其自带的 GCC 4.9.2 编译器。当然,任何支持 C++11 的 Windows 编译器都可以用。
(点击下面展开更多)
特性一览
零配置:
开箱即用的绘图:
精灵系统:
键盘和鼠标:
声音:
游戏工具:
Tilemap 系统:
快速上手
第一步:下载
把 GameLib.h 放到你的项目文件夹里。
第二步: 写代码
创建一个 main.cpp:
#include "GameLib.h"
int main() {
GameLib game;
game.Open(800, 600, "Hello GameLib", true);
while (!game.IsClosed()) {
game.Clear(COLOR_DARK_BLUE);
game.DrawTextScale(200, 250, "Hello, World!", COLOR_GOLD, 3);
game.DrawText(280, 320, "Press ESC to exit", COLOR_GRAY);
if (game.IsKeyPressed(KEY_ESCAPE)) break;
game.Update();
game.WaitFrame(60);
}
return 0;
}
第三步:编译运行
Dev C++:新建项目 > 添加 main.cpp > 编译运行。
或者命令行:
g++ -o game.exe main.cpp -mwindows
就行了。
随机星空
再来个有点视觉效果的例子,随机星空:
#include "GameLib.h"
int main() {
GameLib game;
game.Open(800, 600, "Starfield", true);
// 生成 200 颗星星
int sx[200], sy[200], speed[200];
uint32_t colors[] = {COLOR_WHITE, COLOR_LIGHT_GRAY, COLOR_YELLOW, COLOR_CYAN};
for (int i = 0; i < 200; i++) {
sx[i] = GameLib::Random(0, 799);
sy[i] = GameLib::Random(0, 599);
speed[i] = GameLib::Random(1, 5);
}
while (!game.IsClosed()) {
game.Clear(COLOR_BLACK);
for (int i = 0; i < 200; i++) {
sx[i] -= speed[i];
if (sx[i] < 0) {
sx[i] = 800;
sy[i] = GameLib::Random(0, 599);
}
game.SetPixel(sx[i], sy[i], colors[speed[i] % 4]);
}
game.DrawText(250, 290, "Press ESC to exit", COLOR_GRAY);
if (game.IsKeyPressed(KEY_ESCAPE)) break;
game.Update();
game.WaitFrame(60);
}
return 0;
}
就这么简单,运行效果(点击播放 GIF 动画):

几行代码就能有看得见摸得着的东西,正反馈远远强过黑窗口打印文字。
这个 GameLib.h 适合开发哪些类型的游戏呢?
更多例子请访问项目主页:
https://github.com/skywind3000/GameLib
里面有 15 个例子程序,包括类似《打砖块》 ,《太空射击》之类游戏的代码:

一步一步教你从:窗口控制,键盘鼠标交互,图形绘制,精灵,音乐,卷轴等覆盖各个 GameLib.h 的功能点。
欢迎学会了 C++ 语法想做点什么的同学尝试。
![]()
The post 单头文件 C++ 游戏开发库(GameLib.h) appeared first on Skywind Inside.
2026-01-30 00:27:00
如何最快搭建个人云盘?Nextcloud 太大太臃肿,后面一堆 apache/nginx/php/mysql,命令行同步也不好用,私货还太多。
著名的 syncthing 要求有 P2P 中转服务;还要求同步时另一台电脑也开着机,不开机的话,你要在服务器上做一个同步点持续运行,那么做了这个服务和 C/S 架构的 rclone 有啥区别呢?还要多依赖一个 P2P 中转服务(虽然可以找到别人提供的),其他的开源产品也好不到哪里,相比之下 rclone 是最轻量级的解决方案了。
恰巧 rclone 最近几年一直在优化 bisync 功能,就是双向同步,网盘的核心功能,bisync 在 2022 年引入 rclone 一直处于 experimental/beta 阶段,其实几年前就基本可以用了,官方文档在 2025 年下半年正式移除 experimental/beta 字样,然后 bisync 功能正式转正。
所以我们用 rclone 的 bisync 功能来分别搭建客户端和服务端:
1️⃣ 服务端搭建
使用 supervisor 编辑 /etc/supervisor/conf.d/rclone-sftp.conf 文件:
[program:rclone-sftp]
command=/home/data/app/rclone/rclone serve sftp /home/data/sync --addr :2022 --user MYNAME --pass MYPASS --cache-dir /var/cache/rclone --vfs-cache-mode full
user=nobody
autorestart=true
然后重启:
sudo supervisorctl reload
一个 rclone 提供的 sftp 服务就启动了,就是这么简单,它速度快性能好,传输有加密。
最后我们在 sftp 的文件夹里建立一个叫做 bisync 的文件夹:
sudo mkdir /home/data/sync/bisync
sudo chown -R nobody:nogroup /home/data/sync
处理好权限,让 nobody 这个用户能够读写即可,就这么几步操作,比搭建个 Nextcloud 之类的服务方便太多了。
2️⃣ 客户端
我用 WSL,编辑配置 /root/.config/rclone/rclone.conf 内容如下:
[sftp1]
type = sftp
host = 192.168.1.12
user = MYNAME
port = 2022
pass = [运行 rclone obscure "MYPASS" 得到的加密字符串]
shell_type = unix
md5sum_command = md5sum
sha1sum_command = sha1sum
不想手工填写也可以用 rclone config 交互式的初始化并连接 sftp 服务,一旦服务配置好了,我么就能找个文件夹然后在定时任务里 bisync 了。
不过首先要初始化一下:
mkdir /mnt/e/Local/Cloud/rclone
rclone bisync /mnt/e/Local/Cloud/rclone sftp1:/bisync --resync
这个 --resync 参数用于首次同步初始化,后面就定时任务了。
编辑同步脚本 /home/data/shim/rclone-bisync-sftp1 内容如下:
#!/bin/bash
# configure
RCLONE_BIN="/home/data/app/rclone/rclone"
RCLONE_REMOTE=sftp1:/bisync
RCLONE_LOCAL=/mnt/e/Local/Cloud/rclone
LOGFILE="/var/log/rclone-bisync.log"
# start
$RCLONE_BIN bisync "$RCLONE_LOCAL" "$RCLONE_REMOTE" \
--create-empty-src-dirs \
--compare size,modtime \
--resilient \
--recover \
--max-lock 2m \
--verbose \
--log-file="$LOGFILE"
定时启动:
编辑 /etc/cron.d/rclone_bisync 内容如下:
*/5 * * * * root /home/data/shim/rclone-bisync-sftp1
即可,调试完正常可以把启动脚本里的 --verbose 去掉,没错误就不写日志了。你可以在多个客户端上进行类似的配置,不管 Windows 还是 Linux,要点就是先 config 上远端 sftp,然后初始化 --resync,然后就是定时调用 bisync 子命令就行。
然后你就得到了一个干净纯粹的,开源的,多端同步网盘了。
后记
在 bisync 之前,rclone 实现网盘主要靠 mount,这个功能类似 samba,每次读取写入都要走网络,局域网还行,跨机房就卡的不行了,它后来提供了 cache 机制有一定缓解,但一致性又有问题,经常不同步,这边改了不能像 samba 那样通知那边。
所以 rclone 做网盘体验最好的目前就是 bisync 功能了,bisync 的 bisync 可以用很多源,作为服务端,如果你不想搭建一大套 webserver / fileserver 来做源的话,最好就是用 rclone 自己可以 serve 的服务,包括:http,sftp,webdav,nfs 等等。
我试过 webdav 等,发现如果想要加密,前面还得再套一层 https 代理,或者又搞一大堆证书什么的,异常麻烦,所以体验最好,速度最快的是 sftp 服务。
![]()
The post 使用 rclone bisync 两步搭建个人云盘 appeared first on Skywind Inside.
2026-01-03 22:06:35
说起文本模式界面库,也许有人听过 Turbo Vision 2.0,这货是当年 Borland C++ 3.1 (不是 Turbo C 2.0)背后的商用界面库 TV2 的开源版,经过多年迭代,如今是一款支持 unicode 和现代 C++ 跨平台的 TUI 库了:

项目地址:https://github.com/magiblot/tvision
主要特性:
Linux 下大部分 TUI 程序都是平铺窗口,无法重叠,更无法自由拖动,而 Turbo Vision 2.0 完全像用图形界面程序一样,鼠标操作这些窗口自由移动,扩大缩小,全屏化:

而且 Linux 下面大部分程序对 ALT+ ,CTRL+ ,SHIFT+CTRL+ 等组合键支持非常有限,而 TV2 对不同平台的键盘鼠标做了很好的兼容,让你在远程终端里也能自由的使用各种组合键和功能键。
用过 Borland C++ 3.1 的人一定会以为 BC31 重生了,某种意义上来讲是的,不要觉得技术古老,Linux 下面 TUI 发展几十年,没一个打得过 Turbo Vision 2 的:

这是 TV2 做的终端模拟器 tvterm,各位天天用 tmux 分屏模拟,但 tmux 发展了那么长时间都不支持子窗口互相重叠覆盖,鼠标拖动,TV2 可以让你像用桌面软件一样灵活的操作各个子窗口。
Vim/NeoVim 直到 2019 年才支持 popup/floatwin 可以实现上面类似的效果,而 Turbo Vision 2 在三十年前就做到了。
过去 TV2 只支持 ANSI 编码,无法显示中文,如今中文,日文都能正常显示:

包括 emoji:

你在 Linux 下大部分 TUI 程序想调整下设置都只能编写配置文件,配置 vim 也只能写 vimrc,但 TV2 里有丰富的 TUI 设置对话框:

大部分设置,对话框里点点鼠标就能搞定,毫无学习门槛,无需看很多帮助才知道怎么写配置:

当然 TV2 也有内置帮助系统,它有一套类似 .chm 等帮助系统,内部包含索引,跳转,可以在 TUI 内随时查看你的帮助文件,比如下面的快捷键帮助,基本上和 Windows 程序一脉相承:

最后是编程接口,linux 下一堆 tui 接口,比如 ncurses 这样的都是比较初级的原始的,没有任何高级控件,同时接口也是 C 的,而 TV2.0 基本上所有高级控件你都可以直接使用,写起代码来类似传统的 Qt 程序:
class HelloApp : public TApplication {
public:
HelloApp();
void showHelloDialog();
};
HelloApp::HelloApp() :
TProgInit(&TApplication::initStatusLine,
&TApplication::initMenuBar,
&TApplication::initDeskTop) {
// 启动时显示对话框
showHelloDialog();
}
void HelloApp::showHelloDialog() {
// 创建对话框 (x, y, width, height)
TDialog *dialog = new TDialog(TRect(0, 0, 40, 9), "Hello World");
if (dialog) {
// 居中对话框
dialog->options |= ofCentered;
// 添加 "Hello World" 静态文本 (居中显示)
TStaticText *text = new TStaticText(
TRect(2, 2, 38, 5),
"\003Hello World" // \003 表示居中对齐
);
dialog->insert(text);
// 添加 OK 按钮 (居中)
TButton *button = new TButton(
TRect(14, 5, 26, 7),
"~O~K",
cmOK,
bfDefault
);
dialog->insert(button);
// 显示模态对话框
deskTop->execView(dialog);
// 清理
TObject::destroy(dialog);
}
}
int main() {
HelloApp app;
app.run();
app.shutDown();
return 0;
}
基本就是类似 Qt 的编程方式:事件驱动+控件组合+OOP,不是 ncurses 那种 select/read 标准输入,自己解码半天终端控制码,在琐碎的控制各处显示,自己控制状态切换和重绘,写的你想吐。
Linux 下面基于 ncurses 二次封装的库也很多,但大多是个人项目,浅层封装,Turbo Vision 过去作为支持 Borland C++ 3.1 这种商用级 IDE 的界面库,不是这些玩票项目可以比得了的。
编程语言 TMBASIC 也是用 Turbo Vision 2 做的界面:

补充点历史,Turbo Vision 最初是 Borland 公司用 Pascal 实现的,用于 Turbo Pascal,后来在做 Borland C++ 3.x 的时候用 C++ 重新实现了一个版本,用于支持 BC31 的界面,在 BC31 里包含头文件和静态库,你可以直接用它构建 TUI 程序,接着 Borland 在 1997 年将 C++ 版本的完全开源了,就是我们上面说的这套的源头;
而 Pascal 版本的 Turbo Vision 一直没开源,Free Pascal 后面又根据 C++ 开源的版本重新实现了一套叫做 Free Vision 的界面库给 Free Pascal 做 IDE 用:

我很喜欢它的设置界面,根本不用读文档写配置文件,直接对话框里全部帮你归好类了:
c
是不是很眼熟?Free Pascal 的 IDE,背后使用的 Free Vision,和上面的 Turbo Vision 同出一源。
PS:Turbo Vision 还出过几本书:

想看的话到开头项目主页里有链接。
![]()
The post C++ 最好用的 TUI 界面库 Turbo Vision 2.0 appeared first on Skywind Inside.
2025-12-27 00:32:00
就一年没清理 C 盘,今天清理出 140GB 的东西来,而且还没影响使用,所有程序都在往你的 C 盘拉屎。不要网友问我怎么清理下来的:
1)右键 C 盘属性,清理;
2)自己到 TEMP 目录手动清空,注意有三个 Temp:AppData 下面两个,Windows 目录下有一个;
3)SpaceSniffer 找占用大的目录,清空不合理的,这个需要一点经验,拿不准可问下 AI 某目录能不能清空;
4)清浏览器缓存;
5)最后 CCleaner 跑一遍。

上面一系列任务做完基本就清理出 100GB 的内容了,然后再使用 Dism++ 删除系统还原点后,又多出 40GB 来:

最开始剩余空间只有 130GB,现在有 272GB 剩余,可以做一次年度全盘备份了。
![]()
The post 如何清理你的系统盘(C: 盘)? appeared first on Skywind Inside.
2025-10-30 13:48:00
Rust 并不适合开发游戏,它更擅长有明确定义,边界清晰的项目,这样你类型体操一遍做完问题不大,比如重构个已经十年没变过的 C 模块,但游戏领域并没有明确的定义,策划案不停修改,你的代码不但要求快速迭代还要求不停重构,那么类型体操在这过程中就变成锁死你的紧箍咒。
参考文章:3 年写了 10 万行代码开发者吐槽:当初用 Rust 是被忽悠了
这里解释一下,为什么当项目没有明确定义时,rust 为啥会显得笨拙?因为此时不但需求会随时间变来变去,更要命的是你没有一份十年没变过的 C 代码做参考,对项目整体实现缺乏全局的认识,只有自底向上的方法不断尝试和修正自己,不段反思和改进中上层代码,才能像盲人摸象那样逐步认清楚整个世界因该是啥样。
而此时类型体操会在这时勒得你喘不过气来,一个之前需要横着用的变量现在需要竖着用了,你思来想去发现你完全没办像其他语言那样改成法竖着用了,于是你只有引入更大范围的重写才能解决问题,你觉得这样很难受,去 rust 社区寻求帮助,但发现他们并不会帮助你真的解决语言问题,只会一个劲的指责你 “你觉得痛苦正是因为你对 rust 不熟悉导致的” 或者 “rust 逼迫你更大范围重写正是逼你尽早写出更好的代码”,他们这么说在定义清晰的项目里的确没问题,越早重构越好,但在定义不清晰的项目上里存在大量中间设计,你今天改成这样,八成不是最终形态,隔几天可能还要改,而此时 rust 却逼迫你每次都提前费精力进行更大范围的重写,即使这时完全没必要的,过两天就不需要的,他也不许你像其他语言那样用快速实现的方式应对新的中间状态,等需求稳定了,技术方案也收敛的情况下再进行迭代和完善,然后你就抓狂了!
网友 FENG DONG:项目没有明确定义时候,需要设计 cost function,然后让代码沿着 gradient 演进。但 Rust 不是一种可微的语言。
网友 Aaltonen:游戏开发是 “巨型可变状态球” (giant balls of mutable state),需求像 gradient descent 一样逐步演进,但 Rust 的借用检查器(borrow checker)和所有权模型强制你 “一次性想好”,导致小改动引发大重构。
那么 Rust 适合开发游戏引擎么?我只能说 depends,主要到了现在也没啥 rust 开发游戏引擎的成功例子啊,一天到晚到处搞营销的 rust 游戏引擎 bevy 基本上类似个玩具,到现在都没啥靠谱的商业游戏案例,顶多几个独立小游戏之类,而且它要求用 rust 来写业务逻辑,这个上面已经论述过,它并不适合开发游戏业务逻辑;
其次游戏引擎有很多部件,有需要高度优化各种汇编技巧的性能部分(类似 ffmpeg),有需要同各种系统图形 api 打交道的抽象硬件层部分(不断同 direct3d,opengl,vulkan 还有各种系统 api 打交道),还有需要大量整合第三方(基本是 c++ 库,比如 imgui, box2d, sdl, bgfx, physx)的胶水层,这些也并不适合 rust。除非你觉得 ffmpeg 这样的项目适合用 rust 重写,或者可以用 rust 把大量久经考验的第三方库全部发明一遍。
最后,成熟的游戏引擎里都是有各种 hack 或者 dirty trick 的,rust 做这些并不是特别方便。
配图:“But it’s SAFE !!”

![]()
The post Rust 适合开发游戏吗? appeared first on Skywind Inside.
2025-10-24 00:04:59
我的博客使用的 wordpress 一直架设在 bluehost.cn 上,差不多十多年了,前两天突然就不能访问了,后台也登录不进去,一查 bluehost.cn 主页,原来停止服务了,很多和我一样在上面运营十多年的网站都是说停就停,然后完全不提供数据备份的时间,连个电话都不给你打一个,就是邮件垃圾箱里提前几天给你发了一封告知邮件,人家 linode 之类的欠费停止你服务后,任然给你机会备份走,结果它完全不给。
所以没有啥完全稳定会一直存在的服务商,幸亏我机器上有备份,调查了以下几家虚拟主机提供商,他们的业务发展情况及稳定性,最后迁移 bluehost.com 了,帖子和评论都恢复了,但是页面访问统计没恢复到,因为页面访问统计插件是把数据存在别的 mysql 表里的,但之前用的备份插件又是只导出 wordpress 标准表格,所以包括访问统计,upvote 之类的数据全部清零了,无所谓了,还好访问量不算啥重要的东西,希望这次 bluehost.com 能多用两年。
之前我用过 bluehost.com 的,指示图 bluehost.cn 服务器在香港,国内访问会快点后面才选他,看来太小众的还是有问题。这次 bluehost.com 的服务器在亚利桑那,虽然远点,但国内访问起来,只要不下载,看个页面什么的也还算顺利。
有人问我为何不用静态页面?发布到 github pages 上那种,因为我这个 wordpress 博客以及个人 wiki 只依赖一家服务商,但是 github pages 页面需要依赖 github,评论需要依赖 gihtub issues+插件,计数器又需要依赖别的什么服务,依赖的服务太多了,上网那么多年我从不相信有什么服务可以一直持续下去的,所以依赖自然也少越好。
除了服务外,依赖的项目也是越少越好,之前那些 github pages 使用的基于 issues 的插件突然作妖,要收费,不收费就给你插广告,闹得天怒人怨,你还没办法,历史评论是博客相当重要的数据,依赖 github issues 作为评论数据存储的机制还有个致命方案是你还不能方便的导入导出,你会被绑死在 github issues 这个方案上,完全无法掌握自己的数据,不说 github 停止服务,一旦它一朝更改 api 规则(跟 twitter 一样)就只有哭了。
最后 wordpress 的功能真的很强大,插件生态也非常丰富,我也比较熟悉,有啥需求大概都能搞得定。
![]()
The post 博客迁移服务商 appeared first on Skywind Inside.