Development/ru: Difference between revisions
Created page with "Прежде всего, DDNet написан с использованием языка программирования C++, вам необходимо быть достаточно знакомым с ним, но вы также можете знать основы и научиться большему с его помощью." |
Был пропущен символ |
||
(28 intermediate revisions by 3 users not shown) | |||
Line 1: | Line 1: | ||
<languages /> | |||
<languages/> | |||
Цель этой статьи - познакомить вас с DDNet '''''разработкой''''', поскольку это игра с открытым исходным кодом, она полагается на случайных людей, готовых внести в нее свой вклад в свободное время. | Цель этой статьи - познакомить вас с DDNet '''''разработкой''''', поскольку это игра с открытым исходным кодом, она полагается на случайных людей, готовых внести в нее свой вклад в свободное время. | ||
Line 12: | Line 12: | ||
* Эта статья пока не имеет версии для Windows и ориентирована на Linux. | * Эта статья пока не имеет версии для Windows и ориентирована на Linux. | ||
Прежде всего, DDNet написан | Прежде всего, DDNet написан на языке программирования C++, и вам потребуется достаточно глубокое знакомство с ним, но вы также можете узнать основы и научиться большему с его помощью. | ||
Некоторые полезные ресурсы для изучения C++: | Некоторые полезные ресурсы для изучения C++: | ||
Line 39: | Line 39: | ||
Для Arch Linux: | Для Arch Linux: | ||
< | <syntaxhighlight lang="bash"> | ||
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 | |||
</syntaxhighlight> | |||
Для Debian: | |||
<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 67: | Line 74: | ||
== Расположение исходного кода == | == Расположение исходного кода == | ||
Теперь, когда вы можете | Теперь, когда вы можете собрать DDNet, вы можете приступить к его редактированию. | ||
Line 97: | Line 104: | ||
К числу важных структур относятся: | К числу важных структур относятся: | ||
* [https://github.com/ddnet/ddnet/blob/master/src/game/server/entities/character.h CCharacter]: Представляет собой [[Special:MyLanguage/Common_Terminology#Tee|тии]], который | *[https://github.com/ddnet/ddnet/blob/master/src/game/server/entities/character.h CCharacter]: Представляет собой [[Special:MyLanguage/Common_Terminology#Tee|тии]], который жив, он создаётся при спавне тии и удаляется при его смерти. | ||
* [https://github.com/ddnet/ddnet/blob/master/src/game/server/player.h CPlayer] содержит информацию, не относящуюся к [[Common Terminology/fr#Tee|Тии]] (никнейм, флаг, и тд). | |||
Line 103: | Line 111: | ||
==== Клиентская сторона ==== | ==== Клиентская сторона ==== | ||
Клиентская | Клиентская часть состоит из компонентов - классов, наследующих [https://github.com/ddnet/ddnet/blob/master/src/game/client/component.h CComponent], определенных в <code>src/game/client/component.h</code>. Эти компоненты могут реализовывать виртуальные методы, такие как <code>OnInit</code>, <code>OnMessage</code> и т.д, для обеспечения их функциональности. | ||
< | <span id="Networking"></span> | ||
==== | ==== Сетевое взаимодействие ==== | ||
Сетевой протокол в основном генерируется скриптами python, которые выводят код C++, например, <code>datasrc/network.py</code> определяет все сетевые пакеты. | |||
< | <span id="Code_conventions"></span> | ||
== | == Кодовые конвенции == | ||
Продолжающаяся дискуссия о кодовых соглашениях находится здесь: [https://github.com/ddnet/ddnet/issues/2945 ddnet#2945]. | |||
В настоящее время применяется следующее: | |||
< | <span id="Indentation_style"></span> | ||
=== Indentation | === Indentation стиль === | ||
[https://en.wikipedia.org/wiki/Indentation_style#Allman_style Allman style] используется. | |||
[https://en.wikipedia.org/wiki/Indentation_style#Allman_style Allman style] | |||
<blockquote> | <blockquote> | ||
Этот стиль помещает скобку, связанную с управляющим оператором, на следующую строку с отступом на том же уровне, что и управляющий оператор. Утверждения внутри скобок отступают на следующий уровень. | |||
</blockquote> | </blockquote> | ||
<syntaxhighlight lang="cpp"> | <syntaxhighlight lang="cpp"> | ||
while(x == y) | while(x == y) | ||
Line 149: | Line 143: | ||
SomethingElse(); | SomethingElse(); | ||
} | } | ||
FinalThing(); | |||
</syntaxhighlight> | </syntaxhighlight> | ||
< | <span id="Classes_and_Structs"></span> | ||
=== | === Классы и структуры === | ||
Должен иметь префикс <code>C</code> (по устаревшим причинам это игнорируется для структур в некоторых местах, например, в графическом коде) или <code>I</code> для интерфейсов. Новая структуры должны иметь префикс <code>S</code>. | |||
Пример: | |||
<syntaxhighlight lang="cpp"> | <syntaxhighlight lang="cpp"> | ||
class CCharacter : public CEntity | class CCharacter : public CEntity | ||
Line 176: | Line 160: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
< | <span id="Enums_and_constants"></span> | ||
=== | === Перечисления и константы === | ||
Должен быть ''screaming snake case [https://en.wikipedia.org/wiki/Snake_case]'', например: <code>MAX_PLAYERS</code> | |||
<syntaxhighlight lang="cpp"> | <syntaxhighlight lang="cpp"> | ||
enum | enum | ||
Line 200: | Line 179: | ||
}; | }; | ||
</syntaxhighlight> | </syntaxhighlight> | ||
< | <span id="Variable_naming"></span> | ||
=== | === Именование переменных === | ||
* Имена переменных содержат 3 части: классификатор, префикс и имя. | |||
* | * Имена переменных должны начинаться с прописной буквы, если только они не имеют длину в 1 символ без какого-либо префикса или определителя, например: <code>i</code>, <code>x</code>, <code>y</code>. | ||
* | * Переменные могут иметь более 1 классификатора (или нуля) и более 1 префикса (или нуля). | ||
* | |||
Они расположены следующим образом: <code>[qualifiers]_[prefixes][Name]</code> | |||
< | <span id="Qualifiers"></span> | ||
==== | ==== Классификаторы ==== | ||
* <code>m</code> для переменных-членов: <code>m_MyVariable</code>. | |||
* <code>m</code> | * <code>s</code> для статических переменных: <code>s_MyStaticVariable</code>, <code>ms_MyStaticMemberVariable</code>. | ||
* <code>s</code> | * <code>g</code> для глобальных переменных с внешней связью: <code>gs_MyGlobalStaticVar</code>. | ||
* <code>g</code> | |||
< | <span id="Prefixes"></span> | ||
==== | ==== Префиксы ==== | ||
* <code>p</code> для указателей: <code>pMyPointer</code>, <code>m_pCharacter</code>, <code>ppMyPointerToPointer</code>. | |||
* <code>p</code> | * <code>a</code> для массивов: <code>aMyArray</code>, <code>aBuf</code>. | ||
* <code>a</code> | * <code>v</code> для <code>std::vector</code>s: <code>vMyVector</code>, <code>vpvMyVectorOfPointersToVectors</code>. | ||
* <code>v</code> | * <code>fn</code> для функций: <code>pfnMyCallback</code>, <code>m_papfnMyPointerToArrayOfCallbacks</code>. | ||
* <code>fn</code> | |||
< | <span id="Common_snippets"></span> | ||
== | == Общие фрагменты == | ||
Вот список кода, который вы можете часто встретить в кодовой базе: | |||
< | <span id="Formatting_text"></span> | ||
=== | === Форматирование текста === | ||
<syntaxhighlight lang="cpp"> | <syntaxhighlight lang="cpp"> | ||
char aBuf[128]; | char aBuf[128]; | ||
str_format(aBuf, sizeof(aBuf), "number: %d", 2); | str_format(aBuf, sizeof(aBuf), "number: %d", 2); | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Список всех спецификаторов форматирования см. в [https://cplusplus.com/reference/cstdio/printf/ документации по printf]. | |||
=== | === Итерация по всем игрокам === | ||
<syntaxhighlight lang="cpp"> | <syntaxhighlight lang="cpp"> | ||
for(int i = 0; i < MAX_CLIENTS; i++) | for(int i = 0; i < MAX_CLIENTS; i++) | ||
Line 274: | Line 232: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
< | <span id="Printing_to_the_game_console"></span> | ||
=== | === Печать на игровой консоли === | ||
<syntaxhighlight lang="cpp"> | <syntaxhighlight lang="cpp"> | ||
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> | ||
=== | === Отладочная печать === | ||
<syntaxhighlight lang="cpp"> | <syntaxhighlight lang="cpp"> | ||
int i = 2; | int i = 2; | ||
dbg_msg("wikiprint", "Hello from the ddnet wiki: %d", i); | dbg_msg("wikiprint", "Hello from the ddnet wiki: %d", i); | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== Перевод текста в клиенте === | |||
<code>Localize</code> можно использовать в клиенте игры, чтобы получить перевод для определенной строки из языкового файла, выбранного пользователем. | |||
<syntaxhighlight lang="cpp"> | |||
DoButton(..., Localize("Connect"), ...); | |||
</syntaxhighlight>Строка может также содержать спецификаторы формата. Переведенная строка должна содержать те же спецификаторы форматирования.<syntaxhighlight lang="cpp"> | |||
char aBuf[128]; | |||
str_format(aBuf, sizeof(aBuf), Localize("%d of %d servers"), NumServers, TotalServers); | |||
</syntaxhighlight>Скрипт используется для сканирования кода на наличие вызовов <code>Localize</code> и сбора строк для обновления файлов перевода. По этой причине вызов <code>Localize</code> не должен содержать никакого другого кода, иначе скрипт не сможет правильно определить текст. | |||
<syntaxhighlight lang="cpp"> | |||
// НЕ делайте этого: | |||
const char *pStr = Localize(Team == TEAM_RED ? "Red team" : "Blue team"); | |||
// Вместо этого сделайте следующее: | |||
const char *pStr = Team == TEAM_RED ? Localize("Red team") : Localize("Blue team"); | |||
</syntaxhighlight> | |||
<span id="External_resources"></span> | |||
== Внешние ресурсы == | |||
*[https://edgarluque.com/blog/ui-code-ddnet/ Код пользовательского интерфейса в DDraceNetwork] от [[Special:MyLanguage/User:Ryozuki|Ryozuki]] | |||
*[https://edgarluque.com/blog/intro-to-ddnet/ Знакомство с исходным кодом игры DDraceNetwork] от [[Special:MyLanguage/User:Ryozuki|Ryozuki]] | |||
*[https://edgarluque.com/blog/code-conventions-in-ddnet/ Соглашения по коду в DDraceNetwork] от [[Special:MyLanguage/User:Ryozuki|Ryozuki]] | |||
*[https://edgarluque.com/blog/chat-command-ddracenetwork/ Реализация команды чата в DDraceNetwork] от [[Special:MyLanguage/User:Ryozuki|Ryozuki]] | |||
*[https://codedoc.ddnet.org/ Автоматически сгенерированная документация] | |||
*[https://ddnet.org/libtw2-doc/ Техническая документация по форматам файлов Teeworlds и сетевому протоколу] | |||
*[https://heinrich5991.github.io/blog/blog/one-tick-unfreeze Анатомия размораживания одного тика] | |||
*[https://www.youtube.com/playlist?list=PLhJkqAQmOh5LyYOfnMy4PJB6CSZltQyTc YouTube-учебник по программированию Teeworlds] от [[User:ChillerDragon|ChillerDragon]] | |||
*[https://chillerdragon.github.io/teeworlds-protocol/ Документация по сетевому протоколу Teeworlds 0.6/0.7] от [[User:ChillerDragon|ChillerDragon]] | |||
<span id="About_Tee_Skin_Rendering"></span> | |||
== О рендеринге скинов == | |||
В этом разделе описано, как выполнить рендеринг скина тии. | |||
Значения собраны вместе Patiga | |||
Особая благодарность компании Jupstar | |||
Масштабирование сегментов: | |||
* | тело: 100% | ||
* | ноги: 150% | ||
глаза: 120% | |||
* | моргание глаз: 45% | ||
рука: 93,75% | |||
Позиционирование: | |||
64/64 = 1 = ширина или высота сегмента тела | |||
туловище: 4/64 вверх | |||
ноги: | |||
10/64 вниз | |||
7/64 влево/вправо | |||
глаза: | |||
0,125 вверх | |||
0,05 влево/вправо | |||
движение глаз: | |||
dir = угол наклона глаз (угол обзора), правый = 0 | |||
глаза: | |||
x: cos(dir) * 0.125 | |||
y: sin(dir) * 0.1 | |||
каждый глаз (в сторону от другого): | |||
x: abs(cos(dir)) * 0.01 |
Latest revision as of 21:40, 23 September 2024
Цель этой статьи - познакомить вас с DDNet разработкой, поскольку это игра с открытым исходным кодом, она полагается на случайных людей, готовых внести в нее свой вклад в свободное время.
Ваша среда разработки
Крайне рекомендуется установить среду Linux для начала программирования в DDNet по следующим причинам (на данный момент):
- Большинство участников DDNet на самом деле используют Linux для внесения вклада.
- Более простое управление пакетами, вы можете легко установить все необходимые библиотеки и начать вносить свой вклад.
- Эта статья пока не имеет версии для Windows и ориентирована на Linux.
Прежде всего, DDNet написан на языке программирования C++, и вам потребуется достаточно глубокое знакомство с ним, но вы также можете узнать основы и научиться большему с его помощью.
Некоторые полезные ресурсы для изучения C++:
- learncpp.com
- cppreference.com
- Предпочтительная поисковая система
Исходный код 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 python3 rustc spirv-tools
Компиляция 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, определенных в src/game/client/component.h
. Эти компоненты могут реализовывать виртуальные методы, такие как OnInit
, OnMessage
и т.д, для обеспечения их функциональности.
Сетевое взаимодействие
Сетевой протокол в основном генерируется скриптами python, которые выводят код C++, например, datasrc/network.py
определяет все сетевые пакеты.
Кодовые конвенции
Продолжающаяся дискуссия о кодовых соглашениях находится здесь: ddnet#2945.
В настоящее время применяется следующее:
Indentation стиль
Allman style используется.
Этот стиль помещает скобку, связанную с управляющим оператором, на следующую строку с отступом на том же уровне, что и управляющий оператор. Утверждения внутри скобок отступают на следующий уровень.
while(x == y)
{
Something();
SomethingElse();
}
FinalThing();
Классы и структуры
Должен иметь префикс C
(по устаревшим причинам это игнорируется для структур в некоторых местах, например, в графическом коде) или I
для интерфейсов. Новая структуры должны иметь префикс S
.
Пример:
class CCharacter : public CEntity
{
// ...
}
Перечисления и константы
Должен быть screaming snake case [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,
};
Именование переменных
- Имена переменных содержат 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::vector
s: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);
Перевод текста в клиенте
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");
Внешние ресурсы
- Код пользовательского интерфейса в DDraceNetwork от Ryozuki
- Знакомство с исходным кодом игры DDraceNetwork от Ryozuki
- Соглашения по коду в DDraceNetwork от Ryozuki
- Реализация команды чата в DDraceNetwork от Ryozuki
- Автоматически сгенерированная документация
- Техническая документация по форматам файлов Teeworlds и сетевому протоколу
- Анатомия размораживания одного тика
- YouTube-учебник по программированию Teeworlds от ChillerDragon
- Документация по сетевому протоколу Teeworlds 0.6/0.7 от ChillerDragon
О рендеринге скинов
В этом разделе описано, как выполнить рендеринг скина тии.
Значения собраны вместе Patiga Особая благодарность компании Jupstar Масштабирование сегментов: тело: 100% ноги: 150% глаза: 120% моргание глаз: 45% рука: 93,75% Позиционирование: 64/64 = 1 = ширина или высота сегмента тела туловище: 4/64 вверх ноги: 10/64 вниз 7/64 влево/вправо глаза: 0,125 вверх 0,05 влево/вправо движение глаз: dir = угол наклона глаз (угол обзора), правый = 0 глаза: x: cos(dir) * 0.125 y: sin(dir) * 0.1 каждый глаз (в сторону от другого): x: abs(cos(dir)) * 0.01