00001
00002
00003
00004 #ifdef WIN32
00005 #pragma warning(disable : 4786 )
00006 #endif
00007
00008 #include "CSWorld.h"
00009 #include "CSXMLHelper.h"
00010 #include "CSMusic.h"
00011
00012 CSWorldLoader CSWorldLoader::INSTANCE;
00013 const char *CSWorld::CLASS = "CSWorld";
00014
00015 CSWorld::CSWorld(const std::string &filename)
00016 {
00017 static char *functionName="CSWorld";
00018 LOG_ENTER
00019 CSWorldData data;
00020 loadWorldData(filename, data);
00021 initialize(data);
00022 LOG_EXIT
00023 }
00024
00025
00026 CSWorld::CSWorld(const CSWorld &world)
00027 {
00028 static char *functionName="CSWorld";
00029 LOG_ENTER
00030 initialize();
00031 mId = strdup(world.mId);
00032 mLayers = world.mLayers;
00033 LOG_EXIT
00034 }
00035
00036 void CSWorld::initialize(void)
00037 {
00038 static char *functionName="initialize";
00039 LOG_ENTER
00040 mFactor = 0;
00041 mId = 0;
00042 mScaleMapCount = 0;
00043 mWorld = 0;
00044 mLayers = 0;
00045 mMapArea.x = 0;
00046 mMapArea.y = 0;
00047 mMapArea.w = 0;
00048 mMapArea.h = 0;
00049 mXOffset = 0;
00050 mYOffset = 0;
00051 mHeight = 0;
00052 mWidth = 0;
00053 mXPos = 0;
00054 mYPos = 0;
00055 mWorldNo = 0;
00056 mMusic = 0;
00057 mActive = false;
00058 mScaledWorldDestination.x = 0;
00059 mScaledWorldDestination.y = 0;
00060 mScaledWorldDestination.w = 0;
00061 mScaledWorldDestination.h = 0;
00062 LOG_EXIT
00063 }
00064
00065 void CSWorld::scaleBackgroundTiles(int w, int h)
00066 {
00067 static char *functionName="scaleBackgroundTiles";
00068 LOG_ENTER
00069 if (mWorld != 0)
00070 {
00071 for (int l=0; l< mLayers; l++)
00072 {
00073 if (mWorld[l]->isBackground())
00074 {
00075 mWorld[l]->scaleMapToFit(w, h);
00076 }
00077 }
00078 }
00079 LOG_EXIT
00080 }
00081
00082 void CSWorld::initialize(const CSWorldData &data)
00083 {
00084 static char *functionName="initialize";
00085 LOG_ENTER
00086 initialize();
00087 mId = strdup(data.id);
00088 mLayers = data.layers;
00089
00090 mWorld = (CSTileMap **) new void *[data.layers];
00091
00092 for (int l=0; l< data.layers; l++)
00093 {
00094 MapData *mapData = data.maps->at(l);
00095 CSTileMap *map = CSTileMapLoader::INSTANCE.load(mapData->name);
00096 map->setOffset(mapData->offsetX, mapData->offsetY);
00097 map->setBackground(mapData->isBackground);
00098
00099 map->setParallax(mapData->isParallax);
00100 if (l==0)
00101 {
00102 map->setSolid(true);
00103 }
00104 mWorld[l] = map;
00105 if (!mapData->isBackground)
00106 {
00107 if (map->getHeight() > mHeight) mHeight = map->getHeight();
00108 if (map->getWidth() > mWidth) mWidth = map->getWidth();
00109 }
00110 }
00111 if (mWorld != 0)
00112 {
00113 for (int l=0; l< mLayers; l++)
00114 {
00115 mWorld[l]->setWorldMax(mWidth, mHeight);
00116 }
00117 }
00118 if (data.musicName != 0)
00119 {
00120 mMusic = CSMusicLoader::INSTANCE.load(data.musicName);
00121 mMusic->play();
00122 }
00123 LOG_EXIT
00124 }
00125
00126 CSWorld::~CSWorld()
00127 {
00128 static char *functionName="~CSWorld";
00129 LOG_ENTER
00130 if (mId != 0)
00131 {
00132 free(mId);
00133 mId = 0;
00134 }
00135
00136 if (mWorld != 0)
00137 {
00138 for (int l=0; l< mLayers; l++)
00139 {
00140 delete mWorld[l];
00141 }
00142 delete[] mWorld;
00143 mWorld = 0;
00144 }
00145 if (mMusic != 0)
00146 {
00147
00148 mMusic->stop();
00149 mMusic = 0;
00150 }
00151 LOG_EXIT
00152 }
00153
00154 void CSWorld::display()
00155 {
00156 static char *functionName="display";
00157 SDL_SetClipRect(SDLMain::getScreen(), &mMapArea);
00158
00159 if (mWorld != 0)
00160 {
00161 for (int l=0; l< mLayers; l++)
00162 {
00163 mWorld[l]->display();
00164 }
00165 }
00166 SDL_SetClipRect(SDLMain::getScreen(), 0);
00167 }
00168
00169 void CSWorld::setWorldNo(unsigned int no)
00170 {
00171 static char *functionName="setWorldNo";
00172 LOG_ENTER
00173 mWorldNo = no;
00174 if (mWorld != 0)
00175 {
00176 for (int l=0; l< mLayers; l++)
00177 {
00178 mWorld[l]->setWorldNo(no);
00179 }
00180 }
00181 LOG_EXIT
00182 }
00183
00184 void CSWorld::setTile(unsigned int x, unsigned int y, unsigned int z, char idChar)
00185 {
00186 static char *functionName="setTile";
00187 mWorld[z]->setTile(x, y, idChar);
00188 }
00189
00190 void CSWorld::setTile(unsigned int x, unsigned int y, unsigned int z, CSTile *tile)
00191 {
00192 static char *functionName="setTile";
00193 mWorld[z]->setTile(x, y, tile);
00194 }
00195
00196 void CSWorld::update()
00197 {
00198 static char *functionName="update";
00199 if (mWorld != 0)
00200 {
00201 for (int l=0; l< mLayers; l++)
00202 {
00203 mWorld[l]->update();
00204 }
00205 }
00206 }
00207
00208 void CSWorld::setDisplayArea(SDL_Rect area)
00209 {
00210 static char *functionName="setDisplayArea";
00211 LOG_ENTER
00212 mMapArea = area;
00213 mXOffset = area.x;
00214 mYOffset = area.y;
00215
00216 if (mWorld != 0)
00217 {
00218 for (int l=0; l< mLayers; l++)
00219 {
00220 mWorld[l]->setDisplayOffset(mXOffset, mYOffset);
00221 mWorld[l]->setDisplaySize(mMapArea.w, mMapArea.h);
00222 }
00223 }
00224 LOG_EXIT
00225 }
00226
00227 void CSWorld::setWorldPosition(int x, int y)
00228 {
00229 static char *functionName="setWorldPosition";
00230 mXPos = x;
00231 mYPos = y;
00232 if (mWorld != 0)
00233 {
00234 for (int l=0; l< mLayers; l++)
00235 {
00236 mWorld[l]->setMapPosition(x,y);
00237 }
00238 }
00239
00240 CSSprites::iterator iter = mSprites.begin();
00241 while (iter != mSprites.end())
00242 {
00243 CSSprite *sprite = *iter;
00244 sprite->setWorldPosition(x, y);
00245 iter++;
00246 }
00247 }
00248
00249 void CSWorld::setSecPerFrame(float secPerFrame)
00250 {
00251 static char *functionName="setSecPerFrame";
00252 LOG_ENTER
00253 if (mWorld != 0)
00254 {
00255 for (int l=0; l< mLayers; l++)
00256 {
00257 mWorld[l]->setSecPerFrame(secPerFrame);
00258 }
00259 }
00260 CSSprites::iterator iter = mSprites.begin();
00261 while (iter != mSprites.end())
00262 {
00263 CSSprite *sprite = *iter;
00264 sprite->setSecPerFrame(secPerFrame);
00265 iter++;
00266 }
00267 LOG_EXIT
00268 }
00269
00270 void CSWorld::loadWorldData(const std::string &filename, CSWorldData &data)
00271 {
00272 static char *functionName="loadWorldData";
00273 LOG_ENTER
00274 char tmp[10];
00275 CSXMLHelper xmlSupport(filename, "WORLD");
00276 try
00277 {
00278 if (xmlSupport.getError())
00279 {
00280 LOG_EXIT
00281 throw "error";
00282 }
00283
00284 data.id = strdup(xmlSupport.getString("ID").c_str());
00285 int mapCount = xmlSupport.getInt("count(MAPS/MAP)");
00286 for (int i=0; i<mapCount; i++)
00287 {
00288 MapData *map = new MapData();
00289
00290 std::string a = xmlSupport.getString((std::string)"MAPS/MAP["+itoa(i+1,tmp,10)+"]/NAME");
00291 map->name = strdup(a.c_str());
00292
00293 int hasOffsetData = xmlSupport.getInt((std::string)"count(MAPS/MAP["+itoa(i+1,tmp,10)+"]/OFFSET_X)");
00294 if (hasOffsetData == 1)
00295 {
00296 map->offsetX = xmlSupport.getInt((std::string)"MAPS/MAP["+itoa(i+1,tmp,10)+"]/OFFSET_X");
00297 map->offsetY = xmlSupport.getInt((std::string)"MAPS/MAP["+itoa(i+1,tmp,10)+"]/OFFSET_Y");
00298 }
00299 map->isBackground = xmlSupport.getInt((std::string)"count(MAPS/MAP["+itoa(i+1,tmp,10)+"]/BACKGROUND)") == 1;
00300 map->isParallax = xmlSupport.getInt((std::string)"count(MAPS/MAP["+itoa(i+1,tmp,10)+"]/PARALLAX)") == 1;
00301 data.maps->push_back(map);
00302 }
00303 data.layers = mapCount;
00304 bool hasMusic = xmlSupport.getInt((std::string)"count(MUSIC)") == 1;
00305 if (hasMusic)
00306 {
00307 data.musicName = strdup(xmlSupport.getString("MUSIC").c_str());
00308 }
00309 }
00310 catch(...)
00311 {
00312 LOG_EXIT
00313 SDLMain::shutdown((std::string)"XML error \"" + filename + "\": " + xmlSupport.getErrorMessage().c_str(), 1);
00314 }
00315 LOG_EXIT
00316 }
00317
00318
00319 void CSWorld::addSprite(CSSprite *sprite)
00320 {
00321 static char *functionName="addSprite";
00322 LOG_ENTER
00323
00324 removeSprite(sprite);
00325 mSprites.push_back(sprite);
00326
00327 if (mWorld != 0)
00328 {
00329 if (sprite->getLayer() < 0)
00330 {
00331
00332 mWorld[mLayers-1]->addSprite(sprite);
00333 return;
00334 LOG_EXIT
00335 }
00336 if (sprite->getLayer() < mLayers)
00337 {
00338 mWorld[sprite->getLayer()]->addSprite(sprite);
00339 }
00340 else
00341 {
00342 LOG_EXIT
00343 SDLMain::shutdown((std::string)"Sprite-Layer-Error!", 1);
00344 }
00345 }
00346 LOG_EXIT
00347 }
00348
00349 void CSWorld::removeSprite(CSSprite *sprite)
00350 {
00351 static char *functionName="removeSprite";
00352 LOG_ENTER
00353 CSSprites::iterator iter = mSprites.begin();
00354 while (iter != mSprites.end())
00355 {
00356 if ((*iter) == sprite)
00357 {
00358 mSprites.erase(iter);
00359 iter = mSprites.begin();
00360 }
00361 else
00362 {
00363 iter++;
00364 }
00365 }
00366 if (mWorld != 0)
00367 {
00368 if (sprite->getLayer() < 0)
00369 {
00370
00371 mWorld[mLayers-1]->removeSprite(sprite);
00372 LOG_EXIT
00373 return;
00374 }
00375 if (sprite->getLayer() < mLayers)
00376 {
00377 mWorld[sprite->getLayer()]->removeSprite(sprite);
00378 }
00379 else
00380 {
00381 LOG_EXIT
00382 SDLMain::shutdown((std::string)"Sprite-Layer-Error!", 1);
00383 }
00384 }
00385 LOG_EXIT
00386 }
00387
00388 void CSWorld::buildScaledWorld(double factor, const SDL_Rect &sourceRect, SDL_Surface *destination, const SDL_Rect &displayRect)
00389 {
00390 static char *functionName="buildScaledWorld";
00391 bool isNew = false;
00392 mFactor = factor;
00393 SDL_Rect destRect;
00394 SDL_Rect srcRect;
00395 bool first = true;
00396 if (mWorld != 0)
00397 {
00398 for (int l=0; l< mLayers; l++)
00399 {
00400 if (mWorld[l]->isScaleDisplay())
00401 {
00402 destRect.x = displayRect.x;
00403 destRect.y = displayRect.y;
00404 destRect.w = displayRect.w;
00405 destRect.h = displayRect.h;
00406 srcRect.x = sourceRect.x;
00407 srcRect.y = sourceRect.y;
00408 srcRect.w = sourceRect.w;
00409 srcRect.h = sourceRect.h;
00410 SDL_Surface *src = mWorld[l]->getScaledMap(factor, first);
00411 first = false;
00412
00413 if (SDL_BlitSurface(src, &srcRect, destination, &destRect) < 0)
00414 {
00415 SDLMain::shutdown((std::string)"Display Format error (buildScaledWorld()): " + SDL_GetError(), 1);
00416 }
00417 }
00418 }
00419 }
00420
00421 if (mWorld != 0)
00422 {
00423 for (int l=0; l< mLayers; l++)
00424 {
00425 mWorld[l]->addScaledSprites(factor, sourceRect, destination, displayRect);
00426 }
00427 }
00428 }
00429
00430 void CSWorld::resetScaledWorld()
00431 {
00432 static char *functionName="resetScaledWorld";
00433 LOG_ENTER
00434 if (mWorld != 0)
00435 {
00436 for (int l=0; l< mLayers; l++)
00437 {
00438 mWorld[l]->resetScaledMap();
00439 }
00440 }
00441 LOG_EXIT
00442 }
00443
00444 void CSWorld::displayScaled(CSSprite *centerSprite)
00445 {
00446 static char *functionName="displayScaled";
00447 if ((mScaledWorldDestination.w == 0) || (mScaledWorldDestination.h == 0) || (mFactor == 0))
00448 {
00449 return;
00450 }
00451 int x = ((double)centerSprite->getXPos() + centerSprite->getMaxWidth()/2) * mFactor;
00452 int y = ((double)centerSprite->getYPos() + centerSprite->getMaxHeight()/2) * mFactor;
00453 int xOffset;
00454 int yOffset;
00455 int thresholdX = mScaledWorldDestination.w/2;
00456 int thresholdY = mScaledWorldDestination.h/2;
00457
00458 SDL_Rect srcRect;
00459 srcRect.w = mScaledWorldDestination.w;
00460 srcRect.h = mScaledWorldDestination.h;
00461
00462 xOffset = x-thresholdX;
00463 yOffset = y-thresholdY;
00464
00465 if (xOffset + mScaledWorldDestination.w > ((double)mWidth) * mFactor)
00466 {
00467 xOffset = ((double) (((double)mWidth) * mFactor)) - mScaledWorldDestination.w;
00468 }
00469 if (yOffset + mScaledWorldDestination.h >((double)mHeight) * mFactor)
00470 {
00471 yOffset = ((double) (((double)mHeight) * mFactor)) - mScaledWorldDestination.h;
00472 }
00473
00474 if (xOffset < 0)
00475 {
00476 xOffset = 0;
00477 }
00478 if (yOffset < 0)
00479 {
00480 yOffset = 0;
00481 }
00482
00483 srcRect.x = xOffset;
00484 srcRect.y = yOffset;
00485
00486 SDL_SetClipRect(SDLMain::getScreen(), &mScaledWorldDestination);
00487 SDL_Rect destRect = mScaledWorldDestination;
00488
00489 buildScaledWorld(mFactor, srcRect, SDLMain::getScreen(),destRect);
00490 SDL_SetClipRect(SDLMain::getScreen(), 0);
00491 }
00492
00493 void CSWorld::setScaleDisplayArea(SDL_Rect area)
00494 {
00495 static char *functionName="setScaleDisplayArea";
00496 LOG_ENTER
00497 mScaledWorldDestination = area;
00498 LOG_EXIT
00499 }