00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <string.h>
00018 #include <stdlib.h>
00019 #include "spritemanager.h"
00020 #include "ticktimer.h"
00021 #include "spriteloader.h"
00022
00029
00034 int SpriteManager::Event(int code, void *data1, void *data2)
00035 { return(0); }
00036
00041 void SpriteManager::Handler(SDL_Event *event)
00042 { }
00043
00048 void SpriteManager::Idle()
00049 { }
00050
00051
00056 SpriteManager::SpriteManager(Uint16 w, Uint16 h, Uint8 depth, Uint32 vflags)
00057 {
00058 flag=SM_TOTALREDRAW|SM_OWNBG;
00059
00060 lock=SDL_CreateMutex();
00061
00062 if(!SDL_WasInit(SDL_INIT_VIDEO))
00063 if(SDL_InitSubSystem(SDL_INIT_VIDEO)<0)
00064 {
00065 fprintf(stderr,"Warning, couldn't initialize SDL video\n");
00066 }
00067
00068 if(vflags&SDL_DOUBLEBUF)
00069 {
00070 fprintf(stderr,"SDL_DOUBLEBUF flag detected, using fullscreen flips\n");
00071 flag|=SM_DOUBLEBUF;
00072 }
00073
00074 screen=SDL_SetVideoMode(w,h,depth,SDL_ANYFORMAT|vflags);
00075
00076 if(screen==NULL)
00077 {
00078 fprintf(stderr,"SpriteManager::SpriteManager(%d,%d,%d,%d)\n",w,h,depth,vflags);
00079 fprintf(stderr,"Warning - can't set video mode!\n");
00080 }
00081
00082 bg=SDL_DisplayFormat(screen);
00083
00084 if(bg==NULL)
00085 {
00086 fprintf(stderr,"Error - can't create background!\n");
00087 }
00088 }
00089
00093 void SpriteManager::DrawOnBG(SDL_Surface *src, SDL_Rect *srcrect, SDL_Rect *destrect)
00094 {
00095 Lock();
00096
00097 SDL_BlitSurface(src,srcrect,bg,destrect);
00098
00099 flag|=SM_TOTALREDRAW;
00100
00101 Unlock();
00102 }
00103
00107 void SpriteManager::SendEvent(int code, void *data1, void *data2)
00108 {
00109 Sprite *spr=sprites.Head();
00110
00111 while(spr!=NULL)
00112 {
00113 spr->Event(code,data1,data2);
00114 spr=spr->next;
00115 }
00116 }
00117
00125 SMRun_Return SpriteManager::Run(Sint32 frametick, Sint32 gametick)
00126 {
00127 TickTimer frame,game;
00128 bool drawn=false;
00129
00130 flag|=SM_RUNNING;
00131 frame.Reset();
00132 game.Reset();
00133
00134 if((frametick<=0)||(gametick<=0))
00135 return(SMRUN_TIMESTEP);
00136
00137 while(flag&SM_RUNNING)
00138 {
00139 SDL_Event event;
00140 while(SDL_PollEvent(&event))
00141 switch(event.type)
00142 {
00143 case SDL_QUIT:
00144 flag&=~SM_RUNNING;
00145 break;
00146
00147 case SDL_USEREVENT:
00148
00149 if(!Event(event.user.code,event.user.data1,event.user.data2))
00150 {
00151
00152 SendEvent(event.user.code, event.user.data1, event.user.data2);
00153 }
00154 break;
00155
00156 default:
00157 Handler(&event);
00158 break;
00159 }
00160
00161 if(game>=gametick)
00162 {
00163
00164
00165
00166 int max_iterations=(game/gametick)*2;
00167 int iterations=0;
00168 drawn=false;
00169
00170 while(game>=gametick)
00171 {
00172 if(iterations>max_iterations)
00173 return(SMRUN_TIMESTEP);
00174
00175 if(!Paused()) Move(gametick);
00176
00177 game-=gametick;
00178 iterations++;
00179 }
00180 }
00181 else if(frame>=frametick)
00182 {
00183 if(!drawn)
00184 {
00185 drawn=true;
00186 Draw();
00187 Update();
00188 Preserve();
00189 }
00190 frame-=frametick;
00191 }
00192 else
00193 {
00194 Idle();
00195 SDL_Delay(10);
00196 }
00197 }
00198
00199 return(SMRUN_OK);
00200 }
00201
00209 SMRun_Return SpriteManager::Run(Sint32 frametick)
00210 {
00211 TickTimer timer;
00212 flag|=SM_RUNNING;
00213
00214 if(frametick<=0)
00215 return(SMRUN_TIMESTEP);
00216
00217 timer.Reset();
00218
00219 while(flag&SM_RUNNING)
00220 {
00221 SDL_Event event;
00222
00223 while(SDL_PollEvent(&event))
00224 switch(event.type)
00225 {
00226 case SDL_QUIT:
00227 flag&=~SM_RUNNING;
00228 break;
00229
00230 case SDL_USEREVENT:
00231
00232 if(!Event(event.user.code,event.user.data1,event.user.data2))
00233 {
00234
00235 SendEvent(event.user.code, event.user.data1, event.user.data2);
00236 }
00237 break;
00238
00239 default:
00240 Handler(&event);
00241 break;
00242 }
00243
00244
00245 if(timer>=frametick)
00246 {
00247 Draw();
00248 Update();
00249
00250 if(!Paused())
00251 {
00252 Preserve();
00253 while(timer>=frametick)
00254 {
00255 Move(frametick);
00256 timer-=frametick;
00257 }
00258 }
00259 }
00260 else
00261 {
00262 Idle();
00263 SDL_Delay(10);
00264 }
00265 }
00266
00267 return(SMRUN_OK);
00268 }
00269
00274 void SpriteManager::Preserve()
00275 {
00276 Sprite *spr=sprites.Head();
00277
00278 while(spr!=NULL)
00279 {
00280 spr->Preserve();
00281 spr=spr->next;
00282 }
00283 }
00284
00289 SpriteManager::SpriteManager(Uint16 flags,SDL_Surface *screenin,
00290 const char *bgnd)
00291 :rects(MAX_RECTS)
00292 {
00293 flag=flags|SM_TOTALREDRAW|SM_OWNBG;
00294
00295 lock=SDL_CreateMutex();
00296
00297 if(screenin==NULL)
00298 {
00299 screen=SDL_GetVideoSurface();
00300 if(screen==NULL)
00301 {
00302 fprintf(stderr,"Couldn't get video surface!\n");
00303 exit(1);
00304 }
00305
00306 if(bgnd==NULL)
00307 {
00308 bg=SDL_DisplayFormat(screen);
00309 }
00310 else
00311 {
00312 bg=LoadConvertBMP(bgnd);
00313 }
00314 }
00315 else
00316 {
00317 screen=screenin;
00318
00319 if(bgnd==NULL)
00320 {
00321 bg=SDL_DisplayFormat(screen);
00322 }
00323 else
00324 {
00325 bg=LoadConvertBMP(bgnd);
00326 }
00327 }
00328 }
00329
00333 bool SpriteManager::AddSprite(Sprite *spr)
00334 {
00335 bool retval;
00336
00337 Lock();
00338 retval=sprites.Insert(spr);
00339 Unlock();
00340
00341 return(retval);
00342 }
00343
00347 bool SpriteManager::RemoveSprite(Sprite *spr)
00348 {
00349 bool retval;
00350
00351 Lock();
00352 retval=sprites.Extract(spr);
00353 Unlock();
00354
00355 return(retval);
00356 }
00357
00361 void SpriteManager::Draw()
00362 {
00363
00364 if(flag&(SM_TOTALREDRAW|SM_DOUBLEBUF))
00365 {
00366 flag&=~SM_TOTALREDRAW;
00367 SimpleBlit();
00368 }
00369 else
00370 {
00371 QuadBlit();
00372 }
00373 }
00374
00378 void SpriteManager::Move(Sint32 dtick)
00379 {
00380 Sprite *spr=NULL;
00381
00382 Lock();
00383
00384 spr=sprites.Head();
00385 while(spr!=NULL)
00386 {
00387 if(spr->Expired())
00388 {
00389 spr=spr->next;
00390 continue;
00391 }
00392 else if(spr->New())
00393 {
00394
00395 spr->ClearFlags(SPRITE_WAIT);
00396
00397
00398 spr->SetFlags(SPRITE_MOVED);
00399 }
00400
00401 spr->Update(dtick);
00402
00403 spr=spr->next;
00404 }
00405
00406 spr=sprites.Head();
00407 while(spr!=NULL)
00408 {
00409 Sprite *spr2=spr->next;
00410
00411 if(spr->Expired())
00412 {
00413
00414 }
00415 else if(spr->Moved())
00416 {
00417
00418 while(spr2!=NULL)
00419 {
00420 if(spr2->Expired())
00421 {
00422
00423 }
00424 else if(spr->CanCollide(spr2))
00425 {
00426
00427 spr->OnCollide( spr2,spr2->GetColIndex() );
00428 spr2->OnCollide( spr , spr->GetColIndex() );
00429 }
00430
00431 spr2=spr2->next;
00432 }
00433 }
00434 else
00435 {
00436 while(spr2!=NULL)
00437 {
00438 if(spr2->Expired())
00439 {
00440
00441 }
00442 else if(spr2->Moved())
00443 if(spr->CanCollide(spr2))
00444 {
00445
00446 spr->OnCollide( spr2,spr2->GetColIndex() );
00447 spr2->OnCollide( spr , spr->GetColIndex() );
00448 }
00449
00450
00451 spr2=spr2->next;
00452 }
00453 }
00454
00455 spr=spr->next;
00456 }
00457
00458 Unlock();
00459 }
00460
00461
00462
00468 SDL_Surface *SpriteManager::CheckOutBG()
00469 {
00470 Lock();
00471 return(bg);
00472 }
00476 bool SpriteManager::CheckInBG(SDL_Surface *bg_in)
00477 {
00478 if(bg_in==bg)
00479 {
00480 Unlock();
00481 return(true);
00482 }
00483 else
00484 {
00485 return(false);
00486 }
00487 }
00488
00489
00490
00494 SpriteManager::~SpriteManager()
00495 {
00496 Lock();
00497
00498
00499 if((flag&SM_OWNBG)&&(bg!=NULL))
00500 {
00501 SDL_FreeSurface(bg);
00502 }
00503
00504 SDL_DestroyMutex(lock);
00505 }