1. Основы организации: файловая структура, CMake и разделение на модули
Основы организации: файловая структура, CMake и разделение на модули
Добро пожаловать в курс «Архитектура C++ проектов: Создание редактора уровней на Raylib». Вы здесь, потому что хотите перестать писать «спагетти-код» и научиться создавать инструменты, которые не стыдно показать коллегам и удобно поддерживать самому.
Многие начинающие разработчики сталкиваются с одной и той же проблемой: проект начинается с одного файла main.cpp. Затем появляется player.cpp, потом enemy.cpp, и внезапно папка проекта превращается в свалку из десятков файлов, в которых невозможно ориентироваться. Когда вы пытаетесь написать редактор уровней — инструмент сложный и требующий строгой логики — такой хаос становится фатальным.
В этой статье мы заложим фундамент вашего будущего редактора. Мы не напишем ни строчки игровой логики сегодня, но мы сделаем кое-что более важное: создадим профессиональный каркас проекта.
Почему структура важна?
Представьте, что вы строите дом. Если вы свалите кирпичи, доски и цемент в одну кучу, дом построить не получится. В программировании то же самое. Хорошая структура проекта обеспечивает:
Стандартная файловая структура C++ проекта
В индустрии сложился определенный стандарт организации папок. Мы будем придерживаться современной структуры, разделяющей исходный код, заголовки и сторонние библиотеки.
!Структура папок нашего будущего проекта
Разберем назначение каждой директории:
* src/ (Source): Здесь лежат файлы реализации с расширением .cpp. Это «мясо» вашего проекта.
* include/ (Include): Здесь хранятся заголовочные файлы .h или .hpp. Это публичный интерфейс ваших модулей.
* external/ или libs/: Место для сторонних библиотек (в нашем случае здесь будет жить Raylib).
* assets/: Ресурсы игры — текстуры, звуки, шрифты и файлы конфигурации.
* build/: Папка для артефактов сборки. Мы никогда не коммитим её в git, так как она содержит временные файлы компилятора.
> Хорошая архитектура — это не когда нечего добавить, а когда нечего убрать, и при этом всё лежит на своих местах.
Система сборки: Почему CMake?
Вы упомянули, что хотите «нормальную структуру». В мире C++ это практически синоним использования CMake. Это мета-система сборки, которая генерирует инструкции для нативной системы сборки вашей ОС (Makefile для Linux, Solution для Visual Studio, Project для Xcode).
Базовый CMakeLists.txt
В корне вашего проекта всегда должен лежать файл CMakeLists.txt. Вот минимальный шаблон для нашего редактора:
Однако, просто создать файл недостаточно. Нам нужно подключить библиотеку Raylib.
Интеграция Raylib через CMake
Есть много способов подключить библиотеку: скачать бинарники, использовать git submodules или пакетные менеджеры (Conan, Vcpkg). Для учебного проекта самым надежным и простым способом является FetchContent. Это модуль CMake, который сам скачает исходники Raylib и подключит их к проекту при первой сборке.
Обновим наш CMakeLists.txt:
Что здесь происходит?
FetchContent_Declare: Мы говорим CMake, откуда скачать Raylib.FetchContent_MakeAvailable: CMake скачивает, настраивает и готовит библиотеку к использованию.target_link_libraries: Мы говорим компилятору: «Когда будешь собирать наш редактор, используй код из Raylib».Разделение на модули: Отказ от монолита
Главная ошибка при создании редакторов — писать код игры и код редактора вперемешку. Редактор уровней — это программа, которая использует движок вашей игры, но также имеет свой собственный интерфейс (UI).
Мы разделим проект на три логических слоя:
!Архитектурные слои редактора уровней
Пример организации кода
Вместо того чтобы писать всё в main.cpp, мы создадим класс приложения.
Файл include/app.h:
Файл src/app.cpp:
И, наконец, наш src/main.cpp становится предельно чистым:
Зачем нужен #pragma once?
В примере выше вы видели директиву #pragma once. Это страж включения (header guard). Если вы случайно подключите один и тот же .h файл в нескольких местах (что неизбежно в больших проектах), компилятор без этой директивы попытается объявить одни и те же классы дважды и выдаст ошибку. #pragma once гарантирует, что файл будет обработан компилятором только один раз.
Практическое задание: Сборка проекта
Теперь ваша задача — воспроизвести эту структуру на своем компьютере.
RaylibEditor.src, include, assets.CMakeLists.txt с кодом, приведенным выше (версия с FetchContent).src/main.cpp, src/app.cpp и include/app.h.build.
* Откройте терминал в папке build.
* Выполните cmake ...
* После завершения выполните cmake --build . (или откройте сгенерированный проект в IDE).Если вы увидели окно с надписью "Editor Initialized!" — поздравляю! Вы создали профессиональную заготовку для вашего будущего редактора уровней.
В следующей статье мы займемся наполнением слоя Core и создадим надежную обертку для работы с окном и входными данными, чтобы наш редактор мог корректно обрабатывать события мыши и клавиатуры.