00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "object/snow_particle_system.hpp"
00018
00019 #include <math.h>
00020
00021 #include "math/random_generator.hpp"
00022 #include "supertux/globals.hpp"
00023 #include "video/drawing_context.hpp"
00024
00025
00026 namespace SNOW {
00027 static const float SPIN_SPEED = 60.0f;
00028 static const float WIND_SPEED = 30.0f;
00029 static const float STATE_LENGTH = 5.0f;
00030 static const float DECAY_RATIO = 0.2f;
00031 static const float EPSILON = 0.5f;
00032 static const float WOBBLE_DECAY = 0.99f;
00033 static const float WOBBLE_FACTOR = 4 * .005f;
00034 }
00035
00036 SnowParticleSystem::SnowParticleSystem() :
00037 state(RELEASING),
00038 timer(),
00039 gust_onset(0),
00040 gust_current_velocity(0)
00041 {
00042 snowimages[0] = Surface::create("images/objects/particles/snow2.png");
00043 snowimages[1] = Surface::create("images/objects/particles/snow1.png");
00044 snowimages[2] = Surface::create("images/objects/particles/snow0.png");
00045
00046 virtual_width = SCREEN_WIDTH * 2;
00047
00048 timer.start(.01);
00049
00050
00051 size_t snowflakecount = size_t(virtual_width/10.0);
00052 for(size_t i=0; i<snowflakecount; ++i) {
00053 SnowParticle* particle = new SnowParticle;
00054 int snowsize = graphicsRandom.rand(3);
00055
00056 particle->pos.x = graphicsRandom.randf(virtual_width);
00057 particle->pos.y = graphicsRandom.randf(SCREEN_HEIGHT);
00058 particle->anchorx = particle->pos.x + (graphicsRandom.randf(-0.5, 0.5) * 16);
00059
00060 particle->drift_speed = graphicsRandom.randf(-0.5, 0.5) * 0.3;
00061 particle->wobble = 0.0;
00062
00063 particle->texture = snowimages[snowsize];
00064 particle->flake_size = powf(snowsize+3,4);
00065
00066 particle->speed = 2 * (1 + (2 - snowsize)/2 + graphicsRandom.randf(1.8)) * 10;
00067
00068
00069 particle->angle = graphicsRandom.randf(360.0);
00070 particle->spin_speed = graphicsRandom.randf(-SNOW::SPIN_SPEED,SNOW::SPIN_SPEED);
00071
00072 particles.push_back(particle);
00073 }
00074 }
00075
00076 void
00077 SnowParticleSystem::parse(const Reader& reader)
00078 {
00079 z_pos = reader_get_layer (reader, LAYER_BACKGROUND1);
00080 }
00081
00082 SnowParticleSystem::~SnowParticleSystem()
00083 {
00084 }
00085
00086 void SnowParticleSystem::update(float elapsed_time)
00087 {
00088
00089
00090 if (timer.check()) {
00091
00092 state = (State) ((state + 1) % MAX_STATE);
00093
00094 if(state == RESTING) {
00095
00096 gust_current_velocity = 0;
00097
00098 gust_onset = graphicsRandom.randf(-SNOW::WIND_SPEED, SNOW::WIND_SPEED);
00099 }
00100 timer.start(graphicsRandom.randf(SNOW::STATE_LENGTH));
00101 }
00102
00103
00104 switch(state) {
00105 case ATTACKING:
00106 gust_current_velocity += gust_onset * elapsed_time;
00107 break;
00108 case DECAYING:
00109 gust_current_velocity -= gust_onset * elapsed_time * SNOW::DECAY_RATIO;
00110 break;
00111 case RELEASING:
00112
00113 gust_current_velocity -= gust_current_velocity * elapsed_time / timer.get_timeleft();
00114 break;
00115 case SUSTAINING:
00116 case RESTING:
00117
00118 break;
00119 default:
00120 assert(false);
00121 }
00122
00123 std::vector<Particle*>::iterator i;
00124
00125 for(i = particles.begin(); i != particles.end(); ++i) {
00126 SnowParticle* particle = (SnowParticle*) *i;
00127 float anchor_delta;
00128
00129
00130 particle->pos.y += particle->speed * elapsed_time;
00131
00132 particle->drift_speed += (gust_current_velocity - particle->drift_speed) / particle->flake_size + graphicsRandom.randf(-SNOW::EPSILON,SNOW::EPSILON);
00133 particle->anchorx += particle->drift_speed * elapsed_time;
00134
00135 particle->pos.x += particle->wobble * elapsed_time;
00136 anchor_delta = (particle->anchorx - particle->pos.x);
00137 particle->wobble += (SNOW::WOBBLE_FACTOR * anchor_delta) + graphicsRandom.randf(-SNOW::EPSILON, SNOW::EPSILON);
00138 particle->wobble *= SNOW::WOBBLE_DECAY;
00139
00140 particle->angle += particle->spin_speed * elapsed_time;
00141 particle->angle = fmodf(particle->angle, 360.0);
00142 }
00143 }
00144
00145