src/tron/gExplosion.cpp

Go to the documentation of this file.
00001 /*
00002 
00003 *************************************************************************
00004 
00005 ArmageTron -- Just another Tron Lightcycle Game in 3D.
00006 Copyright (C) 2000  Manuel Moos (manuel@moosnet.de)
00007 
00008 **************************************************************************
00009 
00010 This program is free software; you can redistribute it and/or
00011 modify it under the terms of the GNU General Public License
00012 as published by the Free Software Foundation; either version 2
00013 of the License, or (at your option) any later version.
00014 
00015 This program is distributed in the hope that it will be useful,
00016 but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 GNU General Public License for more details.
00019 
00020 You should have received a copy of the GNU General Public License
00021 along with this program; if not, write to the Free Software
00022 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00023 
00024 ***************************************************************************
00025 
00026 */
00027 
00028 #include "gExplosion.h"
00029 #include "rModel.h"
00030 #include "rRender.h"
00031 #include "tInitExit.h"
00032 #include "gWall.h"
00033 #include "gCycle.h"
00034 #include "eGrid.h"
00035 #include "tRandom.h"
00036 #include "tMath.h"
00037 
00038 #include "eSoundMixer.h"
00039 #ifdef USEPARTICLES
00040 #include "papi.h"
00041 #endif
00042 
00043 static tList< gExplosion > sg_Explosions;
00044 
00045 static void clamp01(REAL &c)
00046 {
00047     if (!finite(c))
00048         c = 0.5;
00049 
00050     if (c<0)
00051         c = 0;
00052 
00053     if (c>1)
00054         c = 1;
00055 }
00056 
00057 int     gExplosion::expansionSteps=5;
00058 REAL gExplosion::expansionTime = 0.2f;
00059 
00060 static eCoord s_explosionCoord;
00061 static REAL   s_explosionRadius;
00062 static REAL       s_explosionTime;
00063 static gExplosion * s_holer = 0;
00064 
00065 // blow a hole centered at s_explosionCoord with radius s_explosionRadius into wall w
00066 static void S_BlowHoles( eWall * w )
00067 {
00068     // determine the point closest to s_explosionCoord
00069     eCoord normal = w->Vec().Conj();
00070     normal.Normalize();
00071 
00072     eCoord Pos1 = normal.Turn( w->EndPoint(0) - s_explosionCoord );
00073     eCoord Pos2 = normal.Turn( w->EndPoint(1) - s_explosionCoord );
00074 
00075     tASSERT( fabs( Pos1.y - Pos2.y ) <= fabs( Pos1.y + Pos2.y + .1f ) * .1f );
00076 
00077     REAL alpha = .5f;
00078     if ( Pos1.x != Pos2.x)
00079         alpha = Pos1.x / ( Pos1.x - Pos2.x );
00080 
00081     REAL radius = s_explosionRadius * s_explosionRadius - Pos1.y * Pos2.y;
00082 
00083     // wall too far away
00084     if ( radius < 0 )
00085         return;
00086 
00087     radius = sqrt( radius );
00088 
00089     // works only for player walls
00090     gPlayerWall* wall = dynamic_cast<gPlayerWall*>( w );
00091     if ( ! wall )
00092         return;
00093 
00094     REAL closestPos = wall->Pos( alpha );
00095 
00096     REAL start = closestPos - radius;
00097     REAL end = closestPos + radius;
00098 
00099     // only cut away walls that were created before the explosion started
00100     REAL wallEnd = wall->EndPos();
00101     REAL wallBeg = wall->BegPos();
00102     if ( wallEnd <= wallBeg )
00103     {
00104         return;
00105     }
00106     REAL endAlpha = ( end - wallBeg ) / ( wallEnd - wallBeg );
00107     // //std::cout << wall->BegTime() << "\n";
00108     clamp01( endAlpha );
00109     REAL endHoleTime = wall->Time( endAlpha );
00110     if ( endHoleTime > s_explosionTime )
00111     {
00112         REAL begTime = wall->BegTime();
00113         REAL endTime = wall->EndTime();
00114         REAL timeNorm = endTime - begTime;
00115         if ( timeNorm != 0.0f )
00116         {
00117             endAlpha = ( s_explosionTime - begTime ) / timeNorm;
00118             end = wall->Pos( endAlpha );
00119         }
00120     }
00121 
00122     if ( end > start )
00123     {
00124         wall->BlowHole ( start, end, s_holer );
00125     }
00126 }
00127 
00128 /*
00129 // synchronize walls affected by explosion
00130 static void S_Sync( eWall * w )
00131 {
00132         // works only for player walls
00133         gPlayerWall* wall = dynamic_cast<gPlayerWall*>( w );
00134         if ( ! wall )
00135                 return;
00136 
00137         wall->RequestSync ();
00138 }
00139 */
00140 
00141 gExplosion::gExplosion(eGrid *grid, const eCoord &pos,REAL time, gRealColor& color, gCycle * owner )
00142         :eReferencableGameObject(grid, pos, eCoord(0,0), NULL, true),
00143         createTime(time),
00144         expansion(0),
00145         listID(-1),
00146         owner_(owner) 
00147 {
00148     eSoundMixer* mixer = eSoundMixer::GetMixer();
00149     mixer->PushButton(CYCLE_EXPLOSION, pos);
00150     //std::cout << "explosion sound effect\n";
00151     holeAccountedFor_ = false;
00152 
00153     lastTime = time;
00154     explosion_r = color.r;
00155     explosion_g = color.g;
00156     explosion_b = color.b;
00157     //std::cout << "about to do sg_Explosions.Add\n";
00158     sg_Explosions.Add( this, listID );
00159     z=0;
00160     //std::cout << "explosion constructed\n";
00161 #ifdef USEPARTICLES
00162     //std::cout << "Using particle explosion\n";
00163     //    particle_handle_circle = pGenParticleGroups(1, 10);
00164     //    particle_handle_cylinder = pGenParticleGroups(1, 1000);
00165 
00166     //    pCurrentGroup(particle_handle_circle);
00167     // Generate particles along a very small line in the nozzle.
00168     //    pSource(1000, PDSphere(pVec(pos.x, pos.y, 0.3), 0.2));
00169     //    pCurrentGroup(particle_handle_cylinder);
00170     // Generate particles along a very small line in the nozzle.
00171     //    pSource(1000, PDSphere(pVec(Position().x, Position().y, 0.3), 0.2));
00172 #endif
00173 
00174     // add to game object lists
00175     AddToList();
00176     //std::cout << "Last line of constructor\n";
00177 }
00178 
00179 gExplosion::~gExplosion(){
00180     sg_Explosions.Remove( this, listID );
00181 
00182     if ( s_explosionRadius > 0 )
00183     {
00184         /*
00185         s_explosionCoord  = pos;
00186         s_explosionRadius = gCycle::ExplosionRadius()*1.5f;
00187 
00188         grid->ProcessWallsInRange( &S_Sync,
00189                                                            s_explosionCoord,
00190                                                            s_explosionRadius,
00191                                                            this->CurrentFace() );
00192         */
00193     }
00194 }
00195 
00196 // virtual eGameObject_type type();
00197 
00198 
00199 bool gExplosion::Timestep(REAL currentTime){
00200     lastTime=currentTime;
00202 
00203     int currentExpansion = int(REAL( expansionSteps )*((currentTime - createTime)/expansionTime)) + 1;
00204     if ( currentExpansion > expansionSteps )
00205         currentExpansion = expansionSteps;
00206 
00207     if ( currentExpansion > expansion )
00208     {
00209         expansion = currentExpansion;
00210 
00211         s_explosionCoord  = pos;
00212         REAL factor = expansion / REAL( expansionSteps );
00213         s_explosionRadius = gCycle::ExplosionRadius() * sqrt(factor);
00214         s_explosionTime = currentTime;
00215         s_holer = this;
00216 
00217         if ( s_explosionRadius > 0 && (currentTime < createTime+4) )
00218         {
00219             grid->ProcessWallsInRange( &S_BlowHoles,
00220                                        s_explosionCoord,
00221                                        s_explosionRadius,
00222                                        this->CurrentFace() );
00223         }
00224 
00225         s_holer = 0;
00226     }
00227 #ifndef USEPARTICLES
00228 
00229     /*
00230         // see every once in a while if all cycles did a turn since the expl was created
00231         if ( expansion >= expansionSteps )
00232         {
00233                 currentExpansion = expansionSteps + 1 + int( REAL( expansion ) * ( currentTime - createTime ) );
00234         }
00235         if ( currentExpansion > expansion )
00236         {
00237                 expansion = currentExpansion;
00238                 REAL time = createTime + 5.0f;
00239 
00240                 const tList<eGameObject>& gameObjects = this->Grid()->GameObjects();
00241                 for ( int i = gameObjects.Len() - 1; i>=0; --i )
00242                 {
00243                         eGameObject* o = gameObjects( i );
00244 
00245                         gCycle* c = dynamic_cast< gCycle* >( o );
00246                         if ( c && c->Alive() )
00247                         {
00248                                 const gPlayerWall* w = c->CurrentWall();
00249 
00250                                 if ( !w || w->BegTime() < time || w->EndTime() < time )
00251                                 {
00252                                         // c has not made a turn; we need to stay around some more
00253                                         return false;
00254                                 }
00255                         }
00256                 }
00257         }
00258     */
00259     if (currentTime>createTime+4)
00260         return true;
00261     else
00262         return false;
00263 #else
00264     /*    pCurrentGroup(particle_handle_circle);
00265     // Set up the state.
00266     pExplosion(Position().x, Position().y, 0.3, 20.0, 20.0, 1.0);
00267     //pVelocityD(PDCylinder(pVec(0.0, 0.0, 0.0), pVec(0.0, 0.0, 0.01), 0.01, 0.007));
00268     pColorD(PDLine(pVec(1.0, 1.0, 1.0), pVec(1.0, 1.0, 1.0)));
00269     pSize(40.0);
00270     //pStartingAge(0);
00271 
00272     //pRandomAccel(PDSphere(pVec(Position().x, Position().y, 0.0), 100.0));
00273 
00274     // Bounce particles off the grid floor.
00275     pBounce(-0.05, 1.0, 0.1, PDDisc(pVec(0, 0, 0), pVec(0, 0, 1), 5000000));
00276 
00277     pKillOld(400.0);
00278 
00279     // Move particles to their new positions.
00280     pMove();
00281 
00282     // Finished when there are less than 1/10 of the original particles
00283     if (pGetGroupCount() < 100) {
00284     pDeleteParticleGroups(particle_handle_circle, particle_handle_circle);
00285     return true;
00286     } else
00287     return false;*/
00288     //std::cout << "returning from timestep\n";
00289     if (currentTime>createTime+4)
00290         return true;
00291     else
00292         return false;
00293 #endif
00294 }
00295 
00296 void gExplosion::InteractWith(eGameObject *,REAL ,int){}
00297 
00298 void gExplosion::PassEdge(const eWall *,REAL ,REAL ,int){}
00299 
00300 void gExplosion::Kill(){
00301     createTime=lastTime-100;
00302 }
00303 
00304 bool gExplosion::AccountForHole()
00305 {
00306     bool ret = !holeAccountedFor_;
00307     holeAccountedFor_ = true;
00308     return ret;
00309 }
00310 
00311 void gExplosion::OnNewWall( eWall* w )
00312 {
00313     for ( int i = sg_Explosions.Len() - 1; i>=0; --i )
00314     {
00315         const gExplosion* e = sg_Explosions(i);
00316         if ( e->expansion >= expansionSteps )
00317         {
00318             // e is a already completed explosion
00319             s_explosionCoord  = e->pos;
00320             s_explosionRadius = gCycle::ExplosionRadius();
00321             s_explosionTime = e->createTime;
00322 
00323             S_BlowHoles( w );
00324         }
00325     }
00326 }
00327 
00328 static tArray<Vec3> expvec;
00329 
00330 static void init_exp(){
00331     int i=0;
00332     expvec[i++]=Vec3(0,0,1);
00333     expvec[i++]=Vec3(0,1,1);
00334     expvec[i++]=Vec3(0,-1,1);
00335     expvec[i++]=Vec3(1,0,1);
00336     expvec[i++]=Vec3(-1,0,1);
00337     expvec[i++]=Vec3(1,1,1);
00338     expvec[i++]=Vec3(-1,1,1);
00339     expvec[i++]=Vec3(1,-1,1);
00340     expvec[i++]=Vec3(-1,-1,1);
00341 
00342     const REAL fak=7;
00343 
00344     tRandomizer & randomizer = tRandomizer::GetInstance();
00345 
00346     for (int j=i;j<40;j++){
00347         expvec[i++]=Vec3(fak*( randomizer.Get() -.5f ),
00348                          fak*( randomizer.Get() -.5f ),
00349                          1);
00350         //        expvec[i++]=Vec3(fak*(rand()/static_cast<REAL>(RAND_MAX)-.5f),
00351         //                         fak*(rand()/static_cast<REAL>(RAND_MAX)-.5f),
00352         //                         1);
00353     }
00354 
00355     for (int k=expvec.Len()-1;k>=0;k--)
00356         expvec[k]=expvec[k]*(1/expvec[k].Norm());
00357 }
00358 
00359 static tInitExit ie_exp(&init_exp);
00360 
00361 bool sg_crashExplosion = true;
00362 bool sg_crashExplosionHud = true;
00363 
00364 #ifndef DEDICATED
00365 void gExplosion::Render(const eCamera *cam){
00366     //std::cout << "Starting render\n";
00367 #ifdef USEPARTICLES
00368     /*if(sg_crashExplosion){
00369         ModelMatrix();
00370         glPushMatrix();
00371         pCurrentGroup(particle_handle_circle);
00372         int cnt = (int)pGetGroupCount();
00373         if(cnt < 1) return;
00374 
00375         float *ptr;
00376         size_t flstride, pos3Ofs, posB3Ofs, size3Ofs, vel3Ofs, velB3Ofs, color3Ofs, alpha1Ofs, age1Ofs;
00377 
00378         cnt = (int)pGetParticlePointer(ptr, flstride, pos3Ofs, posB3Ofs,
00379             size3Ofs, vel3Ofs, velB3Ofs, color3Ofs, alpha1Ofs, age1Ofs);
00380         if(cnt < 1) return;
00381 
00382         glEnableClientState(GL_COLOR_ARRAY);
00383         glColorPointer(4, GL_FLOAT, int(flstride) * sizeof(float), ptr + color3Ofs);
00384 
00385         glEnableClientState(GL_VERTEX_ARRAY);
00386         glVertexPointer(3, GL_FLOAT, int(flstride) * sizeof(float), ptr + pos3Ofs);
00387 
00388         glDrawArrays(GL_POINTS, 0, cnt);
00389         glDisableClientState(GL_VERTEX_ARRAY);
00390         glDisableClientState(GL_COLOR_ARRAY);
00391         glPopMatrix();
00392     }*/
00393 #else
00394     if (sg_crashExplosion){
00395         REAL a1=(lastTime-createTime)+.01f;//+.2;
00396         REAL e=a1-1;
00397 
00398         if (e<0) e=0;
00399 
00400         REAL fade=(2-a1);
00401         if (fade<0) fade=0;
00402         if (fade>1) fade=1;
00403 
00404         a1*=100;
00405         e*=100;
00406 
00407         ModelMatrix();
00408         glPushMatrix();
00409         glTranslatef(pos.x,pos.y,0);
00410 
00411         //glDisable(GL_TEXTURE);
00412         glDisable(GL_TEXTURE_2D);
00413 
00414         glColor4f(explosion_r,explosion_g,explosion_b,fade);
00415         BeginLines();
00416         for (int i=expvec.Len()-1;i>=0;i--){
00417             glVertex3f(a1*expvec[i].x[0],a1*expvec[i].x[1],a1*expvec[i].x[2]);
00418             glVertex3f( e*expvec[i].x[0], e*expvec[i].x[1], e*expvec[i].x[2]);
00419         }
00420         RenderEnd();
00421         glPopMatrix();
00422     }
00423     /*
00424     if(sr_alphaBlend)
00425     for(int i=2;i>=0;i--){
00426     REAL age=a1-i*.1;
00427     if (0<age && age<.5){
00428     REAL alpha=(3-i)*.5*(1-age*2)*(1-age*2);
00429     glColor4f(r,g,b,alpha);
00430     glDisable(GL_LIGHTING);
00431     glDisable(GL_TEXTURE_2D);
00432     glMatrixMode(GL_MODELVIEW);
00433     glPushMatrix();
00434     glTranslatef(pos.x,pos.y,age*pow((age+1),3)*(age+.5)*100);
00435     y
00436 
00437     GLUquadricObj* q= gluNewQuadric();
00438 
00439     gluSphere(q,(age*pow((age+1),3)*(age+.5))*100,5,5);
00440 
00441     gluDeleteQuadric( q );
00442 
00443     glPopMatrix();
00444     }
00445     }
00446     */
00447 #endif
00448     //std::cout << "Finishing render\n";
00449 }
00450 
00451 void gExplosion::Render2D(tCoord scale) const {
00452 #ifndef DEDICATED
00453     if(sg_crashExplosionHud){
00454         REAL a1=(lastTime-createTime)+.01f;//+.2;
00455         REAL e=a1-1;
00456 
00457         if (e<0) e=0;
00458 
00459         REAL fade=(2-a1);
00460         if (fade<0) fade=0;
00461         if (fade>1) fade=1;
00462 
00463         a1*=100;
00464         e*=100;
00465 
00466         ModelMatrix();
00467         glPushMatrix();
00468         glTranslatef(pos.x,pos.y,0);
00469 
00470         glDisable(GL_TEXTURE_2D);
00471 
00472         glColor4f(explosion_r,explosion_g,explosion_b,fade);
00473         BeginLines();
00474         for(int i=expvec.Len()-1;i>=0;i--){
00475             glVertex2f(a1*expvec[i].x[0],a1*expvec[i].x[1]);
00476             glVertex2f( e*expvec[i].x[0], e*expvec[i].x[1]);
00477         }
00478         RenderEnd();
00479         glPopMatrix();
00480     }
00481 #endif
00482     //std::cout << "Finishing render\n";
00483 }
00484 
00485 #if 0
00486 void gExplosion::SoundMix(Uint8 *dest,unsigned int len,
00487                           int viewer,REAL rvol,REAL lvol){
00488 #ifndef HAVE_LaIBSDL_MIXER
00489     sound.Mix(dest,len,viewer,rvol*4,lvol*4);
00490 #endif
00491 }
00492 #endif
00493 
00494 #endif
00495 
00496 void gExplosion::OnRemoveFromGame()
00497 {
00498     // remove from list to avoid costy checks whenever a new wall appears
00499     sg_Explosions.Remove( this, listID );
00500 
00501     // delegate to base
00502     eReferencableGameObject::OnRemoveFromGame();
00503 }

Generated on Sat Mar 15 22:56:07 2008 for Armagetron Advanced by  doxygen 1.5.4