- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

# 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 }