/
moshroom_edu
/
evolution
Обзор
Документация
Войти
/
moshroom_edu
/
evolution
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
master
src/bact_engine/engine.cpp
452 строки
10 KB
mushroom
resurrection
21 май 2026, 17:18
21 май 2026, 17:18
4d88a97
Код
Авторство
О чём код?
#include "bact_engine/engine.h" //TODO Documentation! namespace b_engine { void engine::spawn_player() { auto b = std::make_shared<bact>(); b->set_pos(g_world_width/2, g_world_height/2); add_object(b); } void engine::calc_tps() { ull start = ticks_couner(); std::this_thread::sleep_for(std::chrono::seconds(1)); ull end = ticks_couner(); logger::info("ticks per this second:\033[31m" + std::to_string(end - start)+"\033[0m"); } void engine::pause() { m_paused = !m_paused; logger::info(std::string("Engine ") + (m_paused ? "paused!" : "unpaused!")); } void engine::multithreading() { m_multi_threading = !m_multi_threading; logger::warn(std::string("Engine multithreading ") + (m_multi_threading ? "ON" : "OFF")); } void engine::process_commands() { comm_message::ptr command; if(!m_commands->try_pop(command)) { return; } switch (static_cast<commands>(command->key)) { case commands::exit : { stop(); return; } case commands::pause : { pause(); return; } case commands::calc_tps : { std::thread(std::bind(&engine::calc_tps, this)).detach(); return; } case commands::window_hide : { hide_window(); return; } case commands::window_show : { show_window(); return; } case commands::spawn_player : { spawn_player(); return; } case commands::multithreading : { multithreading(); return; } } } engine::engine() : m_commands(std::make_shared<multithreading::queue<comm_message::ptr>>()) { terminal::add_command( command("show_w", static_cast<int>(commands::window_show), "shows the render window", m_commands ) ); terminal::add_command( command( "hide_w", static_cast<int>(commands::window_hide), "hides the render window", m_commands ) ); terminal::add_command( command( "exit", static_cast<int>(commands::exit), "exit immediately", m_commands ) ); terminal::add_command( command( "sp_plr", static_cast<int>(commands::spawn_player), "spawn the bactery with control by player", m_commands ) ); terminal::add_command( command( "tps", static_cast<int>(commands::calc_tps), "Counts ticks per one second and shows it.", m_commands ) ); terminal::add_command( command("pause", static_cast<int>(commands::pause), "pause/unpause engine", m_commands ) ); terminal::add_command( command("mt", static_cast<int>(commands::multithreading), "ON/OFF multithreading calculation of ANN", m_commands ) ); spawn_player(); m_commands->push( std::make_shared<comm_message>(int(commands::multithreading), "mt")); std::this_thread::sleep_for(std::chrono::seconds(1)); } engine::~engine() { m_is_run = false; } void engine::solve_collisions(object_ptr a, object_ptr b) { if(a->check_collision(b)) { a->on_collision(b); } if(b->check_collision(a)) { b->on_collision(a); } } void engine::thinker( std::vector<std::shared_ptr<object>> * t_objs, size_t from, size_t n, size_t * flag) { size_t to = from + n; for(size_t i = from; i < to; ++i) { object_ptr & obj = (*t_objs)[i]; if(!obj) { continue; } if(obj->need_remove()) { continue; } obj->think(m_objects); } { std::lock_guard<std::mutex>lk(m_jobs_mutexl); *flag += 1; } m_cond.notify_one(); } void engine::make_objects_think( std::vector<std::shared_ptr<object>> &think_objs, size_t per_job, size_t job_count) { size_t count = think_objs.size(); size_t from = 0; size_t job_counter = 0; size_t shift = (per_job * (job_count-1)); m_thread_pool.submit( std::bind( &engine::thinker, this, &think_objs, shift, count - shift, &job_counter ) ); for(size_t i = 0; i < job_count-1; ++i) { m_thread_pool.submit( std::bind( &engine::thinker, this, &think_objs, from, per_job, &job_counter ) ); from += per_job; } // m_thread_pool.submit( // std::bind( // &engine::thinker, // this, // &think_objs, // from, // count - from, // &job_counter // ) // ); //assert(from + per_job == count-1); std::unique_lock<std::mutex>lk(m_jobs_mutexl); m_cond.wait(lk, [&job_counter, job_count](){ return job_count == job_counter; }); } void engine::remove_object(size_t index) { auto temp = m_objects[index]; m_objects[index] = nullptr; m_f_indexes.push_back(index); temp->on_remove(); } void engine::update_objects_multithread() { size_t count = m_objects.size(); static std::vector<std::shared_ptr<object>> think_objs; think_objs.clear(); for(auto & obj:m_objects) { if(obj && obj->type() == object_type::bact) think_objs.push_back(obj); } size_t t_count = think_objs.size(); if(!t_count) { update_objects(); return; } size_t min_obj_count_per_thread = 5; size_t per_job = t_count / m_thread_pool.get_threads_count(); //SHIT per_job = per_job < min_obj_count_per_thread ? t_count / ((t_count >= min_obj_count_per_thread? t_count: min_obj_count_per_thread) / min_obj_count_per_thread) : per_job; size_t job_count = t_count / per_job ; if(job_count ==1) { update_objects(); return; } make_objects_think(think_objs, per_job, job_count); for(size_t i = 0; i < count; ++i) { object_ptr & current = m_objects[i]; if(!current) { continue; } if(current->need_remove()) { remove_object(i); continue; } for(size_t j = i+1; j < count; ++j) { object_ptr & next = m_objects[j]; if(!next) { continue; } if(next->need_remove()) { remove_object(j); continue; } solve_collisions(current, next); } current->update(m_objects); } } void engine::update_objects() { size_t count = m_objects.size(); for(size_t i = 0; i < count; ++i) { object_ptr & current = m_objects[i]; if(!current) { continue; } if(current->need_remove()) { remove_object(i); continue; } current->think(m_objects); for(size_t j = i+1; j < count; ++j) { object_ptr next = m_objects[j]; if(!next) { continue; } if(next->need_remove()) { remove_object(j); continue; } assert(current.get() != next.get()); solve_collisions(current, next); } current->update(m_objects); } } void engine::run() { m_is_run = true; // add_object(std::make_shared<food_generator>()); // add_object(std::make_shared<popul_controller>()) while(m_is_run) { update(); } m_obj_mutex.lock(); m_objects.clear(); m_f_indexes.clear(); m_obj_mutex.unlock(); } void engine::update() { if(m_multi_threading) { update_objects_multithread(); } else { update_objects(); } m_render.draw(m_objects); ++m_ticks_couner; while(m_paused) { process_commands(); std::this_thread::sleep_for(std::chrono::milliseconds(20)); } process_commands(); } engine &engine::instance() { static engine me; return me; } void engine::add_object(const object_ptr &obj) { std::lock_guard<std::mutex> lk(m_obj_mutex); if(!m_f_indexes.size()) { m_objects.push_back(obj); return; } size_t t = m_f_indexes.back(); m_f_indexes.pop_back(); m_objects[t] = obj; } void engine::run_thread() { if(m_is_run) { return; } run(); } }//namespace b_engine