Sprint 2 — Move Players Solution
📌 Что реализуется в задаче move_players второго спринта C++ backend
📖 Подробное описание серверной логики управления движением игрока через REST API
🧠 Почему эта задача важна для развития игрового backend-сервера
✅ Итог
Управление направлением и скоростью собаки игрока
В этой задаче к уже реализованному состоянию игры добавляется endpoint POST /api/v1/game/player/action, который принимает команду движения и меняет speed и dir у собаки игрока
После join_game и game_state сервер уже умеет создавать игрока и возвращать состояние, а теперь игрок может отправлять команды управления
Сервер умеет принимать команды движения и менять направление и скорость собаки
📌 Окружение и каталог решения задачи move_players
📖 Полный путь к папке solution на виртуальной машине
🧠 Когда использовать этот путь при сборке, запуске и редактировании README
✅ Итог
Yandex Cloud / пользователь almusha
/home/almusha/cppbackend/sprint2/problems/move_players/solution
Используется как основной рабочий каталог для редактирования файлов, сборки проекта, запуска сервера и проверки API движения игрока
Путь проекта известен
/home/almusha/cppbackend/sprint2/problems/move_players/solution
📌 Откуда взята основа для реализации задачи move_players
📖 Что именно используется из этого источника
🧠 Почему этот источник нужен для текущего решения
✅ Итог
Предыдущее задание game_state/solution
Берётся уже реализованный сервер с API входа в игру, списком игроков и получением состояния через /api/v1/game/state
move_players продолжает развитие сервера: сначала игрок входит, потом получает состояние, затем отправляет команду движения
Решение построено поверх game_state
Precode нового задания move_players/precode/data
Из precode берётся новая папка data с конфигурацией игры
Конфигурация нужна для чтения скорости собаки: defaultDogSpeed и dogSpeed на карте
Данные задания подключены
Precode нового задания move_players/precode/static
Из precode берётся новая папка static с клиентскими файлами
Статика нужна для браузерного клиента, который отправляет команды движения и отображает состояние
Клиентская статика подключена
/home/almusha/cppbackend/sprint2/problems/game_state/solution
/home/almusha/cppbackend/sprint2/problems/move_players/precode/data
/home/almusha/cppbackend/sprint2/problems/move_players/precode/static
📌 API или часть игровой логики, которая реализована в задаче
📖 Подробное описание поведения
🧠 Какую роль это играет в игровом сервере
✅ Итог
POST /api/v1/game/join
Endpoint принимает имя игрока и id карты, создаёт собаку, создаёт игрока и возвращает authToken с playerId
Базовый вход игрока в игровую сессию, унаследованный из предыдущих задач
Вход в игру работает
GET /api/v1/game/players
Endpoint принимает Bearer token и возвращает список игроков текущей игровой сессии
Позволяет клиенту получить участников своей игровой сессии
Список игроков работает
HEAD /api/v1/game/players
Endpoint работает как GET /players, но возвращает только заголовки без тела ответа
Нужен для корректной поддержки HTTP-метода HEAD
HEAD для players работает
GET /api/v1/game/state
Endpoint принимает Bearer token и возвращает состояние игроков текущей игровой сессии
Позволяет клиенту получить pos, speed и dir собак игроков
Игровое состояние возвращается
HEAD /api/v1/game/state
Endpoint работает как GET /state, но возвращает только заголовки без тела ответа
Позволяет проверять state endpoint без загрузки тела ответа
HEAD для state работает
POST /api/v1/game/player/action
Endpoint принимает команду движения игрока и меняет скорость и направление его собаки
Позволяет игроку управлять персонажем через API
Управление движением реализовано
POST /api/v1/game/join
GET /api/v1/game/players
HEAD /api/v1/game/players
GET /api/v1/game/state
HEAD /api/v1/game/state
POST /api/v1/game/player/action
.
├── CMakeLists.txt
├── Dockerfile
├── README.md
├── conanfile.txt
├── data
│ └── config.json
├── src
│ ├── boost_json.cpp
│ ├── http_server.cpp
│ ├── http_server.h
│ ├── json_loader.cpp
│ ├── json_loader.h
│ ├── logger.cpp
│ ├── logger.h
│ ├── main.cpp
│ ├── model.cpp
│ ├── model.h
│ ├── player_tokens.h
│ ├── players.h
│ ├── request_handler.cpp
│ ├── request_handler.h
│ ├── sdk.h
│ ├── tagged.h
│ └── use_cases.h
└── static
├── abc..html
├── about.html
├── android-chrome-192x192.png
├── android-chrome-512x512.png
├── apple-touch-icon.png
├── assets
│ ├── pug.fbx
│ ├── road_nt.png
│ ├── road_t.png
│ ├── road_tr.png
│ ├── road_v.png
│ └── road_vh.png
├── favicon-16x16.png
├── favicon-32x32.png
├── favicon.ico
├── file with spaces.html
├── game.html
├── game_old.html
├── images
│ └── cube.svg
├── index.html
├── js
│ ├── controls
│ │ └── OrbitControls.js
│ ├── game.js
│ ├── game_map.js
│ ├── helper.js
│ ├── js.cookie.min.js
│ ├── libs
│ │ └── fflate.min.js
│ ├── loaders
│ │ ├── FBXLoader.js
│ │ ├── GLTFLoader.js
│ │ ├── MTLLoader.js
│ │ └── OBJLoader.js
│ ├── three.js
│ ├── three.min.js
│ └── utils
│ └── SkeletonUtils.js
└── site.webmanifest
📌 Что добавлено в задаче move_players
📖 Подробное описание нового поведения
🧠 Для чего это нужно игровому клиенту и серверу
✅ Итог
Управление скоростью собаки
Команда движения меняет вектор скорости speed у собаки игрока
Клиент может отправлять направление движения, а сервер хранит текущую скорость персонажа
Скорость меняется
Управление направлением собаки
Команда движения меняет поле dir у собаки игрока
Клиент может отображать, куда смотрит или движется собака
Направление меняется
Команда остановки
Пустая команда "" устанавливает скорость [0.0, 0.0]
Игрок может остановить собаку
Остановка реализована
Время остановлено
После команды движения меняются только speed и dir, а координаты pos не меняются
В этой задаче управление отделено от tick-логики и обновления координат
Позиция пока не обновляется
Скорость из конфигурации
Скорость берётся из dogSpeed карты, defaultDogSpeed или значения 1.0 по умолчанию
Разные карты могут задавать разную скорость движения
Скорость настраивается
Добавлено управление скоростью и направлением пса.
В этом задании время остановлено.
После команды движения меняются только:
speed
dir
Координаты pos не меняются.
📌 Где задаётся скорость собаки
📖 Подробное описание правила
🧠 Как выбирается итоговая скорость
✅ Итог
defaultDogSpeed в корневом JSON
В корневом JSON может быть поле "defaultDogSpeed": 4.5
Используется как скорость по умолчанию для карт без собственного dogSpeed
Глобальная скорость задана
dogSpeed в конкретной карте
В описании карты может быть поле "dogSpeed": 2.5
Если карта задаёт dogSpeed, именно это значение используется для собак на этой карте
Скорость карты имеет приоритет
Отсутствует dogSpeed
Если у карты нет dogSpeed, используется defaultDogSpeed
Карта наследует глобальную скорость
Используется defaultDogSpeed
Отсутствует defaultDogSpeed
Если нет ни dogSpeed, ни defaultDogSpeed, используется скорость 1.0
Сервер всё равно имеет безопасное значение скорости
Используется скорость 1.0
В корневом JSON может быть:
"defaultDogSpeed": 4.5
В конкретной карте может быть:
"dogSpeed": 2.5
Если dogSpeed отсутствует, используется defaultDogSpeed.
Если defaultDogSpeed отсутствует, используется скорость 1.0.
POST /api/v1/game/player/action
📌 Что делает endpoint POST /api/v1/game/player/action
📖 Подробное описание запроса и ответа
🧠 Какую роль играет в задаче move_players
✅ Итог
Принимает команду движения
Клиент отправляет JSON вида {"move":"R"}
Сервер понимает, куда игрок хочет направить собаку
Команда принимается
Проверяет Bearer token
Запрос должен содержать Authorization: Bearer <token>
Сервер определяет игрока, его сессию и собаку
Игрок найден
Меняет speed
В зависимости от команды сервер выставляет вектор скорости
Это состояние затем возвращается через /api/v1/game/state
Скорость обновлена
Меняет dir
Для команд L, R, U, D сервер обновляет направление
Направление отражает последнюю команду движения
Направление обновлено
Возвращает пустой JSON
При успехе ответ равен {}
Клиенту достаточно знать, что команда принята
Успешный ответ простой
POST /api/v1/game/player/action
Content-Type: application/json
Authorization: Bearer <token>
📌 Значение поля move
📖 Что означает команда
🧠 Как влияет на направление собаки
✅ Итог
"L"
Движение влево
Направление становится L
Собака направлена влево
"R"
Движение вправо
Направление становится R
Собака направлена вправо
"U"
Движение вверх
Направление становится U
Собака направлена вверх
"D"
Движение вниз
Направление становится D
Собака направлена вниз
""
Остановка
Скорость становится нулевой, направление может оставаться последним или обрабатываться как остановка по логике решения
Собака останавливается
"L" → влево
"R" → вправо
"U" → вверх
"D" → вниз
"" → остановка
📌 Команда движения при скорости карты s
📖 Какой вектор скорости устанавливается
🧠 Что означает этот вектор
✅ Итог
"L"
[-s, 0.0]
Движение по оси X влево
Скорость влево задана
"R"
[s, 0.0]
Движение по оси X вправо
Скорость вправо задана
"U"
[0.0, -s]
Движение по оси Y вверх
Скорость вверх задана
"D"
[0.0, s]
Движение по оси Y вниз
Скорость вниз задана
""
[0.0, 0.0]
Полная остановка без движения по X и Y
Скорость остановлена
Если скорость карты равна s:
"L" → [-s, 0.0]
"R" → [s, 0.0]
"U" → [0.0, -s]
"D" → [0.0, s]
"" → [0.0, 0.0]
📌 Что происходит со временем и координатами в этой задаче
📖 Подробное описание поведения
🧠 Почему координаты пока не меняются
✅ Итог
Время остановлено
В этой задаче нет tick-обновления состояния по времени
Сервер только принимает команду движения, но не продвигает модель во времени
Tick-логика ещё не используется
Меняется speed
После команды движения обновляется скорость собаки
Клиент через /state видит, с какой скоростью должна двигаться собака
Speed меняется
Меняется dir
После команды движения обновляется направление собаки
Клиент через /state видит направление движения
Dir меняется
Не меняется pos
Координаты остаются прежними после команды движения
Изменение позиции будет связано с управлением временем в следующих задачах
Position пока не меняется
В этом задании время остановлено.
После команды движения меняются только:
speed
dir
Координаты pos не меняются.
📌 Ошибка endpoint POST /api/v1/game/player/action
📖 Когда возникает
🧠 HTTP-статус
✅ Итог
invalidArgument
Тело запроса некорректное, JSON неправильный, поле move отсутствует или содержит недопустимое значение
400 Bad Request
Невалидная команда отклоняется
invalidToken
Заголовок Authorization отсутствует, не начинается с Bearer или имеет некорректный формат
401 Unauthorized
Запрос без корректного токена отклоняется
unknownToken
Токен имеет правильный формат, но сервер не знает такого игрока
401 Unauthorized
Неизвестный токен отклоняется
invalidMethod
Для endpoint /api/v1/game/player/action используется неподдерживаемый HTTP-метод
405 Method Not Allowed
Неверный метод отклоняется
400 invalidArgument
401 invalidToken
401 unknownToken
405 invalidMethod
📌 Шаг сборки проекта move_players/solution
💻 Команда
📖 Что делает команда
✅ Итог
Перейти в каталог solution
cd /home/almusha/cppbackend/sprint2/problems/move_players/solution
Открывает корневую папку решения задачи move_players
Каталог выбран
Удалить старую сборку
rm -rf build
Полностью очищает предыдущие CMake/Conan-файлы сборки
Сборка очищена
Создать новую папку build
mkdir build
Создаёт отдельный каталог для сборочных файлов
Папка build создана
Перейти в build
cd build
Дальнейшие команды выполняются из build
Каталог build открыт
Активировать Conan venv
source /home/almusha/conan-venv/bin/activate
Включает окружение Conan
Conan доступен
Установить зависимости
conan install .. -s compiler.libcxx=libstdc++11 -s build_type=Release --build=missing
Загружает и собирает недостающие зависимости проекта
Зависимости установлены
Сконфигурировать CMake
cmake .. -DCMAKE_BUILD_TYPE=Release
Генерирует Makefile для Release-сборки
CMake настроен
Собрать проект
cmake --build .
Собирает исполняемый файл game_server
Сервер собран
cd /home/almusha/cppbackend/sprint2/problems/move_players/solution
rm -rf build
mkdir build
cd build
source /home/almusha/conan-venv/bin/activate
conan install .. -s compiler.libcxx=libstdc++11 -s build_type=Release --build=missing
cmake .. -DCMAKE_BUILD_TYPE=Release
cmake --build .
📌 Что нужно для запуска game_server в задаче move_players
📖 Подробное описание
🧠 Почему этот аргумент важен
✅ Итог
Исполняемый файл ./bin/game_server
Запускается из папки build после успешной сборки
Это главный бинарник игрового сервера
Сервер запускается
--config-file
Указывает путь к data/config.json внутри move_players/solution
Сервер загружает карту, параметры мира и скорость собак
Конфиг найден
--www-root
Указывает путь к папке static внутри move_players/solution
Сервер отдаёт браузерный клиент, JavaScript, модели и изображения
Статика найдена
cd /home/almusha/cppbackend/sprint2/problems/move_players/solution/build
./bin/game_server \
/home/almusha/cppbackend/sprint2/problems/move_players/solution/data/config.json \
/home/almusha/cppbackend/sprint2/problems/move_players/solution/static
📌 Проверка POST /api/v1/game/join перед командой движения
💻 Команда
📖 Что проверяется
✅ Итог
Join с корректным JSON
curl -i -X POST ... /api/v1/game/join
Проверяется создание игрока, собаки, токена и playerId
Join работает
Заголовок Content-Type
-H "Content-Type: application/json"
Сервер понимает, что тело запроса является JSON
JSON принят
Тело запроса
{"userName":"Scooby Doo","mapId":"map1"}
Передаётся имя игрока и id карты
Данные входа отправлены
curl -i -X POST http://127.0.0.1:8080/api/v1/game/join \
-H " Content-Type: application/json" \
-d ' {"userName":"Scooby Doo","mapId":"map1"}'
Проверка команды движения
📌 Проверка POST /api/v1/game/player/action
💻 Команда
📖 Что проверяется
✅ Итог
Сохранить token
TOKEN="сюда_вставить_authToken"
Токен из ответа /join сохраняется для отправки команды движения
Token подготовлен
Отправить команду вправо
curl -i -X POST ... /api/v1/game/player/action -d '{"move":"R"}'
Проверяется, что сервер принимает команду движения и меняет speed и dir
Action работает
Проверить state
curl -i ... /api/v1/game/state
Проверяется, что состояние собаки теперь содержит обновлённые скорость и направление
State показывает изменения
TOKEN=" сюда_вставить_authToken"
curl -i -X POST http://127.0.0.1:8080/api/v1/game/player/action \
-H " Content-Type: application/json" \
-H " Authorization: Bearer $TOKEN " \
-d ' {"move":"R"}'
curl -i http://127.0.0.1:8080/api/v1/game/state \
-H " Authorization: Bearer $TOKEN "
📌 Что добавлено в решении move_players
📖 Подробное описание результата
🧠 Почему это важно для дальнейших задач sprint2
✅ Итог
Endpoint действия игрока
Реализован POST /api/v1/game/player/action, который принимает команду движения
Игрок теперь может управлять собакой через API
Action endpoint реализован
Управление скоростью
Команды L, R, U, D, "" меняют вектор speed
Сервер хранит направление будущего движения персонажа
Speed обновляется
Управление направлением
Команды движения меняют dir собаки
Клиент может видеть, куда направлен персонаж
Dir обновляется
Конфигурация скорости
Поддержаны dogSpeed, defaultDogSpeed и fallback 1.0
Скорость можно задавать глобально или отдельно для карты
Скорость настраивается
Остановка собаки
Пустая команда "" устанавливает скорость [0.0, 0.0]
Игрок может остановить персонажа
Остановка работает
Состояние без tick-логики
После команды меняются только speed и dir, а pos не меняется
Задача отделяет команды движения от обновления координат во времени
Позиция пока стабильна
Ошибки API
Поддержаны invalidArgument, invalidToken, unknownToken, invalidMethod
Некорректные запросы получают правильные ответы
Ошибки обработаны
Сервер теперь умеет менять направление и скорость пса по команде игрока.