X-Git-Url: https://git.octo.it/?a=blobdiff_plain;ds=sidebyside;f=src%2Fobject%2Fsnow_particle_system.cpp;h=9dedc5e916a7dc48d3c7fc2d71438639a585b1f7;hb=b699d5a6303e164aab04f1a1d0990b978c15d87d;hp=a6a2addedf9456a38cdce00b462a8d83bf8d84b7;hpb=7bb247564b8236e60384827137e57f328f9614f5;p=supertux.git diff --git a/src/object/snow_particle_system.cpp b/src/object/snow_particle_system.cpp index a6a2added..9dedc5e91 100644 --- a/src/object/snow_particle_system.cpp +++ b/src/object/snow_particle_system.cpp @@ -22,30 +22,52 @@ #include "supertux/globals.hpp" #include "video/drawing_context.hpp" -SnowParticleSystem::SnowParticleSystem() +// TODO: tweak values +namespace SNOW { +static const float SPIN_SPEED = 60.0f; +static const float WIND_SPEED = 30.0f; // max speed of wind will be randf(WIND_SPEED) * randf(STATE_LENGTH) +static const float STATE_LENGTH = 5.0f; +static const float DECAY_RATIO = 0.2f; // ratio of attack speed to decay speed +static const float EPSILON = 0.5f; //velocity changes by up to this much each tick +static const float WOBBLE_DECAY = 0.99f; //wobble decays exponentially by this much each tick +static const float WOBBLE_FACTOR = 4 * .005f; //wobble approaches drift_speed by this much each tick +} + +SnowParticleSystem::SnowParticleSystem() : + state(RELEASING), + timer(), + gust_onset(0), + gust_current_velocity(0) { - snowimages[0] = new Surface("images/objects/particles/snow2.png"); - snowimages[1] = new Surface("images/objects/particles/snow1.png"); - snowimages[2] = new Surface("images/objects/particles/snow0.png"); + snowimages[0] = Surface::create("images/objects/particles/snow2.png"); + snowimages[1] = Surface::create("images/objects/particles/snow1.png"); + snowimages[2] = Surface::create("images/objects/particles/snow0.png"); virtual_width = SCREEN_WIDTH * 2; + timer.start(.01); + // create some random snowflakes size_t snowflakecount = size_t(virtual_width/10.0); for(size_t i=0; ipos.x = systemRandom.randf(virtual_width); - particle->pos.y = systemRandom.randf(SCREEN_HEIGHT); - particle->anchorx = particle->pos.x + (systemRandom.randf(-0.5, 0.5) * 16); - particle->drift_speed = systemRandom.randf(-0.5, 0.5) * 0.3; + particle->pos.x = graphicsRandom.randf(virtual_width); + particle->pos.y = graphicsRandom.randf(SCREEN_HEIGHT); + particle->anchorx = particle->pos.x + (graphicsRandom.randf(-0.5, 0.5) * 16); + // drift will change with wind gusts + particle->drift_speed = graphicsRandom.randf(-0.5, 0.5) * 0.3; particle->wobble = 0.0; particle->texture = snowimages[snowsize]; + particle->flake_size = powf(snowsize+3,4); // since it ranges from 0 to 2 - particle->speed = 1 + (2 - snowsize)/2 + systemRandom.randf(1.8); - particle->speed *= 20; // gravity + particle->speed = 2 * (1 + (2 - snowsize)/2 + graphicsRandom.randf(1.8)) * 10; // gravity + + // Spinning + particle->angle = graphicsRandom.randf(360.0); + particle->spin_speed = graphicsRandom.randf(-SNOW::SPIN_SPEED,SNOW::SPIN_SPEED); particles.push_back(particle); } @@ -54,30 +76,69 @@ SnowParticleSystem::SnowParticleSystem() void SnowParticleSystem::parse(const Reader& reader) { - reader.get("z-pos", z_pos); + z_pos = reader_get_layer (reader, /* default = */ LAYER_BACKGROUND1); } SnowParticleSystem::~SnowParticleSystem() { - for(int i=0;i<3;++i) - delete snowimages[i]; } void SnowParticleSystem::update(float elapsed_time) { + // Simple ADSR wind gusts + + if (timer.check()) { + // Change state + state = (State) ((state + 1) % MAX_STATE); + + if(state == RESTING) { + // stop wind + gust_current_velocity = 0; + // new wind strength + gust_onset = graphicsRandom.randf(-SNOW::WIND_SPEED, SNOW::WIND_SPEED); + } + timer.start(graphicsRandom.randf(SNOW::STATE_LENGTH)); + } + + // Update velocities + switch(state) { + case ATTACKING: + gust_current_velocity += gust_onset * elapsed_time; + break; + case DECAYING: + gust_current_velocity -= gust_onset * elapsed_time * SNOW::DECAY_RATIO; + break; + case RELEASING: + // uses current time/velocity instead of constants + gust_current_velocity -= gust_current_velocity * elapsed_time / timer.get_timeleft(); + break; + case SUSTAINING: + case RESTING: + //do nothing + break; + default: + assert(false); + } + std::vector::iterator i; for(i = particles.begin(); i != particles.end(); ++i) { SnowParticle* particle = (SnowParticle*) *i; float anchor_delta; + // Falling particle->pos.y += particle->speed * elapsed_time; - particle->pos.x += particle->wobble * elapsed_time /* * particle->speed * 0.125*/; - - anchor_delta = (particle->anchorx - particle->pos.x); - particle->wobble += (4 * anchor_delta * 0.05) + systemRandom.randf(-0.5, 0.5); - particle->wobble *= 0.99f; + // Drifting (speed approaches wind at a rate dependent on flake size) + particle->drift_speed += (gust_current_velocity - particle->drift_speed) / particle->flake_size + graphicsRandom.randf(-SNOW::EPSILON,SNOW::EPSILON); particle->anchorx += particle->drift_speed * elapsed_time; + // Wobbling (particle approaches anchorx) + particle->pos.x += particle->wobble * elapsed_time; + anchor_delta = (particle->anchorx - particle->pos.x); + particle->wobble += (SNOW::WOBBLE_FACTOR * anchor_delta) + graphicsRandom.randf(-SNOW::EPSILON, SNOW::EPSILON); + particle->wobble *= SNOW::WOBBLE_DECAY; + // Spinning + particle->angle += particle->spin_speed * elapsed_time; + particle->angle = fmodf(particle->angle, 360.0); } }