Разработка

From DDraceNetwork
Revision as of 10:10, 5 July 2023 by Sedonya (talk | contribs) (Created page with "<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 python rustc spirv-tools4 </syntaxhighlight>")

Цель этой статьи - познакомить вас с DDNet разработкой, поскольку это игра с открытым исходным кодом, она полагается на случайных людей, готовых внести в нее свой вклад в свободное время.


Ваша среда разработки

Крайне рекомендуется установить среду Linux для начала программирования в DDNet по следующим причинам (на данный момент):

  • Большинство участников DDNet на самом деле используют Linux для внесения вклада.
  • Более простое управление пакетами, вы можете легко установить все необходимые библиотеки и начать вносить свой вклад.
  • Эта статья пока не имеет версии для Windows и ориентирована на Linux.

Прежде всего, DDNet написан с использованием языка программирования C++, вам необходимо быть достаточно знакомым с ним, но вы также можете знать основы и научиться большему с его помощью.

Некоторые полезные ресурсы для изучения C++:

Исходный код DDNet управляется с помощью Git, системы контроля версий, важного инструмента для совместной работы с несколькими разработчиками.

Если в вашем дистрибутиве Linux еще нет git, обязательно установите его, например, в большинстве дистрибутивов на базе debian/ubuntu: sudo apt install git.


Получение исходного кода

Исходный код находится на Github, вы можете получить исходный код путем клонирования без необходимости иметь учетную запись, но если вы хотите когда-либо внести свои изменения в официальный исходный код, то она вам понадобится.

Если вы не знакомы с git/github, вы можете изучить основы здесь: Hello World - Github.


Установка зависимостей

Если вы работаете на Linux, вы можете установить все необходимые зависимости, прочитав README на странице 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 python rustc spirv-tools4

Компиляция DDNet

Мы используем CMake для управления процессом компиляции, если у вас установлены все зависимости, это так же просто, как выполнить следующие команды (убедитесь, что вы находитесь в папке DDNet):

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


Общая информация

Вот некоторые общие сведения:

  • В настоящее время исходный код скомпилирован в соответствии со стандартом C++17, но вы увидите, что многие части кода больше похожи на C, поскольку только в основном новый код использует материал C++17.
  • std::string используется редко, массивы символов плюс использование system.h методы для их обработки являются нормой.
  • Большая часть кода ввода-вывода, форматирования и печати выполняется с использованием методов, предоставляемых system.h.


Расположение исходного кода

Теперь, когда вы можете создать DDNet, вы можете приступить к его редактированию.


Каталог src/base

Поскольку DDNet является кросс-платформенной игрой, для облегчения разработки необходим слой абстракции над ней, этот каталог содержит множество полезных функций для этого.


Каталог src/engine

Здесь находится игровой движок, он обрабатывает большинство вещей, не связанных с игровым процессом, таких как графика, звук, сеть и т.д.


Каталог src/game

Весь код, связанный с геймплеем, находится здесь, разделенный на клиентский и серверный.


Серверная сторона

Эта игра использует свою собственную иерархическую объектно-ориентированную систему сущностей, основным классом, от которого происходят все остальные сущности, является CEntity located in src/game/server/entity.h.

Эти сущности управляются игровым миром, расположенным здесь src/game/server/gameworld.h.

К числу важных структур относятся:

  • CCharacter: Представляет собой тии, который является живым, он создается при порождении тии и удаляется при его смерти. Информацию о том, как игрок сохраняется между смертями, см. в CPlayer.


Клиентская сторона

Клиентская сторона состоит из компонентов, это классы, которые наследуют CComponent: Эти компоненты могут реализовывать виртуальные методы, такие как OnInit, OnMessage и т.д., чтобы обеспечить их функциональность.


Сетевое взаимодействие

Сетевой протокол в основном генерируется скриптами python, которые выводят код C++, например, datasrc/network.py определяет все сетевые пакеты.


Кодовые конвенции

Продолжающаяся дискуссия о кодовых соглашениях находится здесь: ddnet#2945.

В настоящее время применяется следующее:


Indentation стиль

Allman style используется.

Этот стиль помещает скобку, связанную с управляющим оператором, на следующую строку с отступом на том же уровне, что и управляющий оператор. Утверждения внутри скобок отступают на следующий уровень.

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

FinalThing();

Классы и структуры

Должен иметь префикс C (по устаревшим причинам это игнорируется для структур в некоторых местах, например, в графическом коде) или I для интерфейсов. Новая структура s должна иметь префикс S.

Пример:

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


Перечисления и константы

Должен быть screaming snake case, например: MAX_PLAYERS

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


Именование переменных

  • Имена переменных содержат 3 части: классификатор, префикс и имя.
  • Имена переменных должны начинаться с прописной буквы, если только они не имеют длину в 1 символ без какого-либо префикса или определителя, например: i, x, y.
  • Переменные могут иметь более 1 классификатора (или нуля) и более 1 префикса (или нуля).

Они расположены следующим образом: [qualifiers]_[prefixes][Name]


Квалификаторы

  • m для переменных-членов: m_MyVariable.
  • s для статических переменных: s_MyStaticVariable, ms_MyStaticMemberVariable.
  • g для глобальных переменных с внешней связью: gs_MyGlobalStaticVar.


Префиксы

  • p для указателей: pMyPointer, m_pCharacter, ppMyPointerToPointer.
  • a для массивов: aMyArray, aBuf.
  • v для std::vectors: vMyVector, vpvMyVectorOfPointersToVectors.
  • fn для функций: pfnMyCallback, m_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);

Translating text in the client

Localize can be used in the game client to get the translation for a specific string from the language file selected by the user.
DoButton(..., Localize("Connect"), ...);
The string can also contain format specifiers. The translated string must contain the same format specifiers.
char aBuf[128];
str_format(aBuf, sizeof(aBuf), Localize("%d of %d servers"), NumServers, TotalServers);
A script is used to scan the code for calls to Localize and collect the strings to update the translation files. For this reason, the call to Localize must not contain any other code, or the script cannot determine the text correctly.
// Do NOT do this:
const char *pStr = Localize(Team == TEAM_RED ? "Red team" : "Blue team");
</div>

<div lang="en" dir="ltr" class="mw-content-ltr">
// Do this instead:
const char *pStr = Team == TEAM_RED ? Localize("Red team") : Localize("Blue team");

Внешние ресурсы