/
tytyshka
/
Typing_Race_Game
Обзор
Документация
Войти
/
tytyshka
/
Typing_Race_Game
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
game_instance.cpp
237 строк
6 KB
tytyshka
Client
16 дек 2025, 21:37
16 дек 2025, 21:37
f770ab5
Код
Авторство
О чём код?
#include "game_instance.h" // #include "room.h" #include "utils.h" #include <chrono> #include <random> #include <algorithm> #include <cstdlib> #include "json.hpp" #include "player_session.h" #include "db.h" #include <iostream> using json = nlohmann::json; extern DBManager* g_db; static std::string gen_id() { static const char* hex = "0123456789abcdef"; std::string s(8, '0'); for (int i = 0; i < 8; i++) s[i] = hex[rand() % 16]; return s; } GameInstance::GameInstance(ms_t duration_ms) : duration_ms_(duration_ms), running_(false), start_ts_(0) { } GameInstance::~GameInstance() { stop(); } void GameInstance::start() { running_ = true; start_ts_ = now_ms(); loop_thread_ = std::thread(&GameInstance::game_loop, this); } void GameInstance::stop() { if (!running_) return; running_ = false; if (loop_thread_.joinable()) loop_thread_.join(); finish_game(); } void GameInstance::add_player(PlayerSession* p) { std::lock_guard<std::mutex> lock(mutex_); players_.push_back(p); } void GameInstance::remove_player(PlayerSession* p) { std::lock_guard<std::mutex> lock(mutex_); players_.erase( std::remove(players_.begin(), players_.end(), p), players_.end() ); } void GameInstance::game_loop() { using namespace std::chrono; auto last_spawn = steady_clock::now(); while (running_) { std::this_thread::sleep_for(10ms); auto now = steady_clock::now(); // spawn new letter every 1 second if (duration_cast<milliseconds>(now - last_spawn).count() > 1000) { spawn_object(); last_spawn = now; } // tick TTL std::vector<std::string> to_remove; { std::lock_guard<std::mutex> lock(mutex_); for (auto& kv : objects_) { GameObject& obj = kv.second; if (!obj.active) continue; obj.ttl_ms -= 10; if (obj.ttl_ms <= 0) { obj.active = false; to_remove.push_back(kv.first); } } } for (auto& id : to_remove) despawn_object(id); // check duration if (duration_ms_ > 0 && (now_ms() - start_ts_) >= duration_ms_) { running_ = false; break; } } // stop -> cleanup and finalize finish_game(); } void GameInstance::spawn_object() { GameObject obj; obj.id = gen_id(); obj.ttl_ms = 3000; obj.letter = 'A' + (rand() % 26); obj.spawn_ts_ms = now_ms(); { std::lock_guard<std::mutex> lock(mutex_); objects_[obj.id] = obj; } json msg = { {"type", "SPAWN"}, {"payload", { {"id", obj.id}, {"char", std::string(1, obj.letter)}, {"ttl", obj.ttl_ms}, {"spawn_ts", obj.spawn_ts_ms} }} }; std::lock_guard<std::mutex> lock(mutex_); for (auto it = players_.begin(); it != players_.end(); ) { if (!(*it)->send_json(msg)) { it = players_.erase(it); } else { ++it; } } } void GameInstance::despawn_object(const std::string& id) { json msg = { {"type", "DESPAWN"}, {"payload", {{"id", id}}} }; std::lock_guard<std::mutex> lock(mutex_); for (auto it = players_.begin(); it != players_.end(); ) { if (!(*it)->send_json(msg)) { it = players_.erase(it); } else { ++it; } } objects_.erase(id); } void GameInstance::handle_keypress(PlayerSession* player, char key) { std::string remove_id; bool hit = false; { std::lock_guard<std::mutex> lock(mutex_); for (auto& kv : objects_) { GameObject& obj = kv.second; if (!obj.active) continue; if (obj.letter == key) { obj.active = false; remove_id = kv.first; hit = true; PlayerInfo info = player->get_info(); info.score++; player->set_info(info); break; } } } if (!hit) { // optional: send MISS json m = { {"type","MISS"}, {"payload", { {"char", std::string(1, key)} }} }; player->send_json(m); return; } // notify all players about deletion despawn_object(remove_id); // notify player about hit (score) json msg = { {"type", "HIT"}, {"payload", { {"id", remove_id}, {"score", player->get_info().score} }} }; player->send_json(msg); } void GameInstance::finish_game() { // broadcast final scores json scores = json::array(); { std::lock_guard<std::mutex> lock(mutex_); for (auto p : players_) { PlayerInfo info = p->get_info(); json entry = { {"player_id", info.player_id}, {"username", info.username}, {"score", info.score} }; scores.push_back(entry); // save to DB (if available) if (g_db) { g_db->save_score(info.player_id, info.username, info.score); } } } json msg = { {"type","GAME_FINISHED"}, {"payload", { {"scores", scores} }} }; std::lock_guard<std::mutex> lock(mutex_); for (auto it = players_.begin(); it != players_.end(); ) { if (!(*it)->send_json(msg)) { it = players_.erase(it); } else { ++it; } } }