Chest — это современная игра и одновременно образовательный мини-движок на C++ с архитектурой Entity-Component-System (ECS).
Проект ставит целью:
- Создать простую, гибкую и расширяемую архитектуру, не зависящую от конкретных низкоуровневых библиотек (SFML, Box2D).
- Получить удобную платформу для экспериментов с игровым кодом, ИИ, физикой, редакторами и визуализацией.
- Сделать качественное учебное и “боевое” MVP с понятным кодом и прозрачной архитектурой.
- Жанр игры: топ-даун или 2D-action (пример: герой, монстры, инвентарь, прокачка, генерация карт).
- Минимальный MVP:
- Игрок (движение WASD, спрайт, здоровье)
- Отрисовка сущностей на карте
- Простое управление
- Инфраструктура для расширения (система сущностей, компонентов и систем)
-
ECS (Entity-Component-System):
- Entity — уникальный объект (например, игрок, моб, предмет). Сам по себе “пустышка” с id, к которой можно прицеплять разные компоненты.
- Component — набор данных (или маленькая логика), которые отвечают за отдельные аспекты поведения/состояния сущности (позиция, рендер, здоровье и т.д.).
- System — класс, который находит все сущности с нужными компонентами и реализует над ними “логику” (например, рендер, физику, обработку управления и пр.).
-
Чистота архитектуры:
- Минимум зависимостей между логикой и внешними фреймворками.
- Все платформенные вызовы (SFML, Box2D) инкапсулированы в системах/адаптерах.
- PositionComponent — позиция (x, y)
- RenderComponent — визуальное отображение (sf::Sprite)
- HealthComponent — здоровье (hp, maxHp)
- (и другие, см. core/Components/)
- InputSystem — управление игроком с клавиатуры
- RenderSystem — отрисовка всех сущностей с компонентом рендера
- WindowSystem — обработка событий платформы, управление окном
- (и другие, см. systems/)
- Всё делится на компоненты, системы и сущности.
- Не завязываемся на SFML или Box2D напрямую в бизнес-логике.
- Любая новая механика реализуется либо как компонент, либо как система.
- Одна задача — один компонент (SRP).
- Все исходники разбиты по папкам:
core/,components/,systems/,adapters/,factories/,utils/. - Код — читаемый, сопровождаемый, с минимальным дублированием.
- Entity, Component, System базовые классы
- Окно, событие закрытия, спрайт игрока
- Система управления (WASD)
- Система отрисовки
- HealthComponent, система урона и смерти
- Примитивный AI для моба
- Система инвентаря и предметов
- Загрузка/сохранение уровня
- Многослойный рендер (UI, карта, сущности)
- Система столкновений и физики (Box2D)
- Система заклинаний/боёвки
- Генерация карт и редактор уровней
- Разделение клиент/сервер (опционально)
- Интеграция тестов, CI/CD
- Entity: уникальный id, к которому “навешиваются” компоненты (сам ничего не умеет).
- Component: набор данных или маленьких функций (например, PositionComponent — x, y; HealthComponent — hp).
- System: отдельный класс, который обновляет все сущности с определёнными компонентами (например, RenderSystem рисует всех, у кого есть Position и Render).
- Собрать проект через CMake (см. инструкции по платформе).
- Положить ресурсы (текстуры, карты) в нужную папку.
- Запустить
chest. - Управлять героем с помощью WASD.
- Вопросы, идеи, баги — кидай в issues или напрямую автору.
- Контрибьюторы приветствуются!
- Всё делается ради фана, развития и кайфа от архитектурно красивого кода :)
Что сейчас делаю:
- Debug system
- Hot reload
a) Физика Добавить PhysicsComponent (скорость, масса, Box2D body и т.д.)
Сделать PhysicsSystem, который обновляет все Entity с этим компонентом, синхронизирует позицию и velocity, вызывает Box2D step.
Связь с рендером — через компонент позиции (как обсуждали раньше).
b) Мобы и контроллеры Добавить фабрики: MobFactory, ControllerFactory (AIController, PlayerController и т.д.)
Компоненты: AIComponent, ControllerComponent (стратегии поведения), HealthComponent, возможно, ещё уникальные фичи для врагов.
В будущем можно сделать систему событий (например, моб реагирует на урон, тревогу, зону игрока).
c) Карта мира Хранить карту как отдельный класс (например, WorldMap или Level), компонент или менеджер.
Добавить систему MapRenderSystem — отрисовывает тайлы, объекты, генерирует меши для стен/пола.
Можно делать карту как tilemap или сетку объектов (подход зависит от жанра).
- Надо инкапсулировать весь SFML в WindowManager он и так уже почти весь там
О событиях должны знать только системы! Entity, components, manager не должны знать о событиях. Все события обрабатываются отдельно определенными системами