Back to index

supertuxkart  0.5+dfsg1
projectile_manager.cpp
Go to the documentation of this file.
00001 //  $Id: projectile_manager.cpp 2111 2008-05-31 07:04:30Z cosmosninja $
00002 //
00003 //  SuperTuxKart - a fun racing game with go-kart
00004 //  Copyright (C) 2006 Joerg Henrichs
00005 //
00006 //  This program is free software; you can redistribute it and/or
00007 //  modify it under the terms of the GNU General Public License
00008 //  as published by the Free Software Foundation; either version 2
00009 //  of the License, or (at your option) any later version.
00010 //
00011 //  This program is distributed in the hope that it will be useful,
00012 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 //  GNU General Public License for more details.
00015 //
00016 //  You should have received a copy of the GNU General Public License
00017 //  along with this program; if not, write to the Free Software
00018 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00019 
00020 #include "loader.hpp"
00021 #include "projectile_manager.hpp"
00022 #include "spark.hpp"
00023 #include "missile.hpp"
00024 #include "homing.hpp"
00025 #include "explosion.hpp"
00026 #include "collectable_manager.hpp"
00027 #include "collectable.hpp"
00028 #include "scene.hpp"
00029 
00030 static ssgSelector *find_selector ( ssgBranch *b );
00031 
00032 ProjectileManager *projectile_manager=0;
00033 
00034 void ProjectileManager::loadData()
00035 {
00036 
00037     // Load the explosion model and find the actual selector branch in it.
00038     // Only the explosion model is loaded here, see collectable_manager.
00039     m_explosion_model = find_selector((ssgBranch*)loader->load("explode.ac",
00040                                    CB_EXPLOSION) );
00041     m_explosion_model->ref();
00042     if ( m_explosion_model == NULL )
00043     {
00044         fprintf ( stderr, "explode.ac doesn't have an 'explosion' object.\n" ) ;
00045         exit ( 1 ) ;
00046     }
00047 
00048 }   // loadData
00049 
00050 //-----------------------------------------------------------------------------
00051 void ProjectileManager::removeTextures()
00052 {
00053     cleanup();
00054     ssgDeRefDelete(m_explosion_model);
00055     // Only the explosion is here, all other models are actually managed
00056     // by collectable_manager.
00057     callback_manager->clear(CB_EXPLOSION);
00058 }   // removeTextures
00059 
00060 //-----------------------------------------------------------------------------
00061 void ProjectileManager::cleanup()
00062 {
00063     for(Projectiles::iterator i = m_active_projectiles.begin();
00064         i != m_active_projectiles.end(); ++i)
00065     {
00066         ssgTransform *m = (*i)->getModelTransform();
00067         m->removeAllKids();
00068         delete *i;
00069     }
00070     m_active_projectiles.clear();
00071     for(Explosions::iterator i  = m_active_explosions.begin();
00072         i != m_active_explosions.end(); ++i)
00073     {
00074         scene->remove((ssgTransform*)*i);
00075         ssgDeRefDelete(*i);
00076     }
00077     m_active_explosions.clear();
00078 }   // cleanup
00079 
00080 // -----------------------------------------------------------------------------
00082 void ProjectileManager::update(float dt)
00083 {
00084     // First update all projectiles on the track
00085     for(Projectiles::iterator i  = m_active_projectiles.begin();
00086         i != m_active_projectiles.end(); ++i)
00087     {
00088         (*i)->update(dt);
00089     }
00090     // Then check if any projectile hit something
00091     if(m_something_was_hit)
00092     {
00093         Projectiles::iterator p = m_active_projectiles.begin();
00094         while(p!=m_active_projectiles.end())
00095         {
00096             if(! (*p)->hasHit()) { p++; continue; }
00097             newExplosion((*p)->getCoord());
00098             Flyable *f=*p;
00099             Projectiles::iterator pNext=m_active_projectiles.erase(p);  // returns the next element
00100             delete f;
00101             p=pNext;
00102         }   // while p!=m_active_projectiles.end()
00103     }
00104 
00105     m_explosion_ended=false;
00106     for(Explosions::iterator i  = m_active_explosions.begin();
00107         i != m_active_explosions.end(); ++i)
00108     {
00109         (*i)->update(dt);
00110     }
00111     if(m_explosion_ended)
00112     {
00113         Explosions::iterator e;
00114         e = m_active_explosions.begin();
00115         while(e!=m_active_explosions.end())
00116         {
00117             if(!(*e)->hasEnded()) { e++; continue;}
00118             Explosion *exp=*e;
00119             Explosions::iterator eNext=m_active_explosions.erase(e);
00120             ssgDeRefDelete(exp);  // reduce refcount and free object
00121             e=eNext;
00122         }   // while e!=m_active_explosions.end()
00123     }   // if m_explosion_ended
00124     m_something_was_hit=false;
00125 }   // update
00126 
00127 // -----------------------------------------------------------------------------
00128 Flyable *ProjectileManager::newProjectile(Kart *kart, CollectableType type)
00129 {
00130     Flyable *f;
00131     switch(type) {
00132     case COLLECT_SPARK:   f = new Spark(kart);   break;
00133     case COLLECT_HOMING:  f = new Homing(kart);  break;
00134     case COLLECT_MISSILE: f = new Missile(kart); break;
00135     default:              return NULL;
00136     }
00137     m_active_projectiles.push_back(f);
00138     return f;
00139 }   // newProjectile
00140 
00141 // -----------------------------------------------------------------------------
00144 Explosion* ProjectileManager::newExplosion(sgCoord* coord)
00145 {
00146     Explosion *e = new Explosion(coord);
00147     m_active_explosions.push_back(e);
00148     return e;
00149 }   // newExplosion
00150 
00151 // =============================================================================
00155 static ssgSelector *find_selector ( ssgBranch *b )
00156 {
00157     if ( b == NULL )
00158         return NULL ;
00159 
00160     if ( ! b -> isAKindOf ( ssgTypeBranch () ) )
00161         return NULL ;
00162 
00163     if ( b -> isAKindOf ( ssgTypeSelector () ) )
00164         return (ssgSelector *) b ;
00165 
00166     for ( int i = 0 ; i < b -> getNumKids() ; i++ )
00167     {
00168         ssgSelector *res = find_selector ( (ssgBranch *)(b ->getKid(i)) ) ;
00169 
00170         if ( res != NULL )
00171             return res ;
00172     }
00173 
00174     return NULL ;
00175 }   // find_selector