Main Page | Modules | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members

sprite.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002                   sprite.cpp  -  Sprite class implementation
00003                              -------------------
00004     begin                : Wed Mar 5 2003
00005     copyright            : (C) 2003 by Tyler Montbriand
00006     email                : tsm@accesscomm.ca
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  ***************************************************************************/
00017 
00024 
00025 /* Define this to use IMG_Load instead of SDL_LoadBMP */
00026 #define USE_SDL_IMAGE
00027  
00028 #include <malloc.h>
00029 #include "Fxp.h"
00030 #include "rect.h"
00031 #include "sprite.h"
00032 #include "bitmask.h"
00033 
00038 Sprite::Sprite()
00039 {
00040   Init_List();
00041   Init_Flags();
00042   Init_Layers();
00043   Init_Surface();
00044   Init_Frames();
00045   Init_Collision();
00046   Init_Bitmask();
00047 }
00048 
00049 
00053 void Sprite::Event(int code, void *data1, void *data2)
00054 {
00055 }
00056 
00061 Sprite *Sprite::Clone()
00062 {
00063   Sprite *spr=new Sprite();
00064 
00065   (*spr)=(*this);
00066   spr->ClearFlags(SPRITE_OWNSURFACE|SPRITE_OWNBITMASK);
00067   return(spr);
00068 }
00069 
00074 void Sprite::OnCollide(const Sprite *spr, ColType index)
00075 {
00076 }
00077 
00083 int Sprite::GetFrame()
00084 { /* Just returns current integer frame, but could do table stuff */
00085   return(FROM_SFXP(frame));
00086 }
00087 
00091 void Sprite::Init_Collision(ColType c_index, ColType c_layer)
00092 {
00093   cindex=c_index;
00094   clayer=c_layer;
00095 }
00096 
00101 void Sprite::Update(Sint32 dtick)
00102 {
00103   /* Update frame # */
00104   if((surface!=NULL)&&(framerate!=0))
00105   {
00106     int of,newf;
00107     /* Get the current frame */
00108     of=FROM_SFXP(frame);    
00109     /* Increment frame position */
00110     
00111     if(framerate<0) /* Wrap negative framerates properly */
00112     {
00113       while((framerate*dtick)< -frame)
00114         frame+=TO_SFXP(frames.x*frames.y);
00115     }
00116 
00117     frame+=(framerate*dtick);      
00118 
00119     /* Get the new frame # */
00120     newf=FROM_SFXP(frame);
00121 
00122     /* If there has been a change of 1 whole digit or more */    
00123     if(of!=newf)
00124     {
00125       /* Calculate the new values for srcrect */
00126       CalcFrame();
00127       /* Mark the sprite as needing redraw */
00128       Tag();
00129     }            
00130   }
00131   
00132   /* Calculate movement */
00133   if((dtick!=0)&&(vel.Nonzero()))
00134   {
00135     /* Get current velocity */
00136     SfxpCoord dpos=vel;
00137     /* Calculate the distance moved */
00138     dpos.IntScalar(dtick);
00139 
00140     /* Increment position */
00141     pos+=dpos;
00142 
00143     /* If there's been a change of 1 pixel or more */
00144     if(!pos.MajorDigitsEqual(prevpos))
00145     {    
00146       /* Mark the sprite as needing redraw */
00147       Tag();
00148     }
00149   }    
00150 }
00151 
00155 void Sprite::Init_Frames(int xframes, int yframes)
00156 {
00157   frame=framerate=0;
00158 
00159   if((xframes<=0)||(yframes<=0))
00160     frames.x=frames.y=1;        
00161   else
00162   {
00163     frames.x=xframes;
00164     frames.y=yframes;
00165   }
00166 
00167   if(surface==NULL)
00168     frames.w=frames.h=0;
00169   else
00170   {
00171     frames.w=surface->w/frames.x;
00172     frames.h=surface->h/frames.y;
00173   }
00174 
00175   CalcFrame();
00176 }
00177 
00181 void Sprite::Init_Flags(SpriteFlag flags)
00182 {
00183   flag=flags|SPRITE_WAIT;
00184 }
00185 
00189 void Sprite::Init_Surface(SDL_Surface *surf, bool os_in)
00190 {
00191   if(surf==NULL)
00192   {
00193     surface=NULL;
00194     srcrect.Set(0,0,0,0);
00195   }
00196   else
00197   {
00198     surface=surf;
00199     srcrect.Set(0,0,surface->w,surface->h);
00200     
00201     if(os_in)
00202       SetFlags(SPRITE_OWNSURFACE);
00203     else
00204       ClearFlags(SPRITE_OWNSURFACE);
00205   }
00206 }
00207 
00211 void Sprite::Init_List(Sprite *previn, Sprite *nextin)
00212 {
00213   prev=previn;
00214   next=nextin;
00215 }
00216 
00220 void Sprite::Init_Bitmask(bool enable, bitmask **bmask_in)
00221 {
00222   if(enable)  
00223   {
00224     if(bmask_in!=NULL)
00225     {
00226       bmask=bmask_in;
00227       ClearFlags(SPRITE_OWNBITMASK);
00228     }
00229     else
00230     {
00231       int n=-1;
00232 
00233       bmask =(bitmask **)malloc(sizeof(bitmask)*frames.x*frames.y);
00234       if(bmask==NULL) return;
00235 
00236       for(n=0; n<(frames.x*frames.y); n++)
00237       {
00238         frame=TO_SFXP(n);
00239         CalcFrame();
00240 
00241         bmask[n]=MakeBitMask(surface,srcrect);
00242       }
00243 
00244       SetFlags(SPRITE_OWNBITMASK);
00245 
00246       frame=0;
00247       CalcFrame();
00248     }
00249   }
00250   else
00251   {
00252     bmask=NULL;
00253     ClearFlags(SPRITE_OWNBITMASK);
00254   }
00255 }
00256 
00260 void Sprite::Init_Layers(Sint16 layer)
00261 {
00262   drawlayer=layer;
00263 }
00264 
00268 Sprite::~Sprite()
00269 {
00270   int n=-1;
00271   
00272   if((bmask!=NULL)&&OwnBitmask())
00273   {
00274     for(n=0; n<(frames.x*frames.y); n++)
00275     {
00276       if(bmask[n]!=NULL)
00277       {
00278         bitmask_free(bmask[n]);
00279         bmask[n]=NULL;
00280       }
00281     }
00282     free(bmask);
00283     bmask=NULL;
00284   }
00285   
00286   if((surface!=NULL)&&OwnSurface())
00287   {
00288     SDL_FreeSurface(surface);
00289     surface=NULL;
00290   }
00291 }
00292 
00297 void Sprite::Draw(SDL_Surface *screen, Rect portion)
00298 {
00299   Rect dstrect(pos.X(),pos.Y(),srcrect.w,srcrect.h);
00300 
00301   /* Both dstrect and portion are absolute coordinates in game space. */
00302   if(portion.Intersect(portion,dstrect))
00303   {
00304     Rect src=srcrect;
00305     Rect tmp=portion;
00306     tmp-=pos;
00307 
00308     /* Offset and reduce by X/Y difference */
00309     src.x+=tmp.x;
00310     src.y+=tmp.y;
00311     src.w-=tmp.x;
00312     src.h-=tmp.y;
00313 
00314     SDL_BlitSurface(surface,&src,screen,&portion);
00315   }  
00316 }
00317 
00321 void Sprite::Draw(SDL_Surface *screen)
00322 {
00323   if(screen==NULL)  return;
00324   if(surface==NULL) return;
00325 
00326   Rect dstrect(pos.X(),pos.Y(),srcrect.w,srcrect.h);
00327   
00328   SDL_BlitSurface(surface,&srcrect,screen,&dstrect);
00329 }
00330 
00334 bitmask *Sprite::GetBitmask()
00335 {
00336   if(bmask==NULL) return(NULL);
00337   
00338   int f=GetFrame()%(frames.x*frames.y);
00339 
00340   return(bmask[f]);
00341 }
00342 
00347 bitmask *MakeBitMask(SDL_Surface *surf, Rect rect)
00348 {
00349   bitmask *bmask=NULL;  
00350   Uint32 colorkey=0;
00351   int x=-1,y=-1;
00352   
00353   /* Sanity checking */
00354   if(surf==NULL)                      return(NULL);
00355   if(!(surf->flags&SDL_SRCCOLORKEY))
00356   {
00357     fprintf(stderr,"MakeBitMask()-Can't make bitmask - no colorkey\n");
00358     return(NULL);
00359   }  
00360   if(rect.x+rect.w>surf->w)           return(NULL);
00361   else if(rect.y+rect.h>surf->h)      return(NULL);
00362   /* Get the color key */
00363   colorkey=surf->format->colorkey;
00364 
00365   bmask=bitmask_create(rect.w,rect.h);
00366   if(bmask==NULL) return(NULL);
00367 
00368   SDL_LockSurface(surf);
00369   
00370   for(y=0; y<rect.h; y++)
00371   {
00372     for(x=0; x<rect.w; x++)
00373     {
00374       Uint32 pixel=getpixel(surf,x+rect.x,y+rect.y);
00375       if(pixel==colorkey) /* Transparent - doesn't collide */
00376         bitmask_clearbit(bmask,x,y);
00377       else  /* Opaque - collides */
00378         bitmask_setbit(bmask,x,y);
00379     }
00380   }
00381 
00382   SDL_UnlockSurface(surf);
00383 
00384   return(bmask);
00385 }
00386 
00390 SDL_Surface *LoadConvertBMP(const char *fname, Uint8 tr, Uint8 tg, Uint8 tb)
00391 {
00392   SDL_Surface *s1=NULL,*s2=NULL;
00393 
00394   if(fname==NULL) return(NULL);
00395 
00396 #ifdef USE_SDL_IMAGE
00397   s1=IMG_Load(fname);
00398 #else
00399   s1=SDL_LoadBMP(fname);
00400 #endif
00401 
00402   if(s1==NULL) return(NULL);
00403   s2=SDL_DisplayFormat(s1); /* Convert to display format  */
00404   
00405   if(s2!=NULL)  /* If converted, free the old copy */
00406   {
00407     SDL_FreeSurface(s1);
00408     s1=NULL;
00409   }
00410   else  /* If not converted, print warning and keep the old copy  */
00411   {
00412     fprintf(stderr,"LoadConvertBMP() - couldn't convert\n"
00413                    "\"%s\"\n"
00414                    "to display format\n\n",fname);
00415     s2=s1;
00416     s1=NULL;
00417   }
00418 
00419   if(s2==NULL)
00420   {
00421     fprintf(stderr,"LoadConvertBmp() - couldn't load %s\n",fname);
00422     return(NULL);
00423   }
00424   else
00425   {
00426     SDL_SetColorKey(s2,SDL_SRCCOLORKEY,SDL_MapRGB(s2->format,tr,tg,tb));
00427     return(s2);
00428   }
00429 }

Generated on Sat Oct 11 13:19:25 2003 for Spritelib by doxygen 1.3.4