DDraceNetwork 是一款开源免费的多人合作平台跳跃游戏(其前身是 Teeworlds 的一个叫 DDRace 的模组),上限高游戏性强,是一个非常独特的合作游戏。本项目依赖众多好心的程序员进行维护,作为一个基本成熟稳定的 C++ 游戏项目,我们可以从这个项目中学习到很多开发相关的知识,甚至如果你有什么改进,也可以为原代码仓库提出 Issue 贡献 PR。
Fork 仓库后克隆代码
bashgit clone --recursive git@github.com:YourUserName/ddnet.git
安装依赖
bashsudo apt install build-essential cargo cmake git glslang-tools google-mock libavcodec-extra libavdevice-dev libavfilter-dev libavformat-dev libavutil-dev libcurl4-openssl-dev libfreetype6-dev libglew-dev libnotify-dev libogg-dev libopus-dev libopusfile-dev libpng-dev libsdl2-dev libsqlite3-dev libssl-dev libvulkan-dev libwavpack-dev libx264-dev python3 rustc spirv-tools
构建项目
bashcmake -Bbuild cmake --build build
如果构建的客户端无法连接服务端,有一种可能是你的 TUN 模式没关。
代码格式化检查,运行 scripts/fix_style.py
脚本。由于 Ubuntu 24.04 已经找不到 clang-format-10 的安装包,我们需要自行编译或通过其他途径安装:
使用 pip 安装(官方推荐)
A lot of the style offenses can be fixed automatically by running the fix script ./scripts/fix_style.py
We use clang-format 10. If your package manager no longer provides this version, you can download it from https://pypi.org/project/clang-format/10.0.1.1/.
由于执行检查脚本使用的是 python,我们可以通过 pip 安装。如果是用 conda 安装的,在执行 python 脚本时指定 python 环境,就可以顺利运行检查。
bashpip install clang-format==10.0.1.1
直接下载二进制文件
https://aur.archlinux.org/packages/clang-format-static-bin
下载后将二进制文件移动到 /usr/local/bin
目录下并重命令为 clang-format-10
bashsudo mv /path/to/clang-format-10_linux-amd64 /usr/local/bin/
cd /usr/local/bin/
sudo chmod +x clang-format-10_linux-amd64
sudo mv clang-format-10_linux-amd64 clang-format-10
通过源码编译(未尝试)
bashgit clone https://github.com/llvm/llvm-project.git
cd llvm-project
git checkout llvmorg-10.0.1
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_PROJECTS=clang ../llvm
make -j$(nproc)
sudo make install
编译过程中可能出现部分报错:
std:numeric_limits
不是 std
成员。在相关文件中包含 #include <limits>
即可uintptr_t
未声明,在相关文件中包含 #include <cstdint>
即可按项目自述文件操作
bashsudo apt install libgtest-dev
cd /usr/src/gtest
sudo cmake CMakeLists.txt
sudo make
# copy or symlink libgtest.a and libgtest_main.a to your /usr/lib folder
sudo cp lib/*.a /usr/lib
在我运行时,还需要安装 gmock
bashsudo apt install libgmock-dev
这个博主配了但试不出来有什么东西,估计是没配置好吧
安装 Clang
bashsudo apt install clang
编译命令
CC=clang CXX=clang++ CXXFLAGS="-fsanitize=address,undefined -fsanitize-recover=address,undefined -fno-omit-frame-pointer" CFLAGS="-fsanitize=address,undefined -fsanitize-recover=address,undefined -fno-omit-frame-pointer" cmake -DCMAKE_BUILD_TYPE=Debug . make
运行命令
bashUBSAN_OPTIONS=suppressions=./ubsan.supp:log_path=./SAN:print_stacktrace=1:halt_on_errors=0 ASAN_OPTIONS=log_path=./SAN:print_stacktrace=1:check_initialization_order=1:detect_leaks=1:halt_on_errors=0 LSAN_OPTIONS=suppressions=./lsan.supp ./DDNet
结果检查
运行后,检查生成的 SAN.*
文件以查看详细的问题报告。ASan + UBSan 能够发现比 Memcheck 更多的问题,尤其是在内存错误和未定义行为方面。
这个工作区配置挺折腾,中间没配好我真的非常沮丧……
在调试过程中,我发现一旦客户端代码命中断点,就会导致鼠标被游戏捕获无法释放的问题。在 dc 中询问后,Jupstar 大佬给我了一个解决方案。
注意
修改桌面环境之后我的系统会经常报错,虽然不影响使用,但修改之前请考虑!
按 other/vscode/README.md
的说明,下载相应的二进制文件和安装相应的包(其中 clang-format
可按前文所述安装)
sudo apt install clangd clang-tidy lldb rustup mold ninja-build xdotool
按照自述文件先按 Ctrl+Shift+P
输入 Scan for kits
扫描工具箱,再按 Ctrl+Shift+P
并选择 Select a kit
,然后选 [DDNet]
开头的工具。
如果 cmake 生成时出现 rustup 相关报错,请执行命令:
bashrustup default stable
查看一下当前显示是什么桌面环境,如果使用的不是 X11 的桌面环境,需要修改设置
查看桌面环境:
bashecho $XDG_SESSION_TYPE
修改设置:
bashsudo vim /etc/gdm3/custom.conf
把该文件中这一行的注释状态解除:
diff- # WaylandEnable=false
+ WaylandEnable=false
然后重启即可切换。
vscode 调试时需要从“运行与调试”中进入,不要点击 vscode 底部的 Cmake 调试按钮,否则走的不是工作区中定义的调试配置。
src/base
目录
由于DDNet是一个跨平台游戏,需要一个抽象层来简化开发,因此该目录包含许多有用的函数来处理这一问题。
src/engine
目录
游戏引擎所在位置,它处理大多数与玩法无关的东西,比如图形、声音、网络等。
src/game
目录
所有玩法的代码所在位置,分为客户端和服务器。
服务器端
这个游戏使用自己的面向对象的实体分级系统,所有其他实体源于主类 CEntity
,位于 src/game/server/entity.h
目录。
游戏世界在 src/game/server/gameworld.h
路径下,管理这些实体。
一些重要实体有:
CCharacter
:代表一个活着的 Tee, 当一个 Tee 生成时会被实例化,当它死亡时会被删除。CPlayer
:包含了其他没有关联 Tee 的信息(昵称、国籍等)。有关玩家在死亡之间的信息,请参阅此项。客户端
客户端由许多组件构成,都是在 src/game/client/component.h
中定义的继承 CComponent
的类:这些组件通过实现视觉方法来提供功能,例如 OnInit
,OnMessage
等等。
网络
网络协议几乎由 python 脚本生成并输出 c++ 代码,例如说,datasrc/network.py
定义了所有网络包。
贡献前的准备
在编写代码前,建议先开一个 issue 讨论想法,确保贡献符合 DDNet 项目的理念。常见的被拒绝贡献包括:
编程语言
DDNet 主要使用 C++,少量使用 Rust,Python 用于代码生成和工具,CMake 用于构建。平台特定代码可能使用 Java(Android)或 Objective-C++(macOS),但不接受其他语言的代码。
代码风格
命名规则:变量、方法和类名使用大驼峰命名法(如 MaxLength
),避免单字母变量名。
匈牙利命名法:继承自 Teeworlds,使用前缀如 m_
(类成员)、g_
(全局变量)、p
(指针)等。
现代 C++ 实践:优先使用 nullptr
、true
/false
,避免 goto
、默认参数和方法重载。
代码格式化:使用 clang-format 10 自动格式化代码。
最佳实践
避免在 if
语句中赋值:明确分离变量赋值和条件判断。
Getter 方法命名:避免使用 Get 前缀(如 MyVariable()
优于 GetMyVariable()
)。
类成员初始化:在声明时直接初始化类成员变量。
文件命名:使用小写字母和下划线分隔(如 foo_bar.cpp
)。
提交消息
提交消息应描述对玩家/用户的影响,而非技术细节,以便直接用于变更日志。
goog first issue 的作用是什么?
比如我找的这个 issue:https://github.com/ddnet/ddnet/issues/9583 是个很简单的工作,只需要把描述文本修改一下就行。
另外,这个网站可以帮助你查看流行开源项目中可能的 goog first issue。
在 PR 中提及要解决的 issue,一般可以用 fix#xxxx
或 close#xxxx
,这样 github 会自动渲染出链接的 issue 并会提示 PR 将关闭这个 issue
想要验证其他人还未被合并的 PR?
在你已经 Fork 了自己的仓库,并且克隆到本地的基础上,先要添加 ddnet 官方的上游仓库:
bashgit remote add upstream git@github.com:ddnet/ddnet.git
然后,根据你要拉取的 PR 编号进行拉取,比如我想拉取 #9786 PR,我就从 upstream
拉取 pull/9786/head
,然后把这个本地分支命名为 keb-pr
:
bashgit fetch upstream pull/9786/head:keb-pr
在 issue 中插入视频,直接拖入即可 `.mp4` 最佳,可直接渲染出播放窗口
在 issue 中引用特定提交的代码。在 github 某个提交的代码浏览的界面里,点选行号(按住 shift 可以选择范围),点击菜单选择 Copy permalink
即可,以下链接会被 github 渲染成相应区域的代码块:
参与代码贡献是一件令人振奋的事情,但中间也会遇到一些会让你感到受挫的事情,你需要以平常心看待它们。
项目维护者对你的 PR 的 review 可能比较严格
一般是因为你的提交存在一些问题,或者不规范的地方,如要求你压缩你的提交,修改提交信息等。正视它们,这些直率的建议也能让你进步的更快。
社区的评价不一定都是中听的
社区对你的贡献的评价也可能让你不舒服,尽管他们看起来并没有恶意。比如我贡献一个提交,想获取 dev 身份组时,会有人用 “commit: readme typo fix” 来打趣我(而且这种开源贡献笑话还挺常见的,时不时就会出现一次)。
面对这种情况,还是要调整好心态,如果想要做长期的贡献还是从简单的 issue 开始的。跟进时间长了自然会做出有价值的提交。而且即使是简单的拼写修复提交,仓库的维护人员也一直欢迎和接纳,不要太受社区人员的影响。同时也需要自己提升心理承受能力。
开源社区终究也是社区,你并不突出
社区总有光彩夺目的人,你需要降低期待做好无人理睬的准备。在 Manim 幼儿园的时候就已经有这种无力感了,更别说外国社区,英语蹩脚没有熟人更会让你觉得自己是被无视了。DDNet 社区里虽然有几位国人版主和贡献者,但也都根本没有接触过,颇有一种孤军奋战的感觉。
在 github 上找了个几个月前的 issue,里面提到了了一个小 BUG,我的开发就从地图编辑器开始了。
随着慢慢深入源码,我可以发现代码中其实有很多可以改进的地方,不知不觉已经提了五个 PR 了。在这个过程中,可能会有自己的 PR 或者 issue 没有被仓库协作者看到的情况。你可以大胆地在 DC 群里去请求 review。当然遇到了编程相关的问题,也可以去问问 DC 里的人,如果有了解相关的代码的人,是会给予你帮助的。即使他们可能没有负责这部分的代码,他们也可以为你提供一些有价值的建议。
另外,这次有了五个 PR 之后,我也是鼓起勇气去 @ 了管理员,最后也是如愿以偿地得到了开发者的 role,所以还是得要大胆一点,只要你不犯大病礼貌一点,不会有什么惩罚的。
本文作者:Zerol Acqua
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!