/
moshroom_edu
/
evolution
Обзор
Документация
Войти
/
moshroom_edu
/
evolution
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
master
src/bact_engine/bact.cpp
272 строки
7 KB
mushroom
resurrection
21 май 2026, 17:18
21 май 2026, 17:18
4d88a97
Код
Авторство
О чём код?
#include "bact_engine/bact.h" #include "bact_engine/engine.h" #include "bact_engine/particles.h" #include <SFML/Window/Keyboard.hpp> #include <SFML/Graphics.hpp> namespace b_engine { float bact::accel_x() const { return m_accel_x; } float bact::accel_y() const { return m_accel_y; } void bact::calc_movement() { //f = m*a; a = f/m double milt = 1.0; m_accel_x = ( m_force_x * milt ) / mass(); m_accel_y = ( m_force_y * milt ) / mass(); m_speed_x += m_accel_x; m_speed_x *= g_friction; m_speed_y += m_accel_y; m_speed_y *= g_friction; set_pos( x() + m_speed_x, y() + m_speed_y ); } void bact::add_farticle( object_ptr f ) { if( m_free.size() ) { m_fart[ m_free.back() ] = f; m_free.pop_back(); } else { m_fart.push_back( f ); } } void bact::fart_update() { if( fabs( static_cast< double >( m_force_x ) ) > 0.001 || fabs( static_cast< double >( m_force_y ) ) > 0.001 ) { float px, py; px = -m_force_x * 0.5f + ( ( static_cast< float >( rand() % 2000 ) - 1000.f ) / 2000.f ) + m_speed_x; py = -m_force_y * 0.5f + ( ( static_cast< float >( rand() % 2000 ) - 1000.f ) / 2000.f ) + m_speed_y; auto p = std::make_shared< particle >( px, py ); p->set_pos( x(), y() ); add_farticle( p ); } for( ull i = 0; i < m_fart.size(); ++i ) { if( !m_fart[ i ] ) continue; m_fart[ i ]->update( m_fart ); if( m_fart[ i ]->need_remove() ) { auto temp = m_fart[ i ]; m_fart[ i ] = nullptr; m_free.push_back( i ); temp->on_remove(); } } } void bact::think( const std::vector< object_ptr >& ) { if( sf::Keyboard::isKeyPressed( sf::Keyboard::Up ) ) { m_force_y = -g_max_force; } else if( sf::Keyboard::isKeyPressed( sf::Keyboard::Down ) ) { m_force_y = g_max_force; } else { m_force_y = 0.0f; } if( sf::Keyboard::isKeyPressed( sf::Keyboard::Right ) ) { m_force_x = g_max_force; } else if( sf::Keyboard::isKeyPressed( sf::Keyboard::Left ) ) { m_force_x = -g_max_force; } else { m_force_x = 0.0f; } } void bact::on_draw( sf::RenderWindow& window ) { sf::CircleShape c; c.setFillColor( get_color() ); float r = radius(); c.setRadius( r ); c.setPosition( x(), y() ); c.setOrigin( r, r ); window.draw( c ); } bact::bact() : object( object_type::bact ) { set_mass( g_bact_born_mass ); set_energy( g_bact_born_energy ); set_color( sf::Color( 0, 250, 250 ) ); } bact::~bact() {} void bact::draw( sf::RenderWindow& window ) { on_draw( window ); fart_update(); for( auto& o : m_fart ) { if( o ) { o->draw( window ); } } } void bact::on_update( const std::vector< object_ptr >& ) { static const double max_force = std::sqrt( 50.0 ); double d_x = g_physic_type == physic_type::force ? m_force_x : m_speed_x; double d_y = g_physic_type == physic_type::force ? m_force_y : m_speed_y; assert( !( std::isnan( d_x ) || std::isnan( d_y ) ) ); calc_movement(); delta_energy( g_bact_mass_burn_out_idle + distance( d_x, 0, d_y, 0 ) / max_force * g_bact_mass_burn_out ); if( std::fabs( energy() ) <= g_EPS ) destroy(); } bool bact::check_collision( const object_ptr obj ) { float r = radius() + obj->radius(); r *= r; auto temp = ( sf::Vector2f( x(), y() ) - sf::Vector2f( obj->x(), obj->y() ) ); float sqr_dist = ( temp.x * temp.x + temp.y * temp.y ); return r > sqr_dist; } void bact::on_collision( const object_ptr obj ) { object_type type = obj->type(); switch( type ) { case object_type::leaf: { sf::Vector2f speed( m_speed_x, m_speed_y ); speed = ( speed * mass() ) / ( mass() + obj->mass() ); m_speed_x = speed.x; m_speed_y = speed.y; delta_energy( obj->mass() ); obj->destroy(); break; } case object_type::bact: { auto pos1 = sf::Vector2f( x(), y() ); auto pos2 = sf::Vector2f( obj->x(), obj->y() ); auto vec1 = pos1 - pos2; auto dist = distance( pos1.x, pos1.y, pos2.x, pos2.y ); float real_d = ( radius() + obj->radius() ) + 1.f; assert( dist < real_d ); const float mul = dist / real_d; vec1 *= mul; auto vec2 = pos1 - pos2; auto delta = vec2 - vec1; pos1 = pos1 - ( delta / -2.f ); pos2 = pos2 - ( delta / 2.f ); set_pos( pos1.x, pos1.y ); obj->set_pos( pos2.x, pos2.y ); auto my_speed = resolve_collision( obj ); object_ptr self_ptr( object_ptr(), this ); //No ownership ptr auto other_bact = std::static_pointer_cast< bact >( obj ); auto other_speed = other_bact->resolve_collision( self_ptr ); set_speed( my_speed.x, my_speed.y ); other_bact->set_speed( other_speed.x, other_speed.y ); auto f = sf::Vector2f( m_force_x, m_force_y ) + vec2 * float( std::exp( 1 / dist ) / 9 ); set_force( f.x, f.y ); f = sf::Vector2f( other_bact->m_force_x, other_bact->m_force_y ) + vec2 * -float( std::exp( 1 / dist ) / 9 ); other_bact->set_force( f.x, f.y ); //fvec = fvec + (pos1 -pos2) * exp(1/dis)/9; // std::shared_ptr< bact > o_bact // = std::static_pointer_cast< bact >( obj ); // if(energy() > o_bact->energy()) // { // sf::Vector2f speed(m_speed_x, m_speed_y); // sf::Vector2f o_speed(o_bact->speed_x(), o_bact->speed_y()); // speed = (speed * mass() + o_speed * o_bact->mass()) / // (mass() + o_bact->mass()); // m_speed_x = speed.x; // m_speed_y = speed.y; // obj->destroy(); // delta_energy(o_bact->energy()); // } break; } default: break; } } void bact::on_destroy() {} sf::Vector2f bact::resolve_collision( const object_ptr& obj ) { auto temp = std::static_pointer_cast< bact >( obj ); //const float E = 0.003f; const float m1 = mass(); const float m2 = obj->mass(); const float mass_SUMM = m1 + m2; const float delta_mass = m1 - m2; //? const float const_e = 1.0; const float vx1 = speed_x(); const float vx2 = temp->speed_x(); const float vy1 = speed_y(); const float vy2 = temp->speed_y(); float VX = delta_mass * vx1 + ( const_e * m2 * vx2 ); VX = VX / mass_SUMM; float VY = delta_mass * vy1 + ( const_e * m2 * vy2 ); VY = VY / mass_SUMM; return sf::Vector2f( VX, VY ); } } // namespace b_engine