00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "Starfield.hpp"
00020 #include "MathFuncs.hpp"
00021 #include "Singletons.hpp"
00022
00023 #include <cstdio>
00024 #include <cassert>
00025
00026 CStarfield::CStarfield()
00027 : m_SpawnPlanets(true),
00028 m_PlanetSpawnTime(0),
00029 m_Width(SCREEN_X_SIZE - HUD_SIZE_X)
00030 {}
00031
00032 CStarfield::~CStarfield()
00033 {
00034 CleanUp();
00035 }
00036
00037 void CStarfield::CleanUp()
00038 {
00039 std::list<CStar*>::iterator ListIterator;
00040
00041 ListIterator = m_StarsBack.begin();
00042 while(ListIterator != m_StarsBack.end())
00043 {
00044 delete (*ListIterator);
00045
00046 ++ListIterator;
00047 }
00048 m_StarsBack.clear();
00049
00050 ListIterator = m_StarsFront.begin();
00051 while(ListIterator != m_StarsFront.end())
00052 {
00053 delete (*ListIterator);
00054
00055 ++ListIterator;
00056 }
00057 m_StarsFront.clear();
00058
00059 m_AsteroidData.clear();
00060 }
00061
00062
00063 void CStarfield::Init(const std::string& FileName)
00064 {
00065 CleanUp();
00066
00067 int Layer = 0;
00068
00069 int StarCount = 200;
00070 std::string StarName = "data/background/Star.png";
00071 ReadData(FileName, &StarName, &StarCount);
00072
00073 for(unsigned CurStar = 0; CurStar < StarCount; CurStar++)
00074 {
00075 Layer = std::rand() % 128;
00076
00077 CStar* Star = new CStar;
00078 Star->Init(StarName, Layer, false, m_Width);
00079
00080 if(Layer < STARFIELD_STAR_FRONT)
00081 {
00082 InsertStarBack(Star);
00083 }
00084 else
00085 {
00086 InsertStarFront(Star);
00087 }
00088 }
00089 }
00090
00091 void CStarfield::ReadData(std::string FileName, std::string* StarFile, int* StarCount)
00092 {
00093
00094
00095 if(StarFile == NULL || StarCount == NULL)
00096 {
00097 return;
00098 }
00099
00100 FILE* BackFile = std::fopen(FileName.c_str(),"r");
00101 if(BackFile == NULL)
00102 {
00103 return;
00104 }
00105
00106 char strBuf[100];
00107 std::string HelpString;
00108 std::string OldString;
00109 std::string DataString;
00110
00111 int AsteroidFrameX = 0;
00112 int AsteroidFrameY = 0;
00113 int AsteroidFrameCount = 0;
00114
00115
00116 while(std::feof(BackFile) == 0)
00117 {
00118 std::fscanf(BackFile,"%s",strBuf);
00119 HelpString = strBuf;
00120
00121 if(HelpString == "=")
00122 {
00123 if(OldString == "Star")
00124 {
00125 std::fscanf(BackFile,"%s",strBuf);
00126 (*StarFile) = strBuf;
00127 }
00128 else if(OldString == "StarCount")
00129 {
00130 std::fscanf(BackFile,"%d",StarCount);
00131 }
00132
00133 else if(OldString == "Planet")
00134 {
00135 std::fscanf(BackFile,"%s",strBuf);
00136 DataString = strBuf;
00137 m_PlanetFiles.push_back(DataString);
00138 }
00139
00140 else if(OldString == "AsteroidFrameX")
00141 {
00142 std::fscanf(BackFile,"%d",&AsteroidFrameX);
00143 }
00144 else if(OldString == "AsteroidFrameY")
00145 {
00146 std::fscanf(BackFile,"%d",&AsteroidFrameY);
00147 }
00148 else if(OldString == "AsteroidFrameCount")
00149 {
00150 std::fscanf(BackFile,"%d",&AsteroidFrameCount);
00151 }
00152
00153 else if(OldString == "Asteroid")
00154 {
00155 AsteroidData* Data = new AsteroidData;
00156 Data->FrameX = AsteroidFrameX;
00157 Data->FrameY = AsteroidFrameY;
00158 Data->FrameCount = AsteroidFrameCount;
00159
00160 std::fscanf(BackFile,"%s",strBuf);
00161 DataString = strBuf;
00162 Data->FileName = DataString;
00163
00164 m_AsteroidData.push_back(Data);
00165 }
00166 }
00167
00168 OldString = HelpString;
00169 }
00170
00171 std::fclose(BackFile);
00172 }
00173
00174 void CStarfield::DrawBack()
00175 {
00176 std::list<CStar*>::iterator ListIterator;
00177
00178 ListIterator = m_StarsBack.begin();
00179 while(ListIterator != m_StarsBack.end())
00180 {
00181 assert (*ListIterator);
00182 (*ListIterator)->Draw();
00183
00184 if((*ListIterator)->CanBeRemoved() == true)
00185 {
00186 delete (*ListIterator);
00187 m_StarsBack.erase(ListIterator++);
00188 }
00189 else
00190 {
00191 ++ListIterator;
00192 }
00193 }
00194 if(m_SpawnPlanets == true)
00195 {
00196 CheckForNewPlanet();
00197 CheckForNewAsteroids();
00198 }
00199 }
00200
00201 void CStarfield::DrawFront()
00202 {
00203 std::list<CStar*>::iterator ListIterator;
00204
00205 ListIterator = m_StarsFront.begin();
00206 while(ListIterator != m_StarsFront.end())
00207 {
00208 (*ListIterator)->Draw();
00209
00210 if((*ListIterator)->CanBeRemoved() == true)
00211 {
00212 delete (*ListIterator);
00213 m_StarsFront.erase(ListIterator++);
00214 }
00215 else
00216 {
00217 ++ListIterator;
00218 }
00219 }
00220
00221 }
00222
00223 void CStarfield::InsertStarBack(CStar* Star)
00224 {
00225 std::list<CStar*>::iterator ListIterator;
00226
00227 int Index = -1;
00228 int CurIndex = 0;
00229 ListIterator = m_StarsBack.begin();
00230
00231 while(ListIterator != m_StarsBack.end())
00232 {
00233 if((*ListIterator)->GetLayer() > Star->GetLayer())
00234 {
00235 Index = CurIndex;
00236 break;
00237 }
00238
00239 ListIterator++;
00240 CurIndex++;
00241 }
00242
00243 if(Index == -1)
00244 {
00245 m_StarsBack.push_back(Star);
00246 }
00247 else if(Index == 0)
00248 {
00249 m_StarsBack.push_front(Star);
00250 }
00251 else
00252 {
00253 m_StarsBack.insert(ListIterator, Star);
00254 }
00255 }
00256
00257 void CStarfield::InsertStarFront(CStar* Star)
00258 {
00259 std::list<CStar*>::iterator ListIterator;
00260
00261 int Index = -1;
00262 int CurIndex = 0;
00263 ListIterator = m_StarsFront.begin();
00264
00265 while(ListIterator != m_StarsFront.end())
00266 {
00267 if((*ListIterator)->GetLayer() > Star->GetLayer())
00268 {
00269 Index = CurIndex;
00270 break;
00271 }
00272
00273 ++ListIterator;
00274 ++CurIndex;
00275 }
00276
00277 if(Index == -1)
00278 {
00279 m_StarsFront.push_back(Star);
00280 }
00281 else if(Index == 0)
00282 {
00283 m_StarsFront.push_front(Star);
00284 }
00285 else
00286 {
00287 m_StarsFront.insert(ListIterator, Star);
00288 }
00289 }
00290
00291
00292 void CStarfield::RemovePlanets()
00293 {
00294 std::list<CStar*>::iterator ListIterator;
00295
00296 ListIterator = m_StarsBack.begin();
00297 while(ListIterator != m_StarsBack.end())
00298 {
00299 if((*ListIterator)->IsPlanet() == true)
00300 {
00301 delete (*ListIterator);
00302 m_StarsBack.erase(ListIterator++);
00303 }
00304 else
00305 {
00306 ++ListIterator;
00307 }
00308 }
00309 }
00310
00311 void CStarfield::CheckForNewPlanet()
00312 {
00313 if(m_PlanetFiles.size() == 0 || STARFIELD_PLANET_MAXCHANCE == 0 ||
00314 sgl::get_clock().GetElapsedTime()*1000 - m_PlanetSpawnTime < STARFIELD_PLANET_DELAY)
00315 {
00316 return;
00317 }
00318
00319 int CurChance = (std::rand() % STARFIELD_PLANET_MAXCHANCE);
00320
00321 if(CurChance <= STARFIELD_PLANET_CHANCE)
00322 {
00323 int FileIndex = std::rand() % m_PlanetFiles.size();
00324 int Layer = std::rand() % 20;
00325
00326 if(m_PlanetFiles.size() > 1)
00327 {
00328 while(FileIndex == m_LastPlanet)
00329 {
00330 FileIndex = std::rand() % m_PlanetFiles.size();
00331 }
00332 }
00333
00334 m_LastPlanet = FileIndex;
00335
00336 m_PlanetSpawnTime = sgl::get_clock().GetElapsedTime()*1000;
00337
00338 CStar* Star = new CStar;
00339 Star->Init(m_PlanetFiles[FileIndex], Layer, true, m_Width);
00340
00341 InsertStarBack(Star);
00342 }
00343 }
00344
00345
00346 void CStarfield::CheckForNewAsteroids()
00347 {
00348 if(m_AsteroidData.size() == 0 || STARFIELD_ASTEROID_MAXCHANCE == 0)
00349 {
00350 return;
00351 }
00352
00353 int CurChance = (std::rand() % STARFIELD_ASTEROID_MAXCHANCE);
00354
00355 if(CurChance <= STARFIELD_ASTEROID_CHANCE)
00356 {
00357
00358 int Dif = STARFIELD_ASTEROID_MAXSIZE - STARFIELD_ASTEROID_MINSIZE;
00359 int Count = STARFIELD_ASTEROID_MAXSIZE;
00360 if(Dif != 0)
00361 {
00362 Count = STARFIELD_ASTEROID_MINSIZE + (rand() % (Dif + 1));
00363 }
00364
00365 int SgnX = -1;
00366 if(std::rand() % 100 < 50)
00367 {
00368 SgnX = 1;
00369 }
00370
00371 int SgnY = 1;
00372
00373 float XSpeed = frnd(ASTEROID_MIN_SPEED * SgnX,ASTEROID_MAX_SPEED * SgnX);
00374 float YSpeed = frnd(ASTEROID_MIN_SPEED * SgnY,ASTEROID_MAX_SPEED * SgnY);
00375
00376 float X = frnd(0.0f, SCREEN_X_SIZE);
00377 X -= STAR_ASTEROID_RADIUS * sgn(XSpeed);
00378 float Y = frnd(0.0f, -STAR_ASTEROID_RADIUS -150.0f * sgn(YSpeed));
00379 Y -= STAR_ASTEROID_RADIUS * sgn(YSpeed);
00380
00381 if(sgn(Y) > 0)
00382 {
00383 Y += SCREEN_Y_SIZE;
00384 }
00385
00386 int CurAsteroid = 0;
00387 for(CurAsteroid = 0; CurAsteroid < Count; CurAsteroid++)
00388 {
00389 int FileIndex = std::rand() % m_AsteroidData.size();
00390 int Layer = rand() % 20 + 21;
00391
00392 CStar* Star = new CStar;
00393 Star->InitAsteroid(m_AsteroidData[FileIndex], Layer, XSpeed, YSpeed, X, Y);
00394
00395 InsertStarBack(Star);
00396 }
00397 }
00398 }
00399
00400
00401 void CStarfield::SetWidth(int Width)
00402 {
00403 std::list<CStar*>::iterator ListIterator;
00404
00405 ListIterator = m_StarsBack.begin();
00406 while(ListIterator != m_StarsBack.end())
00407 {
00408 (*ListIterator)->SetFieldWidth(Width);
00409 (*ListIterator)->SetPosition(rand() % Width, (rand() % (SCREEN_Y_SIZE + 100) - 100));
00410
00411 ++ListIterator;
00412 }
00413 }
00414