Development/zh: Difference between revisions

From DDraceNetwork
Darkh (talk | contribs)
No edit summary
Darkh (talk | contribs)
No edit summary
 
(13 intermediate revisions by 3 users not shown)
Line 1: Line 1:
{{MigrateTranslation}}
<languages />
<languages/>
 
本文皆在教您如何对 DDNet '''开发''' ,因为这是一款开源游戏(源代码公开),它依赖于一些善良的人们在空余时间的贡献。
本文皆在教您如何对 DDNet '''开发''' ,因为这是一款开源游戏(源代码公开),它依赖于一些善良的人们在空余时间的贡献。


Line 21: Line 21:
DDNet的源代码使用[https://git-scm.com/ Git]托管,这是一个版本控制系统,也是与多人协作开发的重要工具。
DDNet的源代码使用[https://git-scm.com/ Git]托管,这是一个版本控制系统,也是与多人协作开发的重要工具。


如果您的Linux发行版中还没有git,请安装它,例如在大多数基于debian/ubuntu的发行版中,您可以打开终端,输入:<code>sudo-apt-install git</code>。
如果您的Linux发行版中还没有git,请安装它,例如在大多数基于debian/ubuntu的发行版中,您可以打开终端,输入:<code>sudo apt install git</code>。




Line 36: Line 36:
== 安装依赖项 ==
== 安装依赖项 ==


如果您在Linux上,您可以通过阅读DDNet github页面上的自述文件来安装所有需要的依赖项:https://github.com/ddnet/ddnet#dependencies-在linux上--macos
如果您在Linux上,您可以通过阅读DDNet github页面上的自述文件来安装所有需要的依赖项:https://github.com/ddnet/ddnet#dependencies-on-linux--macos


对于Arch Linux:
对于Arch Linux:
Line 46: Line 46:


控制台输入
控制台输入
<code>sudo 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 python rustc spirv-tools4</code>
<syntaxhighlight lang="bash">
sudo 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
</syntaxhighlight>


<span id="Compiling_DDNet"></span>
<span id="Compiling_DDNet"></span>
Line 104: Line 106:
一些重要实体有:
一些重要实体有:


* [https://github.com/ddnet/ddnet/blob/master/src/game/server/entities/character.h CCharacter]: 代表一个活着的[[Special:MyLanguage/Common_Terminology#Tee|Tee]] , 当一个Tee生成时会被实例化,当它死亡时会被删除。有关玩家在死亡之间的信息,请参阅[https://github.com/ddnet/ddnet/blob/master/src/game/server/player.h CPlayer]。
* [https://github.com/ddnet/ddnet/blob/master/src/game/server/entities/character.h CCharacter]: 代表一个活着的[[Special:MyLanguage/Common_Terminology#Tee|Tee]] , 当一个Tee生成时会被实例化,当它死亡时会被删除。
* [https://github.com/ddnet/ddnet/blob/master/src/game/server/player.h CPlayer]包含了其他没有关联[[Special:MyLanguage/Common_Terminology#Tee|Tee]]的信息(昵称、国籍等)。有关玩家在死亡之间的信息,请参阅此项




Line 110: Line 113:
==== 客户端 ====
==== 客户端 ====


客户端由许多组件构成,都是继承<code>CComponent</code>的类:这些组件通过实现视觉方法来提供功能,例如<code>OnInit</code>,<code>OnMessage</code>等等。
客户端由许多组件构成,都是<code>src/game/client/component.h</code>中定义的继承[https://github.com/ddnet/ddnet/blob/master/src/game/client/component.h CComponent]的类:这些组件通过实现视觉方法来提供功能,例如<code>OnInit</code>,<code>OnMessage</code>等等。




Line 164: Line 167:
=== 枚举和常量 ===
=== 枚举和常量 ===


应该采用大蛇式命名法(所有单词大写并且用下划线间隔),例如<code>MAX_PLAYERS</code>
应该采用大蛇式命名法[https://en.wikipedia.org/wiki/Snake_case](所有字母大写并且用下划线间隔),例如<code>MAX_PLAYERS</code>


<syntaxhighlight lang="cpp">
<syntaxhighlight lang="cpp">
Line 223: Line 226:
参阅[https://cplusplus.com/reference/cstdio/printf/ printf 文档]查看格式提示符列表。
参阅[https://cplusplus.com/reference/cstdio/printf/ printf 文档]查看格式提示符列表。


=== 玩家迭代 ===
=== 迭代玩家数组 ===


<syntaxhighlight lang="cpp">
<syntaxhighlight lang="cpp">
Line 240: Line 243:
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "wikiprint", "Hello from the ddnet wiki!");
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "wikiprint", "Hello from the ddnet wiki!");
</syntaxhighlight>
</syntaxhighlight>




<span id="Debug_printing"></span>
<span id="Debug_printing"></span>
=== 输出调试结果 ===
=== 调试输出 ===


<syntaxhighlight lang="cpp">
<syntaxhighlight lang="cpp">
Line 268: Line 270:
== 外部资料 ==
== 外部资料 ==


<div lang="en" dir="ltr" class="mw-content-ltr">
* [[Special:MyLanguage/User:Ryozuki|Ryozuki]]:[https://edgarluque.com/blog/ui-code-ddnet/ UI Code in DDraceNetwork]
* [https://edgarluque.com/blog/ui-code-ddnet/ UI Code in DDraceNetwork] by [[Special:MyLanguage/User:Ryozuki|Ryozuki]]
* [[Special:MyLanguage/User:Ryozuki|Ryozuki]][https://edgarluque.com/blog/intro-to-ddnet/ An intro to the DDraceNetwork game source code]
* [https://edgarluque.com/blog/intro-to-ddnet/ An intro to the DDraceNetwork game source code] by [[Special:MyLanguage/User:Ryozuki|Ryozuki]]
* [[Special:MyLanguage/User:Ryozuki|Ryozuki]][https://edgarluque.com/blog/code-conventions-in-ddnet/ Code conventions in DDraceNetwork]
* [https://edgarluque.com/blog/code-conventions-in-ddnet/ Code conventions in DDraceNetwork] by [[Special:MyLanguage/User:Ryozuki|Ryozuki]]
* [[Special:MyLanguage/User:Ryozuki|Ryozuki]][https://edgarluque.com/blog/chat-command-ddracenetwork/ Implementing a chat command in DDraceNetwork]
* [https://edgarluque.com/blog/chat-command-ddracenetwork/ Implementing a chat command in DDraceNetwork] by [[Special:MyLanguage/User:Ryozuki|Ryozuki]]
* [https://codedoc.ddnet.org/ Auto generated docs]
* [https://codedoc.ddnet.org/ Auto generated docs]
* [https://ddnet.org/libtw2-doc/ Technical documentation of Teeworlds file formats and network protocol]
* [https://ddnet.org/libtw2-doc/ Technical documentation of Teeworlds file formats and network protocol]
* [https://heinrich5991.github.io/blog/blog/one-tick-unfreeze The Anatomy of a One Tick Unfreeze]
* [https://heinrich5991.github.io/blog/blog/one-tick-unfreeze The Anatomy of a One Tick Unfreeze]
* [[User:ChillerDragon|ChillerDragon]]:[https://www.youtube.com/playlist?list=PLhJkqAQmOh5LyYOfnMy4PJB6CSZltQyTc Teeworlds programming YouTube tutorial]
* [https://www.youtube.com/playlist?list=PLhJkqAQmOh5LyYOfnMy4PJB6CSZltQyTc Teeworlds programming YouTube tutorial] by ChillerDragon
* [[User:ChillerDragon|ChillerDragon]]:[https://chillerdragon.github.io/teeworlds-protocol/ Teeworlds 0.6/0.7 network protocol documentation]
</div>
 
<span id="About_Tee_Skin_Rendering"></span>
== 关于提交皮肤 ==
 
此部分介绍如何提交皮肤。
 
由 Patiga 提供的各种参数值
特别鸣谢 Jupstar
各部分缩放比例:
    身体-body: 100%
    脚脚-feet: 150%
    眼睛-eyes: 120%
    眨眼-eye blink: 45%
    手手-hand: 93.75%
位置:
    64/64 = 1 = 身体部分的宽高比
    下面给出各部分与边缘距离占总宽或者高的比值
    身体-body: 4/64 上边缘
    脚脚-feet:
        10/64 下边缘
        7/64 左右边缘
    眼睛初始位置:
        0.125 上边缘
        0.05 左右边缘
    眼动范围-eye movement:
        设 dir = 眼睛角度 (辅助线角度), right = 0
        眼睛偏移坐标:
            x: cos(dir) * 0.125
            y: sin(dir) * 0.1
        眼间距:
            x: abs(cos(dir)) * 0.01

Latest revision as of 08:19, 23 May 2024

本文皆在教您如何对 DDNet 开发 ,因为这是一款开源游戏(源代码公开),它依赖于一些善良的人们在空余时间的贡献。


开发环境

截至目前,基于以下原因,我们强烈推荐使用Linux系统进行DDNet开发:

  • 大多数DDNet贡献者使用Linux,使用Linux与之前的开发者交流起来更加方便。
  • 软件包管理更简单,您可以轻松地安装所有需要的库。
  • 本文专注于Linux,还没有涉及Windows。

首先,DDNet由 C++ 语言编写,开发者需要对它相当熟悉,但您也可以在只有基础知识的情况下慢慢学习深入。

学习C++的一些有用资源:

DDNet的源代码使用Git托管,这是一个版本控制系统,也是与多人协作开发的重要工具。

如果您的Linux发行版中还没有git,请安装它,例如在大多数基于debian/ubuntu的发行版中,您可以打开终端,输入:sudo apt install git


获取源代码

源代码位于Github,您没有帐户的情况下可以通过Clone获得源代码,但如果想更改官方源代码,则需要登录账号。

如果您不熟悉git/github,可以在这里学习基础知识: Hello World - Github


安装依赖项

如果您在Linux上,您可以通过阅读DDNet github页面上的自述文件来安装所有需要的依赖项:https://github.com/ddnet/ddnet#dependencies-on-linux--macos

对于Arch Linux:

控制台输入 sudo pacman -S --needed base-devel cmake curl ffmpeg freetype2 git glew glslang gmock libnotify libpng opusfile python rust sdl2 spirv-tools sqlite vulkan-headers vulkan-icd-loader wavpack x264

对于Debian:

控制台输入

sudo 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

编译DDNet

我们使用CMake来控制编译进程,如果你安装完成所有的依赖项,之后只需要简单输入这些命令(确保你在DDNet文件夹下):

mkdir build
cd build
cmake ..
make -j$(nproc)


基本信息

以下是一些基本信息:

  • 目前,源代码是使用C++17标准编译的,但您会看到代码的许多部分更像C,因为只有大多数新代码使用C++17。
  • std::string很少使用,字符数组加system.h方法才是常态。
  • 大多数输入输出代码、格式化和Print都是使用system.h提供的方法完成的。


源代码布局

现在你可以构建DDNet并开始编辑它了。


src/base 目录

由于DDNet是一个跨平台游戏,需要一个抽象层来简化开发,因此该目录包含许多有用的函数来处理这一问题。


src/engine 目录

游戏引擎所在位置,它处理大多数与玩法无关的东西,比如图形、声音、网络等。


src/game 目录

所有玩法的代码所在位置,分为客户端和服务器。


服务器端

这个游戏使用自己的面向对象的实体分级系统,所有其他实体源于主类CEntity,位于src/game/server/e ntity.h目录。

游戏世界在src/game/server/gameworld.h路径下,管理这些实体。

一些重要实体有:

  • CCharacter: 代表一个活着的Tee , 当一个Tee生成时会被实例化,当它死亡时会被删除。
  • CPlayer包含了其他没有关联Tee的信息(昵称、国籍等)。有关玩家在死亡之间的信息,请参阅此项。


客户端

客户端由许多组件构成,都是在src/game/client/component.h中定义的继承CComponent的类:这些组件通过实现视觉方法来提供功能,例如OnInitOnMessage等等。


网络

网络协议几乎由python脚本生成并输出c++代码,例如说,datasrc/network.py定义了所有网络包。


代码规范

代码规范的讨论还在持续:ddnet#2945

目前已经应用了下面的部分:


缩进格式

采用Allman 风格

此风格将控制语句关联的大括号放在下一行并且缩进到相同位置,内部语句则缩进到下一级。

while(x == y)
{
    Something();
    SomethingElse();
}

FinalThing();

类和结构体

必须带有前缀C(由于历史遗留原因有一些结构体没有遵循,例如图形代码部分)或者代表接口的I。新的结构体需要带前缀S

示例:

class CCharacter : public CEntity
{
    // ...
}


枚举和常量

应该采用大蛇式命名法[1](所有字母大写并且用下划线间隔),例如:MAX_PLAYERS

enum
{
	FAKETUNE_FREEZE = 1,
	FAKETUNE_SOLO = 2,
	FAKETUNE_NOJUMP = 4,
	FAKETUNE_NOCOLL = 8,
	FAKETUNE_NOHOOK = 16,
	FAKETUNE_JETPACK = 32,
	FAKETUNE_NOHAMMER = 64,
};


变量命名

  • 变量命名有三个部分:修饰和前缀、名字。
  • 变量命名应该以大写字母开始,除非是单字符例如:ixy
  • 变量可以有多于一个的修饰或前缀,也可以没有。

排列方式:[修饰]_[前缀][名字]


修饰

  • 成员变量mm_MyVariable
  • 静态变量ss_MyStaticVariablems_MyStaticMemberVariable
  • 带外部连接的全局变量ggs_MyGlobalStaticVar


前缀

  • 指针前缀ppMyPointerm_pCharacterppMyPointerToPointer
  • 数组前缀aaMyArrayaBuf
  • 容器(std::vector)前缀vvMyVectorvpvMyVectorOfPointersToVectors
  • 函数前缀fnpfnMyCallbackm_papfnMyPointerToArrayOfCallbacks


常用片段

下面列出经常出现在代码库的代码:


格式文本

char aBuf[128];
str_format(aBuf, sizeof(aBuf), "number: %d", 2);

参阅printf 文档查看格式提示符列表。

迭代玩家数组

for(int i = 0; i < MAX_CLIENTS; i++)
{
    // Server-side
    CPlayer *pPlayer = GameServer()->m_apPlayers[i];
}


输出到游戏控制台

Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "wikiprint", "Hello from the ddnet wiki!");


调试输出

int i = 2;
dbg_msg("wikiprint", "Hello from the ddnet wiki: %d", i);

在客户端翻译文本

Localize 用于在游戏客户端从用户选定的语言文件中获取特定字串的翻译。

DoButton(..., Localize("Connect"), ...);

字符串可以包含格式说明符,翻译文本必须包含同样的格式说明符(这可能产生某些排序不一致的问题)。

char aBuf[128];
str_format(aBuf, sizeof(aBuf), Localize("%d of %d servers"), NumServers, TotalServers);

在调用Localize时依靠一个脚本来扫描识别调用代码,然后收集字符串上传翻译文件。由于此原因,调用Localize 不能包含任何其他代码,否则脚本无法正确识别文本。

// 请勿这样做:
const char *pStr = Localize(Team == TEAM_RED ? "Red team" : "Blue team");

// 应该这样做:
const char *pStr = Team == TEAM_RED ? Localize("Red team") : Localize("Blue team");

外部资料

关于提交皮肤

此部分介绍如何提交皮肤。

由 Patiga 提供的各种参数值
特别鸣谢 Jupstar

各部分缩放比例:
   身体-body: 100%
   脚脚-feet: 150%
   眼睛-eyes: 120%
   眨眼-eye blink: 45%
   手手-hand: 93.75%

位置:
   64/64 = 1 = 身体部分的宽高比
   下面给出各部分与边缘距离占总宽或者高的比值
   身体-body: 4/64 上边缘
   脚脚-feet:
       10/64 下边缘
       7/64 左右边缘
   眼睛初始位置:
       0.125 上边缘
       0.05 左右边缘

   眼动范围-eye movement:
       设 dir = 眼睛角度 (辅助线角度), right = 0
       眼睛偏移坐标:
           x: cos(dir) * 0.125
           y: sin(dir) * 0.1
       眼间距:
           x: abs(cos(dir)) * 0.01