開發

From DDraceNetwork
Revision as of 08:50, 22 April 2023 by FuzzyBot (talk | contribs) (Updating to match new version of source page)

本文皆在教你如何對 DDNet 開發 ,因為這是一款開源遊戲(源代碼公開),它依賴於一些善良的人們來用他們的放鬆時間貢獻。


你的開發環境

截至目前,處於一下原因,我們強烈建議使用Linux環境在DDNet中開發:

  • 大多數DDNet貢獻者實際上使用Linux來貢獻。
  • 更容易的軟件包管理,您可以輕鬆地安裝所有需要的庫並開始貢獻。
  • 本文還沒有Windows版本,主要關注Linux。

首先,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-在linux上--macos

對於Arch Linux:

控制台輸入 sudo pacman -S --needed base-devel cmake curl freetype2 git glew gmock libnotify opusfile python sdl2 sqlite wavpack


編譯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/Entity.h中。

這些實體由位於此處的遊戲世界管理src/game/server/gameworld.h

一些重要實體有:

CCharacter: 代表着一個tee 是活着的, 當一個tee產生時它被實例化,當它死亡時它被刪除。有關玩家在死亡之間的信息,請參閱CPlayer.


客戶端

The client side is made up of components, these are classes that inherit CComponent: These components can implement the virtual methods such as OnInit, OnMessage, etc. to provide their functionality.


Networking

The network protocol is mostly generated by python scripts that output C++ code, for example, datasrc/network.py defines all network packets.


Code conventions

The ongoing discussion on code conventions is located here: ddnet#2945

Currently, the following applies:


Indentation style

Allman style is used.

This style puts the brace associated with a control statement on the next line, indented to the same level as the control statement. Statements within the braces are indented to the next level.

while(x == y)
{
    Something();
    SomethingElse();
}
</div>

<div lang="en" dir="ltr" class="mw-content-ltr">
Finalthing();


Classes and Structs

Must be prefixed by C (for legacy reasons this is ignored for structs in some places, such as in graphics code) or I for interfaces. New structs should be prefixed by S.

Example:

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


Enums and constants

Should be screaming snake case, for example: MAX_PLAYERS

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


Variable naming

  • The names of variables contain 3 parts: qualifier, prefix and name.
  • Variable names should start with uppercase unless they are 1 char long without any prefix or qualifier, for example: i, x, y.
  • Variables can have more than 1 qualifier (or zero) and more than 1 prefix (or zero).

These are laid out like this: [qualifiers]_[prefixes][Name]


Qualifiers

  • m for member variables: m_MyVariable.
  • s for static variables: s_MyStaticVariable, ms_MyStaticMemberVariable.
  • g for global variables with external linkage: gs_MyGlobalStaticVar.


Prefixes

  • p for pointers: pMyPointer, m_pCharacter, ppMyPointerToPointer.
  • a for arrays: aMyArray, aBuf.
  • v for std::vectors: vMyVector, vpvMyVectorOfPointersToVectors.
  • fn for functions: pfnMyCallback, m_papfnMyPointerToArrayOfCallbacks.


Common snippets

Here is a list of code that you may frequently see across the codebase:


Formatting text

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


Iterating over all players

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


Printing to the game console

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


Debug printing

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


External resources