-
Автор темы
- #1
this is how it looks:
struct RainDrop {
vec2_tpos;
vec2_t target_pos;
float speed;
float length;
float time_since_reset;
};
C++:
#pragma region RAIN
//const int NUM_RAIN_DROPS = (int)settings.max_drops;
const float RAIN_SPEED_MIN = 5.0f;
const float RAIN_SPEED_MAX = 10.0f;
const float RAIN_LENGTH_MIN = 3.0f;
const float RAIN_LENGTH_MAX = 7.0f;
const float RAIN_UPDATE_INTERVAL = 0.02f; // update rain particles every 20 milliseconds
const float RAIN_LERP_SPEED = 0.2f; // lerp rain particles by 20% of the distance between their current and target position
const float RAIN_DRAW_ALPHA = 0.5f;
std::vector<RainDrop> rain_drops;
#include <random>
void initializeRainDrops( ) {
// initialize each rain drop with random position, speed, and length
std::random_devicerd;
std::mt19937 gen( rd( ) );
std::uniform_real_distribution<float> dist_x( 0.0f, static_cast< float >( g_cl.m_width ) );
std::uniform_real_distribution<float> dist_speed( RAIN_SPEED_MIN, RAIN_SPEED_MAX );
std::uniform_real_distribution<float> dist_length( RAIN_LENGTH_MIN, RAIN_LENGTH_MAX );
for ( int i = 0; i < ( int )settings.max_drops; i++ ) {
raindrop drop;
drop.pos = { dist_x( gen ), static_cast< float >( -dist_length( gen ) ) };
drop.target_pos = drop.pos;
drop.speed = dist_speed(gen);
drop length = dist_length(gen);
drop.time_since_reset = 0.0f;
rain_drops.push_back( drop );
}
}
vec2_t lerp( const vec2_t& a, const vec2_t& b, float t ) {
return a * ( 1.0f - t ) + b * t;
}
float last_rain_update_time = 0.0f;
void updateRainDrops( float dt ) {
// initialize each rain drop with random position, speed, and length
std::random_devicerd;
std::mt19937 gen( rd( ) );
std::uniform_real_distribution<float> dist_x( 0.0f, static_cast< float >( g_cl.m_width ) );
std::uniform_real_distribution<float> dist_speed( RAIN_SPEED_MIN, RAIN_SPEED_MAX );
std::uniform_real_distribution<float> dist_length( RAIN_LENGTH_MIN, RAIN_LENGTH_MAX );
for ( auto& drop : rain_drops ) {
drop.time_since_reset += dt;
// if drop has gone off screen or its time since last reset exceeds a threshold, reset to top with new random position, speed, and length
if ( drop.target_pos.y > g_cl.m_height || drop.time_since_reset > 10.0f ) {
drop.pos = { dist_x( gen ), static_cast< float >( -dist_length( gen ) ) };
drop.target_pos = drop.pos;
drop.speed = dist_speed(gen);
drop length = dist_length(gen);
drop.time_since_reset = 0.0f;
}
// update drop position
drop.target_pos.y += drop.speed;
// lerp drop position towards target position
drop.pos = lerp( drop.pos, drop.target_pos, RAIN_LERP_SPEED );
}
}
void snowflake( vec2_t pos, float size, Color color )
{
g_csgo.m_surface->DrawSetColor( color );
float half_size = size / 2.0f;
// Draw 6 lines to create the snowflake shape
g_csgo.m_surface->DrawLine( pos.x - half_size, pos.y, pos.x + half_size, pos.y );
g_csgo.m_surface->DrawLine( pos.x, pos.y - half_size, pos.x, pos.y + half_size );
g_csgo.m_surface->DrawLine( pos.x - half_size, pos.y - half_size, pos.x + half_size, pos.y + half_size );
g_csgo.m_surface->DrawLine( pos.x + half_size, pos.y - half_size, pos.x - half_size, pos.y + half_size );
g_csgo.m_surface->DrawLine( pos.x - half_size, pos.y + half_size / 2, pos.x + half_size, pos.y + half_size / 2 );
g_csgo.m_surface->DrawLine( pos.x - half_size / 2, pos.y - half_size, pos.x - half_size / 2, pos.y + half_size );
}
#define M_PI_4 0.7853981633974483
void snowflake_between_points( vec2_t v0, vec2_t v1, float size, Color color ) {
vec2_t midpoint = ( v0 + v1 ) / 2.f;
float angle = atan2f( v1.y - v0.y, v1.x - v0.x );
float distance = v0.distance_to( v1 );
float half_size = size / 2.0f;
g_csgo.m_surface->DrawSetColor( color );
// draw 6 lines to create the snowflake shape
g_csgo.m_surface->DrawLine( midpoint.x - half_size * cosf( angle ), midpoint.y - half_size * sinf( angle ), midpoint.x + half_size * cosf( angle ), midpoint.y + half_size * sinf( angle ) );
g_csgo.m_surface->DrawLine( midpoint.x - half_size * sinf( angle ), midpoint.y + half_size * cosf( angle ), midpoint.x + half_size * sinf( angle ), midpoint.y - half_size * cosf( angle ) );
g_csgo.m_surface->DrawLine( midpoint.x - half_size * cosf( angle - M_PI_4 ), midpoint.y - half_size * sinf( angle - M_PI_4 ), midpoint.x + half_size * cosf( angle - M_PI_4 ), midpoint.y + half_size * sinf( angle - M_PI_4 ) );
g_csgo.m_surface->DrawLine( midpoint.x + half_size * cosf( angle - M_PI_4 ), midpoint.y + half_size * sinf( angle - M_PI_4 ), midpoint.x - half_size * cosf( angle - M_PI_4 ), midpoint.y - half_size * sinf( angle - M_PI_4 ) );
g_csgo.m_surface->DrawLine( midpoint.x - half_size * cosf( angle + M_PI_4 ), midpoint.y - half_size * sinf( angle + M_PI_4 ), midpoint.x + half_size * cosf( angle + M_PI_4 ), midpoint.y + half_size * sinf( angle + M_PI_4 ) );
g_csgo.m_surface->DrawLine( midpoint.x + half_size * cosf( angle + M_PI_4 ), midpoint.y + half_size * sinf( angle + M_PI_4 ), midpoint.x - half_size * cosf( angle + M_PI_4 ), midpoint.y - half_size * sinf( angle + M_PI_4 ) );
}
void drawRainParticles( ) {
float current_time = g_csgo.m_globals->m_realtime;
float dt = current_time - last_rain_update_time;
if ( dt >= RAIN_UPDATE_INTERVAL ) {
// update rain drop positions
updateRainDrops(dt);
last_rain_update_time = current_time;
}
// draw each rain particle
for ( int i = 0; i < ( int )settings.max_drops; i++ ) {
auto& drop = rain_drops[ i ];
vec2_t start = drop.pos;
vec2_t end = { drop.pos.x, drop.pos.y + drop.length };
vec2_t pos = drop.pos;
switch(settings.draw_rain_or_snow) {
case 0: {
render::line( start, end, settings.snoww );
} break;
case 1: {
snowflake_between_points( start, end, 5, settings.snoww );
} break;
}
}
}
#pragmaendregion
C++:
if ( settings.rain_drop_menu ) {
if (ui::m_details.get_menu_state( ) ) {
initializeRainDrops( );
drawRainParticles( );
}
}