1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
|
# Вступительное слово
## Что делать
- - -
Найти в глобальном поиске <https://groups.google.com> нашу группу
yuydev@googlegroups.com и подать в неё заявку на вступление. После этого в гугл
диске появится директория Yuydev в которой можно создавать и сохранять основные
документы/ассеты связанные с игрой.
Также в планах было попробовать
[парное программирование](https://ru.wikipedia.org/wiki/Парное_программирование),
так что почитайте что это вообще такое и как происходит.
## Про архитектуру движка
- - -
Очень настоятельно рекомендую почитать что-то про
[ECS](https://en.wikipedia.org/wiki/Entity_component_system).
Если вкратце --- основные термины:
- Entity (Объект): по факту является уникальным идентификатором объекта, а
именно --- целым числом, которое является индексом в списке всех объектов;
- Component (Компонент): структура с некоторыми данными в которых содержится
состояние объекта. Например, в компоненте `Transform` могут содержаться
координаты объекта, а в компоненте `Collider` --- размеры коллайдера;
- System (Система): какая-то функция, которая изменяет состояние объекта с
определёнными компонентами. Например, система `movePlayer` может обновлять
состояние объектов, у которых есть компоненты `Transform` и `Player`, а
система `moveEnemy` --- `Transform` и `Enemy`.
Идейные вдохновители:
- Unity 3D
- <https://github.com/saintruler/brandNewEngine>
## Стек технологий
- - -
Игра и движок будут писаться на C++, а проект собираться с помощью make
(**не cmake!!!**). В качестве IDE для разработки стоит выбрать Jetbrains CLion,
а про Visual Studio забыть. Студенческую лицензию для CLion можно получить на
сайте [Jetbrains](https://www.jetbrains.com/shop/eform/students). Если
активирована почта на домене sgu.ru, то можно использовать её и получить
лицензию за несколько минут. Иначе, можно использовать студак во вкладке
Official Document, но тогда придётся подождать несколько дней.
Почитать инфу по C++ можно [тут](cpp.html).
Для работы с графикой, со звуком и остальными мультимедийными вещами будет
использоваться библиотека [SFML](https://www.sfml-dev.org/). Для её изучения
можно почитать [туториалы](https://www.sfml-dev.org/tutorials/2.5/) на
официальном сайте. Они на английском языке, но к этому придётся привыкать.
В целом, в данном проекте я рассчитываю на то, что мы будем использовать
минимальное количество внешних библиотек. В идеале --- ограничиться только
SFML. Другие библиотеки стоит добавлять только в самом-самом крайнем случае,
если проблема требует действительно очень большого количества кода и каких-то
продвинутых знаний. На данный момент, единственный кандидат в качестве
дополнительной внешней библиотеки --- это парсер какого-нибудь языка разметки
(например, json).
Для сборки проекта на винде нужно будет установить
[mingw-w64](http://mingw-w64.org/doku.php) и
[GNU make](https://www.gnu.org/software/make/). И после этого каким-то образом
это настроить так, чтобы проект действительно собирался. Пока что этим никто
не занимался, поэтому именно ты --- читатель --- можешь стать первым!
## Оформление в различных частях проекта
- - -
### Оформление кода (будет дополняться)
```
void
someFunctionName(int param1, int param2)
{
int someArray = { 1, 2, 3 };
const std::type_index anotherArray =
{ TYPE(EnemyController)
, TYPE(Transform)
, TYPE(PlayerController
};
if (true || false)
{
callOtherFunction(12345);
}
for (int i = 0; i < 20; ++i)
{
// TODO(andrew): Добавить большее количество обработчиков.
switch (param1)
{
case 1:
{
std::string name = "World"
std::cout << "Hello, " << name << std::endl;
} break;
case 2:
{
// NOTE(andrew): Приветствую только себя потому что могу!
std::string name = "Andrew"
std::cout << "Hi, " << name << std::endl;
} break;
default:
{
std::cout << "Greeting is undefined" << std::endl;
} break;
}
}
}
```
Моменты, на которые необходимо обратить внимание:
- В названиях используется [CamelCase](https://ru.wikipedia.org/wiki/CamelCase);
- Все фигурные скобки находятся на отдельной строке;
- Тип возвращаемого значения функции находится на отдельной строке;
- Блоки кода обозначаются **везде**, даже в ифе с одной командой;
- Немного необычное оформление кейсов в свитче;
- **Забудьте про using namespace std**;
- Длина строки не превышает 80 символов (в некоторых случаях можно позволить
120 символов, но эти случаи рассматриваются отдельно в каждом случае);
- Оформление литералов массивов в случае, если элементы умещаются в одну
строку и в случае, когда не умещаются (аналогичное оформление применяется к
параметрам функций);
- Комментарии на русском языке.
Также можно заметить, что в комментариях есть конструкции `TODO(имя)` и
`NOTE(имя)`. Имя указывает только на автора комментария, а не на того, кто
это будет чинить. Нужно это для того, чтобы можно было найти автора и спросить
его, если не совсем понятна проблема или что-то ещё. Комментарии такого
вида обычно распознаются в IDE и, например, по TODO-комментариям можно искать
части проекта, в которых следовало бы добавить какие-то вещи, которые могут быть
не обязательны для сборки и работы проекта в данный момент, но могут привести
к неожиданным ошибкам. Например, обработку ошибок/исключений можно отложить
на потом, но чтобы не забыть о том, что такая необходимость существует, надо
добавить комментарий `TODO(имя)` и через двоеточие указать чего именно не
хватает.
### Особенности работы с C++ в этом проекте
Очень желательно везде использовать [Plain Old
Data](https://ru.wikipedia.org/wiki/Простая_структура_данных), то есть обычные
`struct`. Использование наследования и рефлексии запрещено (до тех пор, пока не
найдётся место, где это **действительно** понадобится). Макросы не запрещены,
но их количество следует минимизировать. Если какой-то сложный тип данных
встречается достаточно часто есть возможность рассмотреть вынесение его в
отдельный `typedef`. Глобальных переменных следует избегать, а нужные данные
хранить непосредственно в компонентах.
### Работа с git
При начале работы над новой фичей следует создать новую ветку. У названия
ветки будет какой-то префикс, соответствующий типу того, что в этой ветке
разрабатывается, а после него указывается *очень короткое* описание самой
фичи (два -- три слова). Название ветки полностью нижним регистром, а слова
разделяются тире (!!!). Примеры:
- feature/new-interface;
- feature/player-controller-update;
- fix/physics-system-bug.
Во время разработки фичи можете создавать сколько угодно коммитов, так как
при слиянии с основной веткой будет использоваться squash. Не нужно создавать
огромное количество коммитов на каждый чих, но и не нужно делать один огромный
коммит в котором находятся абсолютно все изменения. Git --- это ваш друг,
который поможет откатиться до предыдущего рабочего коммита, если что-то
непоправимо сломалось (или просто получилось какое-то говно, которое лучше
выкинуть, забыть и начать с начала).
Не рекомендуется работа в одной ветке сразу двух людей, так как это
**неизбежно** приведёт к бесконечным конфликтам при автоматическом слиянии.
В тексте squash-коммита следует указывать что именно было изменено. Первая
строка коммита является чем-то вроде заголовка, а весь остальной текст
следует оформлять в виде Markdown с подробным описанием новых фич.
Текст коммита пишется на русском языке.
Основные команды и процесс работы с нашим репозиторием можно прочитать
[тут](git.html).
## Какие есть задачи
- - -
- Сборка проекта под разные архитектуры
- Debug и Release сборки
- Система логгирования
- Чтение конфигов в каком-то языке разметки
- Выбрать этот язык (кандидаты: toml, yaml, json, ini)
- Движок
- Система компонентов
- Подсистема рендеринга
- Подсистема ввода
- Подсистема сцен
- Подсистема сохранений
- Сериализация/десериализация объектов
- Работа с незапакованными ассетами (Debug build)
- Звуковая подсистема
- Подсистема событий
- Фреймворк для разработки графического интерфейса (а также работа со шрифтами)
- Запаковка ассетов и загрузка этих архивов в собранном проекте (Release build)
- Графический интерфейс для создания сцен
- Игровые механики (придумывание идей и реализация)
- Сюжет
- Графика
- Музыка
|