C:/Documents and Settings/jegan/Desktop/projectX/Level.cpp

Go to the documentation of this file.
00001 #include "Level.h"
00002 #include "Screen.h"
00003 #include "CommandManager.h"
00004 #include "Object.h"
00005 #include "Player.h"
00006 #include "Control.h"
00007 #include "Camera.h"
00008 #include "Parser.h"
00009 #include "Bullet.h"
00010 #include "Command.h"
00011 
00012 #include <io.h>
00013 #include <iostream>
00014 #include <sstream>
00015 #include <cassert>
00016 
00017 using namespace std;
00018 
00019 Uint32 Level::WALKBEHIND = 0;
00020 Uint32 Level::WALKINTO = 0;
00021 Uint32 Level::WALKINFRONT = 0;
00022 bool Level::_objectsLoaded = false;
00023 map<Uint32,Sprite *> Level::TEXTURES;
00024 map<Uint32,string> Level::OBJECTS;
00025 Level *Level::_instance = NULL;
00026 
00027 Level::Level()
00028 :_cutScene(false),_score(0),_won(0), _music(NULL), _timed(false), _levelTimer(-1),_background(NULL), _totBad(0), _killed(0)
00029 {
00030         loadObjects();
00031         
00032 
00033         _instance = this;
00034 }
00035 
00036 Level::~Level()
00037 {
00038         //Halt the music since the level no longer exists
00039         Mix_HaltMusic();
00040         Mix_FreeMusic(_music);
00041         
00042         CommandManager::instance()->flush();
00043 
00044         Sprite::cleanSprites();
00045         
00046         if(_background)
00047                 delete _background;
00048 
00049         for(map<std::string, Mix_Chunk*>::iterator i = _sounds.begin(); i!=_sounds.end();i++)
00050         {
00051                 Mix_FreeChunk((*i).second);
00052                 (*i).second = NULL;
00053         }
00054         _sounds.clear();
00055 
00056         for(int i=0; i<_objects.size(); i++)
00057         {
00058                 Control::detachController( _objects[i] );
00059                 delete _objects[i];
00060         }
00061         for(int i=0; i<_tiles.size(); i++)
00062                 delete _tiles[i];
00063 
00064         for(int i=0; i<_save.size(); i++)
00065                 delete _save[i];
00066 }
00067 
00068 void Level::save()
00069 {
00070         for(size_t i = 0; i < _save.size(); i++)
00071                         delete _save[i];
00072 
00073         _save.clear();
00074 
00075         for(size_t i = 0; i < _objects.size(); i++)
00076                 if(_objects[i]->getType() != BULLET)
00077                         _save.push_back(_objects[i]->copy());
00078 }
00079 
00080 void Level::restore()
00081 {
00082         if(!_save.empty()) {
00083 
00084                 for(int i=0; i<_objects.size(); i++)
00085                 {
00086                         Control::detachController( _objects[i] );
00087                         _drawnObjects.erase( remove( _drawnObjects.begin(), _drawnObjects.end(), _objects[i] ), _drawnObjects.end() ); 
00088                         delete _objects[i];
00089                 }
00090 
00091                 CommandManager::instance()->flush();
00092                 _ids.clear();
00093                 _objects.clear();
00094                 _deleteQueue.clear();
00095 
00096                 while(!_addQueue.empty())
00097                 {
00098                         delete _addQueue.front();
00099                         _addQueue.pop();
00100                 }
00101 
00102                 for(size_t i = 0; i < _save.size(); i++) {
00103                         Object *object = _save[i]->copy();
00104 
00105                         addObject(object,_objects);
00106 
00107                         //FIXME: All bullets saved automagically have their shooter set to the player.
00108                         // How wrong can I possible be?!
00109                         if(object->getType() == BULLET)
00110                                 ((Bullet *)object)->setShooter(_player);
00111                 }
00112 
00113                 _player = (Player*)_ids["goudy1"];
00114                 
00115                 SetControlCommand(_player).execute();
00116 
00117                 //Control::registerController(_player);
00118                 Screen::instance()->registerFollowObj(_player);
00119         }
00120 }
00121 
00122 void Level::reset()
00123 {
00124         restore();
00125         /*
00126         for(int i=0; i<_objects.size(); i++)
00127         {
00128                 Control::detachController( _objects[i] );
00129                 delete _objects[i];
00130         }
00131         for(int i=0; i<_tiles.size(); i++)
00132                 delete _tiles[i];
00133 
00134         _objects.clear();
00135         _tiles.clear();
00136         _drawnObjects.clear();
00137         _deleteQueue.clear();
00138 
00139         _ids.clear();
00140 
00141         while(!_addQueue.empty())
00142         {
00143                 delete _addQueue.front();
00144                 _addQueue.pop();
00145         }
00146 
00147         levelLoad(_filenamebase);
00148         */
00149 }
00150 
00151 void Level::loadObjects()
00152 {
00153         if(!_objectsLoaded) {
00154                 readTextures("png");
00155                 readTextures("txt");
00156                 
00157                 WALKBEHIND = loadPixelFile("levels/walkbehind_p.png");
00158                 WALKINFRONT = loadPixelFile("levels/walkinfront_p.png");
00159                 WALKINTO = loadPixelFile("levels/walkinto_p.png");
00160 
00161                 readObjects("characters");
00162                 readObjects("events");
00163                 readObjects("cutscenes");
00164                 readObjects("entities");
00165                 //readTextures("bmp");
00166                 _objectsLoaded = true;
00167         }
00168 }
00169 
00170 Uint32 Level::loadPixelFile(std::string filename)
00171 {
00172         SDL_Surface *surface = glfuncs::instance()->load_image(filename);
00173         SDL_LockSurface(surface);
00174         Uint32 pixel=*((Uint32*)surface->pixels);
00175         SDL_UnlockSurface(surface);
00176         SDL_FreeSurface(surface);
00177         return pixel;
00178 }
00179 
00180 void Level::readObjects(std::string dir)
00181 {
00182         struct _finddata_t file;
00183         intptr_t hFile;
00184         string extension = "txt";
00185 
00186         if( (hFile = _findfirst( (dir + "/*." + extension).c_str(), &file )) != -1L ) {
00187                 do {
00188                         string filename(file.name);
00189                         
00190                         string end = filename.substr(filename.size() - 6,2);
00191                         if(end != "_p") {
00192 
00193                                 filename = dir + "/" + filename;
00194                                 //Sprite * sprite = new Sprite(filename, tileWidth, tileHeight);
00195                                 string objFile = filename;
00196 
00197                                 //filename.insert(filename.find("."),"_p");
00198                                 filename.erase(filename.find("."),4);
00199                                 filename += "_p.png";
00200 
00201                                 SDL_Surface *surface = glfuncs::instance()->load_image(filename);
00202                                 SDL_LockSurface(surface);
00203                                 Uint32 pixel=*((Uint32*)surface->pixels);
00204                                 
00205                                 //cerr << (int) pixel << endl;
00206 
00207                                 SDL_UnlockSurface(surface);
00208                                 SDL_FreeSurface(surface);
00209 
00210                                 OBJECTS[pixel] = objFile;
00211                         }
00212                         else
00213                                 continue;
00214                 }
00215                 while( _findnext( hFile, &file ) == 0 );
00216 
00217                 _findclose( hFile );
00218         }
00219 }
00220 
00221 void Level::readTextures(std::string extension)
00222 {
00223         struct _finddata_t file;
00224         intptr_t hFile;
00225 
00226         if( (hFile = _findfirst( ("textures/*." + extension).c_str(), &file )) != -1L ) {
00227                 do {
00228                         string filename(file.name);
00229                         
00230                         string end = filename.substr(filename.size() - 6,2);
00231                         if(end != "_p") {
00232 
00233                                 filename = "textures/" + filename;
00234                                 //Sprite * sprite = new Sprite(filename, tileWidth, tileHeight);
00235                                 Sprite * sprite = Sprite::loadSprite(filename);
00236 
00237                                 //filename.insert(filename.find("."),"_p");
00238                                 filename.erase(filename.find("."),4);
00239                                 filename += "_p.png";
00240 
00241                                 SDL_Surface *surface = glfuncs::instance()->load_image(filename);
00242                                 SDL_LockSurface(surface);
00243                                 Uint32 pixel=*((Uint32*)surface->pixels);
00244                                 
00245                                 //cerr << (int) pixel << endl;
00246 
00247                                 SDL_UnlockSurface(surface);
00248                                 SDL_FreeSurface(surface);
00249 
00250                                 TEXTURES[pixel] = sprite;
00251                         }
00252                         else
00253                                 continue;
00254                 }
00255                 while( _findnext( hFile, &file ) == 0 );
00256 
00257                 _findclose( hFile );
00258         }
00259 }
00260 
00261 void Level::levelLoad(std::string filenamebase)
00262 {
00263         _filenamebase = filenamebase;
00264 
00265         levelTextureLoad(filenamebase);
00266         levelObjectLoad(filenamebase);
00267         levelSpecsLoad(filenamebase);
00268 
00269 
00270         //FIXME (Have the player object register this itself) 
00271         //This will require a text file for each level (which will have to be loaded here)
00272         //goudy1 is the id of the player
00273         
00274 
00275         _player = (Player *)_ids["goudy1"];
00276 
00277         /*if(prevplayer != NULL)
00278         {
00279 
00280                 prevplayer->setPos(_player->getBox().x, _player->getBox().y);
00281                 prevplayer->setVelocity(0,0);
00282                 prevplayer->setXDirection(_player->getXDirection());
00283                 prevplayer->uncrouch();
00284                 prevplayer->setCollidable(true);
00285 
00286                 _objects.erase(remove(_objects.begin(),_objects.end(),_player),_objects.end());
00287                 _drawnObjects.erase(remove(_drawnObjects.begin(),_drawnObjects.end(),_player),_drawnObjects.end());
00288                 delete _ids["goudy1"];
00289                 
00290                 _player = prevplayer;
00291                 addObject(prevplayer,_objects);
00292         }*/
00293 
00294 
00295         Screen::instance()->registerFollowObj( (Object*)_player );
00296         SetControlCommand(_player).execute();
00297         //Control::registerController((Object*)_player);
00298 
00299         SaveCommand().execute();
00300         //CommandManager::instance()->startPlaying("scripts/newDemo.txt");
00301         //CommandManager::instance()->startRecording();
00302 }
00303 
00304 void Level::levelSpecsLoad(std::string filenamebase)
00305 {
00306         string specsFilename = filenamebase + ".txt";
00307         List *specsList = Parser::parse(specsFilename);
00308 
00309         List *specs = specsList;
00310         
00311         while(!specs->empty()) {
00312                 List *current = specs->firstList();
00313                 if(current->firstString() == "timer")
00314                 {
00315                         _timed = true;
00316                         _levelTimer = current->rest()->firstInt();
00317 
00318                 }
00319                 else if(current->firstString() == "totBad")
00320                 {
00321                         _totBad = current->rest()->firstInt();
00322                 }
00323                 else
00324                 {
00325                         Object *object = getObject(current->firstString());
00326                         object->load(current->rest(), false);
00327                 }
00328 
00329                 specs = specs->rest();
00330         }
00331 
00332         delete specsList;
00333 }
00334 
00335 void Level::setMusic( Mix_Music* music )
00336 {
00337         if(_music)
00338                 Mix_FreeMusic(_music);                  
00339         _music = music;
00340 }
00341 
00342 void Level::levelObjectLoad(std::string filenamebase)
00343 {
00344         string objFilename = filenamebase + "obj.bmp";
00345         SDL_Surface *surface = glfuncs::load_image(objFilename);
00346         SDL_LockSurface(surface);
00347 
00348         _height = surface->h*tileHeight;
00349         _width = surface->w*tileWidth;
00350 
00351         Uint32* objectPixels = (Uint32*)surface->pixels;
00352 
00353         //int maxoffset = surface->h*surface->w;
00354         for(int i=0; i < surface->h ; i++ ){
00355                 for( int j=0 ; j < surface->w ;j++){
00356 
00357                         if(OBJECTS[objectPixels[i*surface->w+j]] != "")
00358                         {
00359                                 Object* o = Object::loadObject(OBJECTS[objectPixels[i*surface->w+j]], j*tileWidth, i*tileHeight);
00360                                 string id = o->id();
00361                                 
00362                                 //Append a number to the end of objects so we get EasyEnemy1, EasyEnemy2, ...
00363                                 int i = 0;
00364                                 do
00365                                 {
00366                                         i++;
00367                                         stringstream num;
00368                                         num << i;
00369                                         o->setId(id+num.str());
00370                                         //map<string,Object *>::iterator j = _ids.find(o->id());
00371 
00372                                 //}while (_ids.find(o->id()) != _ids.end());
00373                                 } while(_ids[o->id()] != NULL);
00374 
00375                                 cerr << o->id() << endl;
00376 
00377                                 addObject(o, _objects);
00378                         }
00379                 }
00380         }
00381 
00382         SDL_UnlockSurface(surface);
00383         SDL_FreeSurface(surface);
00384 }
00385 
00386 
00387 void Level::levelTextureLoad(std::string filenamebase)
00388 {
00389         string texFilename = filenamebase + "tex.bmp";
00390         string colFilename = filenamebase + "col.bmp";
00391         string backFilename = filenamebase + "back.png";
00392         SDL_Surface *surface = glfuncs::load_image(texFilename);
00393         SDL_Surface* colSurface = glfuncs::load_image( colFilename );
00394 
00395         SDL_LockSurface(surface);
00396         SDL_LockSurface(colSurface);
00397 
00398         Tile* t = NULL;
00399 
00400         _height = surface->h*tileHeight;
00401         _width = surface->w*tileWidth;
00402 
00403         _tiles = vector< Tile* >( _height*_width, t );
00404         _background = new Background( backFilename, 0.5 );
00405         _background->setHeight( _height );
00406         _background->setWidth( _width );
00407 
00408         Uint32* texturePixels = (Uint32*)surface->pixels;
00409         Uint32* colPixels = (Uint32*)colSurface->pixels;
00410         Uint32 colPixel;
00411         
00412 
00413 
00414         //int maxoffset = surface->h*surface->w;
00415         for(int i=0; i < surface->h ; i++ ){
00416                 for( int j=0 ; j < surface->w ;j++){
00417                         if(TEXTURES[texturePixels[i*surface->w+j]]!=NULL)
00418                         {
00419                                 t = new Tile(   TEXTURES[texturePixels[i*surface->w+j]]->instance(), 
00420                                         true, j*tileWidth, i*tileHeight);
00421 
00422                                 colPixel = colPixels[ i*colSurface->w + j ];
00423                                 if( colPixel == Level::WALKBEHIND )
00424                                 {
00425                                         t->setCollidable( false );
00426                                         t->setDepth( 5 );
00427                                 } else if( colPixel == Level::WALKINFRONT )
00428                                 {
00429                                         t->setCollidable( false );
00430                                         t->setDepth( -1 );
00431                                 } else if( colPixel == Level::WALKINTO )
00432                                 {
00433                                         t->setCollidable( true );
00434                                         t->setDepth( 0 );
00435                                 }
00436 
00437                                 registerTile( t, i, j );
00438                                 //cerr << i << " " << j << endl;
00439                         }
00440                 }
00441         }
00442 
00443         SDL_UnlockSurface(surface);
00444         SDL_UnlockSurface(colSurface);
00445         SDL_FreeSurface(surface);
00446         SDL_FreeSurface(colSurface);
00447 
00448 
00449         
00450         /*
00451         for(int i = _width - tileWidth; i >= 0; i -= tileWidth) {
00452                 for(int j = _height - tileHeight; j >= 0; j -= tileHeight) {
00453                         Tile* tile  = getTileFromPixels(i,j);
00454                         if(tile != NULL)
00455                                 tile->getDrawBox();
00456                 }
00457         }
00458         */
00459 
00460         for(int j = 0; j < _height; j += tileHeight) {
00461                 for(int i = 0; i < _width; i += tileWidth) {
00462                         Tile* tile  = getTileFromPixels(i,j);
00463                         if(tile && tile->getDraw()) {
00464                                 tile->calcDrawBox();
00465                                 //exit(0);
00466                                 //tile->getDrawBox();
00467                         }
00468                         //if(tile && tile->getDraw())
00469                         //      cerr << i << " " << j << " " << tile->getDrawBox().w << " " << tile->getDrawBox().h << endl;
00470                 }
00471         }
00472 }
00473 
00474 bool Level::update()
00475 {
00476         if(_timed && !_cutScene)
00477                 _levelTimer--;
00478 
00479         if(_levelTimer == 0)
00480         {
00481                 _player->die();
00482                 _won = true;
00483         }
00484         
00485         Object* o;
00486 
00487         while( !_deleteQueue.empty() )
00488         {
00489                 o = _deleteQueue.front();
00490                 _deleteQueue.erase( remove( _deleteQueue.begin(), _deleteQueue.end(), o ), _deleteQueue.end() ); 
00491                 
00492 
00493                 if(o == this->_player)
00494                 {
00495                         // this early return is important for dying to work properly
00496                         _player = (Player *)_player->copy();
00497                         deleteObject( o );
00498                         return false;
00499                 }
00500                 deleteObject( o );
00501         }
00502 
00503         while( !_addQueue.empty() )
00504         {
00505                 o = _addQueue.front();
00506                 addObject( o, _objects );
00507                 _addQueue.pop();
00508         }
00509 
00510         CommandManager::instance()->startTimestep();
00511 
00512         Control::update();
00513         Screen::instance()->update();
00514 
00515         
00516         for( vector< Object* >::iterator i = _objects.begin(); i != _objects.end(); i++ )
00517         {
00518                 (*i)->update();
00519         }
00520 
00521         return true;
00522 }
00523 
00524 void Level::draw()
00525 {
00526         // Draw background
00527         _background->draw();
00528 
00529         // Draw all drawable objects
00530         for( vector< Object* >::iterator i = _drawnObjects.begin(); i != _drawnObjects.end(); i++ )
00531         {
00532                 (*i)->draw();
00533         }
00534 
00535         drawHUD();
00536 
00537         if(_cutScene) {
00538                 Screen::instance()->drawCutScene(_cutSceneText);
00539         }
00540 }
00541 
00542 void Level::drawHUD()
00543 {
00544         SDL_Rect raster;
00545 
00546         Sprite *health = Sprite::loadSprite("sprites/health.png");
00547         Sprite *heart = Sprite::loadSprite("sprites/heart.png");
00548 
00549         raster.x = 5;
00550         raster.y = 5;
00551 
00552         health->draw(raster.x,raster.y,Sprite::SCREEN);
00553 
00554         raster.x += health->width() + 2;
00555         raster.y += 5;
00556 
00557         for(int i = 0; i < _player->getHealth(); i++) {
00558                 heart->draw(raster.x,raster.y,Sprite::SCREEN);
00559                 raster.x += heart->width() + 2;
00560         }
00561         
00562         raster.x = 5;
00563         raster.y += health->height();
00564 
00565         if(_timed)
00566         {
00567                 int secs = ((int)_levelTimer/Screen::FRAMERATE)%5999;
00568                 stringstream timer;
00569                 timer << "Time Left: ";
00570                 if(secs%60 < 10)
00571                         timer << secs/60 << ":0" << secs%60;
00572                 else
00573                         timer << secs/60 << ":" << secs%60;
00574                 glfuncs::instance()->glPrint(raster.x,raster.y,timer.str());
00575         }
00576 
00577         raster.x += 270;
00578 
00579         if(_totBad > 0)
00580         {
00581                 stringstream bad;
00582                 bad << "Enemies: ";
00583                 bad << _killed << "/" << _totBad ;
00584                 glfuncs::instance()->glPrint(raster.x,raster.y,bad.str());
00585         }
00586 
00587         //glfuncs::instance()->glDisable(GL_TEXTURE_2D);
00588         raster.x = 710;
00589         raster.y = 6;
00590         //glfuncs::instance()->glRasterPos2f(raster.x,raster.y);
00591 
00592         stringstream score;
00593         score << "Score: ";
00594         score << _score;
00595         glfuncs::instance()->glPrint(raster.x,raster.y,score.str());
00596 
00597 
00598 
00599         raster.y += 30;
00600         _player->drawSecondaryAmmo(raster);
00601 
00602         //glfuncs::instance()->glEnable(GL_TEXTURE_2D);
00603 }
00604 
00605 // Schedule an object to be added to the level
00606 void Level::registerObject( Object* o )
00607 {
00608         _addQueue.push( o );
00609 }
00610 
00611 void Level::registerTile( Tile* t, int h, int w )
00612 {
00613         //if( t->collidable() )
00614                 _tiles[ h*_width + w ] = t;
00615 
00616         // Add to _drawnObjects vector in depth sorted order
00617         vector< Object* >::iterator i = _drawnObjects.begin();
00618                 
00619         while( i != _drawnObjects.end() && t->getDepth() > (*i)->getDepth() )
00620                 i++;
00621 
00622         _drawnObjects.insert( i, t );
00623 }
00624 
00625 
00626 // Add the object to _drawnObjects, sorted in depth ordering,
00627 // then add the object to vec for collision detection
00628 void Level::addObject( Object* o, std::vector< Object* >& vec )
00629 {
00630         // Add to collision detection vector
00631         vec.push_back( o );
00632 
00633         // Add to _drawnObjects vector in depth sorted order
00634         vector< Object* >::iterator i = _drawnObjects.begin();
00635                 
00636         while( i != _drawnObjects.end() && o->getDepth() > (*i)->getDepth() )
00637                 i++;
00638 
00639         _drawnObjects.insert( i, o );
00640         _ids[o->id()] = o;
00641 
00642         /*
00643         cerr << "Registering : " << endl;
00644         cerr << o->id() << endl;
00645         cerr << o->getDepth() << endl;
00646         cerr << j << endl << endl;
00647         */
00648 }
00649 
00650 Object *Level::getObject( std::string id )
00651 {
00652         return _ids[id];
00653 }
00654 
00655 Level *Level::instance()
00656 {
00657         if(!_instance)
00658                 return new Level();
00659         else
00660                 return _instance;
00661 }
00662 
00663 void Level::scheduleDelete( Object* o )
00664 {
00665         _deleteQueue.push_back( o );
00666 }
00667 
00668 void Level::deleteObject( Object* o )
00669 {
00670         _objects.erase( remove( _objects.begin(), _objects.end(), o ), _objects.end() ); 
00671         _drawnObjects.erase( remove( _drawnObjects.begin(), _drawnObjects.end(), o ), _drawnObjects.end() ); 
00672         if(o->getType() != TILE)
00673                 _ids.erase(o->id());
00674         Control::detachController( o );
00675         delete o;
00676 }
00677 
00678 void Level::setCutScene(bool cutScene)
00679 {
00680         _cutScene = cutScene;
00681 }
00682 
00683 Mix_Chunk* Level::getSound( std::string filename )
00684 {
00685         assert( _sounds.find( filename ) != _sounds.end() );
00686         return _sounds[ filename ];
00687 }
00688 
00689 void Level::loadSound( std::string filename )
00690 {
00691         // If the sound isn't already in the map, load it in
00692         if( _sounds.find( filename ) == _sounds.end() )
00693         {
00694                 _sounds[ filename ] = Mix_LoadWAV( filename.c_str() );
00695         }
00696 }

Generated on Fri May 5 00:20:18 2006 for ProjectX by  doxygen 1.4.6-NO