00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "particle.h"
00023 #include <SDL.h>
00024 #include <map>
00025 #include "../game/time.h"
00026 #include "../graphic/sprite.h"
00027 #include "../include/app.h"
00028 #include "../object/objects_list.h"
00029 #include "../tool/resource_manager.h"
00030 #include "../tool/random.h"
00031 #include "../tool/point.h"
00032 #include "../weapon/explosion.h"
00033 #include "../map/map.h"
00034
00035 #include "body_member.h"
00036 #include "teleport_member.h"
00037 #include "bullet.h"
00038 #include "dark_smoke.h"
00039 #include "explosion_smoke.h"
00040 #include "fire.h"
00041 #include "ground_particles.h"
00042 #include "ill_bubble.h"
00043 #include "magic_star.h"
00044 #include "polecat_fart.h"
00045 #include "smoke.h"
00046 #include "star.h"
00047
00048 ParticleEngine global_particle_engine;
00049
00050 Particle::Particle(const std::string &name) :
00051 PhysicalObj(name)
00052 {
00053 SetCollisionModel(true, false, false);
00054 m_initial_time_to_live = 20;
00055 m_check_move_on_end_turn = false;
00056 m_left_time_to_live = 0;
00057 m_last_refresh = Time::GetInstance()->Read();
00058 }
00059
00060 Particle::~Particle()
00061 {
00062 delete image;
00063 }
00064
00065 void Particle::Draw()
00066 {
00067 if (m_left_time_to_live > 0)
00068 image->Draw(GetPosition());
00069 }
00070
00071 void Particle::Refresh()
00072 {
00073 uint time = Time::GetInstance()->Read() - m_last_refresh;
00074
00075 UpdatePosition();
00076
00077 image->Update();
00078
00079 if (time >= m_time_between_scale) {
00080
00081
00082 if (m_left_time_to_live <= 0) return ;
00083
00084 m_left_time_to_live--;
00085
00086 float lived_time = m_initial_time_to_live - m_left_time_to_live;
00087
00088
00089
00090 if((float)lived_time<m_initial_time_to_live/2.0)
00091 {
00092 float coeff = sin((M_PI/2.0)*((float)lived_time/((float)m_initial_time_to_live/2.0)));
00093 image->Scale(coeff,coeff);
00094 SetSize(image->GetSize());
00095 image->SetAlpha(1.0);
00096 }
00097 else
00098 {
00099 float alpha = 1.0 - sin((M_PI/2.0)*((float)lived_time-((float)m_initial_time_to_live/2.0))/((float)m_initial_time_to_live/2.0));
00100 image->Scale(1.0,1.0);
00101 image->SetAlpha(alpha);
00102 }
00103 m_last_refresh = Time::GetInstance()->Read() ;
00104 }
00105 }
00106
00107 bool Particle::StillUseful()
00108 {
00109 return (m_left_time_to_live > 0);
00110 }
00111
00112
00113
00114 ParticleEngine::ParticleEngine(uint time)
00115 {
00116 m_time_between_add = time ;
00117 m_last_refresh = Time::GetInstance()->Read();
00118 }
00119
00120
00121 void ParticleEngine::AddPeriodic(const Point2i &position, particle_t type,
00122 bool upper,
00123 double angle, double norme)
00124 {
00125
00126 uint time = Time::GetInstance()->Read() - m_last_refresh;
00127 uint tmp = Time::GetInstance()->Read();
00128
00129 uint delta = uint(m_time_between_add * double(randomObj.GetLong(3,40))/10);
00130 if (time >= delta) {
00131 m_last_refresh = tmp;
00132 ParticleEngine::AddNow(position, 1, type, upper, angle, norme);
00133 }
00134 }
00135
00136
00137
00138
00139 std::list<Particle*> ParticleEngine::lst_particles;
00140 Sprite* ParticleEngine::particle_sprite[particle_spr_nbr];
00141
00142 void ParticleEngine::Init()
00143 {
00144
00145 Profile *res = resource_manager.LoadXMLProfile( "weapons.xml", false);
00146 particle_sprite[SMOKE_spr] = resource_manager.LoadSprite(res,"smoke");
00147 particle_sprite[EXPLOSION_SMOKE_spr] = resource_manager.LoadSprite(res,"smoke_explosion");
00148 particle_sprite[ILL_BUBBLE_spr] = resource_manager.LoadSprite(res,"ill_bubble");
00149 particle_sprite[FIRE_spr] = resource_manager.LoadSprite(res,"fire_particle");
00150 particle_sprite[FIRE_spr]->EnableRotationCache(32);
00151 particle_sprite[STAR_spr] = resource_manager.LoadSprite(res,"star_particle");
00152 particle_sprite[DARK_SMOKE_spr] = resource_manager.LoadSprite(res,"dark_smoke");
00153 particle_sprite[MAGIC_STAR_R_spr] = resource_manager.LoadSprite(res,"pink_star_particle");
00154 particle_sprite[MAGIC_STAR_R_spr]->EnableRotationCache(32);
00155 particle_sprite[MAGIC_STAR_Y_spr] = resource_manager.LoadSprite(res,"yellow_star_particle");
00156 particle_sprite[MAGIC_STAR_Y_spr]->EnableRotationCache(32);
00157 particle_sprite[MAGIC_STAR_B_spr] = resource_manager.LoadSprite(res,"blue_star_particle");
00158 particle_sprite[MAGIC_STAR_B_spr]->EnableRotationCache(32);
00159 particle_sprite[BULLET_spr] = resource_manager.LoadSprite(res,"bullet_particle");
00160 particle_sprite[BULLET_spr]->EnableRotationCache(6);
00161 particle_sprite[POLECAT_FART_spr] = resource_manager.LoadSprite(res,"polecat_fart");
00162 particle_sprite[POLECAT_FART_spr]->EnableRotationCache(6);
00163 resource_manager.UnLoadXMLProfile(res);
00164 }
00165
00166 void ParticleEngine::FreeMem()
00167 {
00168 for(int i=0; i<particle_spr_nbr ; i++)
00169 delete global_particle_engine.particle_sprite[i];
00170 }
00171
00172 Sprite* ParticleEngine::GetSprite(particle_spr type)
00173 {
00174 assert(type < particle_spr_nbr);
00175 return new Sprite(*(global_particle_engine.particle_sprite[type]));
00176 }
00177
00178 void ParticleEngine::AddNow(const Point2i &position,
00179 uint nb_particles, particle_t type,
00180 bool upper,
00181 double angle, double norme)
00182 {
00183 Particle *particle = NULL;
00184 double tmp_angle, tmp_norme;
00185
00186 for (uint i=0 ; i < nb_particles ; i++) {
00187 switch (type) {
00188 case particle_SMOKE : particle = new Smoke();
00189 break;
00190 case particle_ILL_BUBBLE : particle = new IllBubble();
00191 break;
00192 case particle_DARK_SMOKE : particle = new DarkSmoke();
00193 break;
00194 case particle_FIRE : particle = new FireParticle();
00195 break;
00196 case particle_STAR : particle = new StarParticle();
00197 break;
00198 case particle_BULLET : particle = new BulletParticle();
00199 break;
00200 case particle_POLECAT_FART : particle = new PolecatFart();
00201 break;
00202 case particle_GROUND : particle = new GroundParticle(Point2i(10,10), position);
00203 break;
00204 case particle_AIR_HAMMER : particle = new GroundParticle(Point2i(21,18), position);
00205
00206
00207
00208 break;
00209 case particle_MAGIC_STAR : particle = new MagicStarParticle();
00210 break;
00211 default : particle = NULL;
00212 assert(0);
00213 break;
00214 }
00215
00216 if (particle != NULL) {
00217 if( norme == -1 )
00218 tmp_norme = double(randomObj.GetLong(0, 5000))/100;
00219 else
00220 tmp_norme = norme;
00221
00222 if( angle == -1 )
00223 tmp_angle = - double(randomObj.GetLong(0, 3000))/1000;
00224 else
00225 tmp_angle = angle;
00226
00227 particle->SetXY(position);
00228 particle->SetOnTop(upper);
00229 particle->SetSpeed(tmp_norme, tmp_angle);
00230 lst_particles.push_back(particle);
00231 }
00232 }
00233 }
00234
00235 void ParticleEngine::AddNow(Particle* particle)
00236 {
00237 lst_particles.push_back(particle);
00238 }
00239
00240 void ParticleEngine::AddBigESmoke(const Point2i &position, const uint &radius)
00241 {
00242
00243
00244
00245 const uint little_partic_nbr = 10;
00246 const float little_cos[] = { 1.000000, 0.809017, 0.309017, -0.309017, -0.809017, -1.000000, -0.809017, -0.309017, 0.309017, 0.809017 };
00247 const float little_sin[] = { 0.000000, 0.587785, 0.951057, 0.951056, 0.587785, -0.000000, -0.587785, -0.951056, -0.951056, -0.587785 };
00248
00249 Particle *particle = NULL;
00250 float norme;
00251 uint size;
00252
00253 for(uint i=0; i < little_partic_nbr ; i++)
00254 {
00255
00256 size = uint(radius / 1.5);
00257 norme = 2.5 * radius / 3.0;
00258
00259 particle = new ExplosionSmoke(size);
00260 particle->SetOnTop(true);
00261
00262 Point2i pos = position;
00263 pos = pos - size / 2;
00264 pos = pos + Point2i(int(norme * little_cos[i]),int(norme * little_sin[i]));
00265
00266 particle->SetXY(pos);
00267 lst_particles.push_back(particle);
00268 }
00269 }
00270
00271 void ParticleEngine::AddLittleESmoke(const Point2i &position, const uint &radius)
00272 {
00273
00274 const uint big_partic_nbr = 5;
00275
00276
00277 const float big_cos[] = { 1.000000, -0.809017, 0.309017, 0.309017, -0.809017 };
00278 const float big_sin[] = { 0.000000, 0.587785, -0.951056, 0.951057, -0.587785 };
00279
00280 Particle *particle = NULL;
00281 float norme;
00282 uint size;
00283 for(uint i=0; i < big_partic_nbr ; i++)
00284 {
00285
00286 size = radius;
00287 norme = radius / 3.0;
00288
00289 Point2i pos = position;
00290 pos = pos - size / 2;
00291 pos = pos + Point2i(int(norme * big_cos[i]),int(norme * big_sin[i]));
00292
00293 particle = new ExplosionSmoke(size);
00294 particle->SetXY(pos);
00295 particle->SetOnTop(true);
00296
00297 lst_particles.push_back(particle);
00298 }
00299 }
00300
00301 void ParticleEngine::AddExplosionSmoke(const Point2i &position, const uint &radius, ESmokeStyle &style)
00302 {
00303 if(style == NoESmoke) return;
00304 AddLittleESmoke (position, radius);
00305 if(style == BigESmoke) AddBigESmoke (position, radius);
00306 }
00307
00308 void ParticleEngine::Draw(bool upper)
00309 {
00310 std::list<Particle *>::iterator Particle_it;
00311
00312 for (Particle_it=lst_particles.begin(); Particle_it!=lst_particles.end(); ++Particle_it){
00313 if ( (*Particle_it)->IsOnTop() == upper) {
00314 (*Particle_it)->Draw();
00315 }
00316 }
00317
00318 }
00319
00320 void ParticleEngine::Refresh()
00321 {
00322
00323 std::list<Particle*>::iterator it=lst_particles.begin(), end=lst_particles.end();
00324 while (it != end) {
00325 if (! (*it)->StillUseful()) {
00326 delete *it;
00327 it = lst_particles.erase(it);
00328 }
00329 else
00330 it++;
00331 }
00332
00333
00334 for(it=lst_particles.begin(); it!=lst_particles.end(); ++it) {
00335 (*it)->Refresh();
00336 }
00337 }
00338
00339 void ParticleEngine::Stop()
00340 {
00341
00342 std::list<Particle*>::iterator it=lst_particles.begin(), end=lst_particles.end();
00343 while (it != end) {
00344 delete *it;
00345 it = lst_particles.erase(it);
00346 }
00347 }
00348
00349 PhysicalObj * ParticleEngine::IsSomethingMoving()
00350 {
00351 std::list<Particle *>::iterator Particle_it;
00352
00353 for (Particle_it=lst_particles.begin(); Particle_it!=lst_particles.end(); ++Particle_it)
00354 if ((*Particle_it)->CheckOnEndTurn() && (*Particle_it)->StillUseful())
00355 return *Particle_it;
00356 return NULL;
00357 }