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
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
00108
00109 if(object->getType() == BULLET)
00110 ((Bullet *)object)->setShooter(_player);
00111 }
00112
00113 _player = (Player*)_ids["goudy1"];
00114
00115 SetControlCommand(_player).execute();
00116
00117
00118 Screen::instance()->registerFollowObj(_player);
00119 }
00120 }
00121
00122 void Level::reset()
00123 {
00124 restore();
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
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
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
00195 string objFile = filename;
00196
00197
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
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
00235 Sprite * sprite = Sprite::loadSprite(filename);
00236
00237
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
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
00271
00272
00273
00274
00275 _player = (Player *)_ids["goudy1"];
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295 Screen::instance()->registerFollowObj( (Object*)_player );
00296 SetControlCommand(_player).execute();
00297
00298
00299 SaveCommand().execute();
00300
00301
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
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
00363 int i = 0;
00364 do
00365 {
00366 i++;
00367 stringstream num;
00368 num << i;
00369 o->setId(id+num.str());
00370
00371
00372
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
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
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
00452
00453
00454
00455
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
00466
00467 }
00468
00469
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
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
00527 _background->draw();
00528
00529
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
00588 raster.x = 710;
00589 raster.y = 6;
00590
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
00603 }
00604
00605
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
00614 _tiles[ h*_width + w ] = t;
00615
00616
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
00627
00628 void Level::addObject( Object* o, std::vector< Object* >& vec )
00629 {
00630
00631 vec.push_back( o );
00632
00633
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
00644
00645
00646
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
00692 if( _sounds.find( filename ) == _sounds.end() )
00693 {
00694 _sounds[ filename ] = Mix_LoadWAV( filename.c_str() );
00695 }
00696 }