SDLGameEngine

src/sgesprite.c

00001 /*
00002  * Copyright (c) 2007 Heiko Irrgang
00003  *
00004  * The license and distribution terms for this file may be
00005  * found in the file COPYING in this distribution or at
00006  * http://93-interactive.com/cms/products/software/sdl-game-engine/license/
00007  */
00008 
00009 #include <sge.h>
00010 
00011 SGESPRITE *sgeSpriteNew() {
00012         SGESPRITE *ret;
00013         sgeNew(ret, SGESPRITE);
00014         ret->x=0;
00015         ret->y=0;
00016         ret->currentFrame=0;
00017         sgeSpriteSetFPS(ret, 15);
00018         ret->sprite=sgeArrayNew();
00019         sgeArrayAdd(ret->sprite, sgeArrayNew());
00020         ret->bankSize=sgeArrayNew();
00021         sgeArrayAdd(ret->bankSize, 0);
00022         ret->isMoving=0;
00023         ret->initMove=1;
00024         ret->wayPoints=sgeArrayNew();
00025         ret->fX=0;
00026         ret->fY=0;
00027         ret->dirX=0;
00028         ret->dirY=0;
00029         ret->moveSpeed=1.0;
00030         ret->userData=NULL;
00031         ret->initialized=0;
00032         ret->numberOfBanks=1;
00033         ret->currentBank=0;
00034         ret->animate=YES;
00035         ret->alpha=0xff;
00036         return ret;
00037 }
00038 
00039 SGESPRITE *sgeSpriteNewFile(SGEFILE *f, const char *filename) {
00040         SGESPRITE *ret=sgeSpriteNew();
00041         sgeSpriteAddFile(ret, f, filename);
00042         return ret;
00043 }
00044 
00045 SGESPRITE *sgeSpriteNewFileRange(SGEFILE *f, const char *templ, Uint32 start, Uint32 end) {
00046         SGESPRITE *ret=sgeSpriteNew();
00047         sgeSpriteAddFileRange(ret, f, templ, start, end);
00048         return ret;
00049 }
00050 
00051 SGESPRITE *sgeSpriteNewSDLSurface(SDL_Surface *surface) {
00052         SGESPRITE *ret=sgeSpriteNew();
00053         sgeSpriteAddSDLSurface(ret, surface);
00054         return ret;
00055 }
00056 
00057 void sgeSpriteDestroy(SGESPRITE *s) {
00058         int i,n;
00059         SGEARRAY *cur;
00060 
00061         for (n=s->numberOfBanks-1;n>-1;n--) {
00062                 sgeSpriteSetAnimBank(s,n);
00063                 cur=sgeSpriteGetCurrentSpriteArray(s);
00064                 for (i=0;i<sgeSpriteGetNumberOfFrames(s);i++) {
00065                         sgeSpriteImageDestroy(sgeArrayGet(cur,0));
00066                         sgeArrayRemove(cur,0);
00067                 }
00068                 sgeArrayDestroy(cur);
00069                 sgeArrayRemove(s->sprite,n);
00070                 sgeArrayRemove(s->bankSize,n);
00071         }
00072         sgeArrayDestroy(s->sprite);
00073         sgeArrayDestroy(s->bankSize);
00074 
00075         sgeSpriteClearWayPoints(s);
00076         sgeArrayDestroy(s->wayPoints);
00077         sgeFree(s);
00078 }
00079 
00080 SGESPRITE *sgeSpriteDuplicate(SGESPRITE *s) {
00081         int i,n;
00082         SGESPRITE *ret;
00083         SGEARRAY *bank;
00084         SGESPRITEIMAGE *image, *newimage;
00085 
00086         ret=sgeSpriteNew();
00087         for (i=0;i<s->numberOfBanks;i++) {
00088                 if (i>0) {
00089                         sgeSpriteAddAnimBank(ret);
00090                 }
00091                 bank=sgeArrayGet(s->sprite,i);
00092                 for (n=0;n<bank->numberOfElements;n++) {
00093                         image=sgeArrayGet(bank, n);
00094                         newimage=sgeSpriteImageDuplicate(image);
00095                         sgeSpriteAddSpriteImage(ret,newimage);
00096                 }
00097         }
00098         ret->x=s->x;
00099         ret->y=s->y;
00100         ret->currentFrame=s->currentFrame;
00101         ret->lastFrame=s->lastFrame;
00102         ret->framesPerSecond=s->framesPerSecond;
00103         ret->animate=s->animate;
00104         ret->currentBank=s->currentBank;
00105         ret->alpha=s->alpha;
00106         ret->userData=s->userData;
00107         sgeSpriteUpdatePosition(ret);
00108         return ret;
00109 }
00110 
00111 SGESPRITEIMAGE *sgeSpriteGetCurrentFrame(SGESPRITE *s) {
00112         return (SGESPRITEIMAGE *)sgeArrayGet(sgeSpriteGetCurrentSpriteArray(s), s->currentFrame);
00113 }
00114 
00115 void sgeSpriteSetFPS(SGESPRITE *s, Uint32 fps) {
00116         s->framesPerSecond=fps;
00117         s->lastFrame=0;
00118 }
00119 
00120 void sgeSpriteAddSDLSurface(SGESPRITE *s, SDL_Surface *surface) {
00121         SGESPRITEIMAGE *new;
00122         sgeNew(new, SGESPRITEIMAGE);
00123         sgeSpriteImageSetImage(new,surface);
00124         sgeSpriteAddSpriteImage(s,new);
00125 }
00126 
00127 void sgeSpriteAddSpriteImage(SGESPRITE *s, SGESPRITEIMAGE *i) {
00128         sgeArrayAdd(sgeSpriteGetCurrentSpriteArray(s), (void *)i);
00129         sgeSpriteSetNumberOfFrames(s, sgeSpriteGetNumberOfFrames(s)+1);
00130 }
00131 
00132 void sgeSpriteAddFile(SGESPRITE *s, SGEFILE *f, const char *name) {
00133         SGESPRITEIMAGE *new;
00134         SDL_Surface *img=sgeReadImage(f,name);
00135         sgeNew(new, SGESPRITEIMAGE);
00136         sgeSpriteImageSetImage(new, img);
00137         sgeArrayAdd(sgeSpriteGetCurrentSpriteArray(s), (void *)new);
00138         sgeSpriteSetNumberOfFrames(s, sgeSpriteGetNumberOfFrames(s)+1);
00139 }
00140 
00141 void sgeSpriteAddFileRange(SGESPRITE *s, SGEFILE *f, const char *templ, Uint32 start, Uint32 end) {
00142         char *buf;
00143         Uint32 i;
00144         
00145         sgeMalloc(buf, char, MAXFILENAMELEN);
00146         for (i=start;i<=end;i++) {
00147                 memset(buf, 0, MAXFILENAMELEN+1);
00148                 snprintf(buf, MAXFILENAMELEN, templ, i);
00149                 sgeSpriteAddFile(s, f, buf);
00150         }
00151         sgeFree(buf);
00152 }
00153 
00154 inline void sgeSpriteUpdatePosition(SGESPRITE *s) {
00155         SGESPRITEIMAGE *frame;
00156 
00157         frame=(SGESPRITEIMAGE *)sgeArrayGet(sgeSpriteGetCurrentSpriteArray(s),s->currentFrame);
00158         frame->x=s->x;
00159         frame->y=s->y;
00160 }
00161 
00162 void sgeSpriteUpdate(SGESPRITE *s) {
00163         SGESPRITEWAYPOINT *wp;
00164 
00165         if (s->isMoving) {
00166                 wp=sgeArrayGet(s->wayPoints,0);
00167                 sgeSpriteMoveTowards(s, wp->x, wp->y);
00168                 if (!s->isMoving) {
00169                         sgeSpriteRemoveNextWayPoint(s);
00170                         if (s->wayPoints->numberOfElements>0) {
00171                                 s->isMoving=1;
00172                         }
00173                 }
00174         }
00175 
00176         if (s->animate) {
00177                 if ((SDL_GetTicks()-s->lastFrame)>=1000/s->framesPerSecond) {
00178                         s->lastFrame=SDL_GetTicks();
00179                         s->currentFrame++;
00180                         s->currentFrame%=sgeSpriteGetNumberOfFrames(s);
00181                 }
00182         }
00183         sgeSpriteUpdatePosition(s);
00184 }
00185 
00186 SDL_Surface *sgeSpriteGetSDLSurface(SGESPRITE *s) {
00187         SGESPRITEIMAGE *si;
00188         sgeSpriteUpdate(s);
00189         si=(SGESPRITEIMAGE *)sgeArrayGet(sgeSpriteGetCurrentSpriteArray(s),s->currentFrame);
00190         return si->image;
00191 }
00192 
00193 void sgeSpriteDraw(SGESPRITE *s, SDL_Surface *dest) {
00194         sgeSpriteUpdate(s);
00195         sgeSpriteImageDrawXY((SGESPRITEIMAGE *)sgeArrayGet(sgeSpriteGetCurrentSpriteArray(s),s->currentFrame),s->x, s->y, s->alpha, dest);
00196 }
00197 
00198 void sgeSpriteDrawXY(SGESPRITE *s, int x, int y, SDL_Surface *dest) {
00199         sgeSpriteUpdate(s);
00200         sgeSpriteImageDrawXY((SGESPRITEIMAGE *)sgeArrayGet(sgeSpriteGetCurrentSpriteArray(s),s->currentFrame), x, y, s->alpha, dest);
00201 }
00202 
00203 inline void sgeSpriteDrawRotoZoomed(SGESPRITE *s, float rotation, float zoom, SDL_Surface *dest) {
00204         sgeSpriteDrawXYRotoZoomed(s, s->x, s->y, rotation, zoom, dest);
00205 }
00206 
00207 inline void sgeSpriteDrawXYRotoZoomed(SGESPRITE *s, int x, int y, float rotation, float zoom, SDL_Surface *dest) {
00208         SGESPRITEIMAGE *sprite;
00209         SDL_Surface *rz;
00210         SDL_Rect r;
00211         SDL_Surface *alphasurface;
00212 
00213         sgeSpriteUpdate(s);
00214         sprite=(SGESPRITEIMAGE *)sgeArrayGet(sgeSpriteGetCurrentSpriteArray(s),s->currentFrame);
00215         rz=sgeRotoZoom(sprite->image, rotation, zoom);
00216         r.x=x-(rz->w>>1)+(sprite->image->w>>1);
00217         r.y=y-(rz->h>>1)+(sprite->image->h>>1);
00218 
00219         if (s->alpha==0xff) {
00220                 SDL_BlitSurface(rz,NULL,dest,&r);
00221         } else {
00222                 alphasurface=sgeChangeSDLSurfaceAlpha(rz, s->alpha);
00223                 SDL_BlitSurface(alphasurface,NULL,dest,&r);
00224                 SDL_FreeSurface(alphasurface);
00225         }
00226         SDL_FreeSurface(rz);
00227 }
00228 
00229 static void sgeSpriteUseAlphaHelper(Uint32 id, void *data) {
00230         SGESPRITEIMAGE *s=(SGESPRITEIMAGE *)data;
00231         sgeSpriteImageUseAlpha(s);
00232 }
00233 void sgeAnimatedSpriteUseAlpha(SGESPRITE *s) {
00234         // TODO all sprite banks
00235         sgeArrayForEach(sgeSpriteGetCurrentSpriteArray(s), sgeSpriteUseAlphaHelper);
00236 }
00237 
00238 static void sgeSpriteIgnoreAlphaHelper(Uint32 id, void *data) {
00239         SGESPRITEIMAGE *s=(SGESPRITEIMAGE *)data;
00240         sgeSpriteImageIgnoreAlpha(s);
00241 }
00242 void sgeAnimatedSpriteIgnoreAlpha(SGESPRITE *s) {
00243         // TODO all sprite banks
00244         sgeArrayForEach(sgeSpriteGetCurrentSpriteArray(s), sgeSpriteIgnoreAlphaHelper);
00245 }
00246 
00247 int sgeSpriteBoxCollide(SGESPRITE *a, SGESPRITE *b) {
00248         if (a==b) return 0;
00249         return sgeSpriteImageBoxCollide((SGESPRITEIMAGE *)sgeArrayGet(sgeSpriteGetCurrentSpriteArray(a),a->currentFrame),(SGESPRITEIMAGE *)sgeArrayGet(sgeSpriteGetCurrentSpriteArray(b),b->currentFrame));
00250 }
00251 
00252 int sgeSpriteCollide(SGESPRITE *a, SGESPRITE *b) {
00253         if (a==b) return 0;
00254         return sgeSpriteImageCollide((SGESPRITEIMAGE *)sgeArrayGet(sgeSpriteGetCurrentSpriteArray(a),a->currentFrame),(SGESPRITEIMAGE *)sgeArrayGet(sgeSpriteGetCurrentSpriteArray(b),b->currentFrame));
00255 }
00256 
00257 int sgeSpriteBoxCollideSpriteImage(SGESPRITE *a, SGESPRITEIMAGE *b) {
00258         return sgeSpriteImageBoxCollide((SGESPRITEIMAGE *)sgeArrayGet(sgeSpriteGetCurrentSpriteArray(a),a->currentFrame), b);
00259 }
00260 
00261 int sgeSpriteCollideSpriteImage(SGESPRITE *a, SGESPRITEIMAGE *b) {
00262         return sgeSpriteImageCollide((SGESPRITEIMAGE *)sgeArrayGet(sgeSpriteGetCurrentSpriteArray(a),a->currentFrame), b);
00263 }
00264 
00265 int sgeSpriteWidth(SGESPRITE *s) {
00266         SGESPRITEIMAGE *i=sgeArrayGet(sgeSpriteGetCurrentSpriteArray(s), s->currentFrame);
00267         return i->w;
00268 }
00269 
00270 int sgeSpriteHeight(SGESPRITE *s) {
00271         SGESPRITEIMAGE *i=sgeArrayGet(sgeSpriteGetCurrentSpriteArray(s), s->currentFrame);
00272         return i->h;
00273 }
00274 
00275 void sgeSpriteAddWayPoint(SGESPRITE *s, int x, int y) {
00276         SGESPRITEWAYPOINT *wp;
00277         sgeNew(wp, SGESPRITEWAYPOINT);
00278         wp->x=x;
00279         wp->y=y;
00280         sgeArrayAdd(s->wayPoints, wp);
00281 }
00282 
00283 void sgeSpriteRemoveNextWayPoint(SGESPRITE *s) {
00284         SGESPRITEWAYPOINT *wp;
00285         wp=sgeArrayGet(s->wayPoints,0);
00286         sgeFree(wp);
00287         sgeArrayRemove(s->wayPoints,0);
00288 }
00289 
00290 void sgeSpriteClearWayPoints(SGESPRITE *s) {
00291         int i;
00292         for (i=0;i<s->wayPoints->numberOfElements;i++) {
00293                 sgeSpriteRemoveNextWayPoint(s);
00294         }
00295 }
00296 
00297 void sgeSpriteStartMovement(SGESPRITE *s, float speed) {
00298         SGESPRITEWAYPOINT *wp=sgeArrayGet(s->wayPoints, 0);
00299         s->fX=(float)wp->x;
00300         s->fY=(float)wp->y;
00301         s->moveSpeed=speed;
00302         s->isMoving=1;
00303 }
00304 
00305 void sgeSpriteAbortMovement(SGESPRITE *s) {
00306         s->isMoving=0;
00307         s->initMove=1;
00308         sgeSpriteClearWayPoints(s);
00309 }
00310 
00311 void sgeSpriteMoveTowards(SGESPRITE *s, int x, int y) {
00312         int dx, dy;
00313         if (s->initMove) {
00314                 dx=x-s->x;
00315                 dy=y-s->y;
00316                 s->fX=(float)s->x;
00317                 s->fY=(float)s->y;
00318                 if (abs(dx)>abs(dy)) {
00319                         if (dx<0) {
00320                                 s->dirX=-1;
00321                         } else {
00322                                 s->dirX=1;
00323                         }
00324                         s->dirY=(float)dy/(float)dx;
00325                         if ( (dx<0) && (dy<0) )  {
00326                                 s->dirY*=-1;
00327                         }
00328                 } else {
00329                         s->dirX=(float)dx/(float)dy;
00330                         if ( (dx<0) && (dy<0) )  {
00331                                 s->dirX*=-1;
00332                         }
00333                         if (dy<0) {
00334                                 s->dirY=-1;
00335                         } else {
00336                                 s->dirY=1;
00337                         }
00338                 }
00339                 s->initMove=0;
00340         }
00341         s->fX+=s->dirX*s->moveSpeed;
00342         s->fY+=s->dirY*s->moveSpeed;
00343         s->x=(int)s->fX;
00344         s->y=(int)s->fY;
00345 
00346 
00347         if ( (s->dirX>0) && (s->fX>=(float)x) ) {
00348                 s->dirX=0;
00349                 s->x=x;
00350                 s->fX=(float)x;
00351         } else if ( (s->dirX<0) && (s->fX<=(float)x) ) {
00352                 s->dirX=0;
00353                 s->x=x;
00354                 s->fX=(float)x;
00355         }
00356         if ( (s->dirY>0) && (s->fY>=(float)y) ) {
00357                 s->dirY=0;
00358                 s->y=y;
00359                 s->fY=(float)y;
00360         } else if ( (s->dirY<0) && (s->fY<=(float)y) ) {
00361                 s->dirY=0;
00362                 s->y=y;
00363                 s->fY=(float)y;
00364         }
00365         if ( (s->x==x) && (s->y==y) ) {
00366                 s->isMoving=0;
00367                 s->initMove=1;
00368         }
00369 }
00370 
00371 void sgeSpriteSetUserData(SGESPRITE *s, void *data) {
00372         s->userData=(void *)data;
00373 }
00374 
00375 void *sgeSpriteGetUserData(SGESPRITE *s) {
00376         return (void *)s->userData;
00377 }
00378 
00379 inline Uint32 sgeSpriteGetNumberOfFrames(SGESPRITE *s) {
00380         intptr_t tmp=(intptr_t)sgeArrayGet(s->bankSize, s->currentBank);
00381         return (Uint32) tmp;
00382 }
00383 
00384 inline void sgeSpriteSetNumberOfFrames(SGESPRITE *s, Uint32 number) {
00385         intptr_t tmp=(intptr_t)number;
00386         sgeArrayReplace(s->bankSize,s->currentBank,(void *)tmp);
00387 }
00388 
00389 inline SGEARRAY *sgeSpriteGetCurrentSpriteArray(SGESPRITE *s) {
00390         SGEARRAY *ret=sgeArrayGet(s->sprite, s->currentBank);
00391         return ret;
00392 }
00393 
00394 inline void sgeSpriteSetAnimBank(SGESPRITE *s, Uint32 bank) {
00395         s->currentBank=bank;
00396         s->currentFrame=0;
00397         s->lastFrame=0;
00398 }
00399 
00400 void sgeSpriteAddAnimBank(SGESPRITE *s) {
00401         Uint32 nextbank=s->bankSize->numberOfElements;
00402         sgeArrayAdd(s->sprite, sgeArrayNew());
00403         sgeArrayAdd(s->bankSize, 0);
00404         sgeSpriteSetAnimBank(s, nextbank);
00405         s->numberOfBanks++;
00406 }
00407 
00408 Uint32 sgeSpriteGetAnimBank(SGESPRITE *s) {
00409         return s->currentBank;
00410 }
00411 
00412 void sgeSpriteAnimate(SGESPRITE *s, int state) {
00413         s->animate=state;
00414 }
00415 
00416 void sgeSpriteResetAnimation(SGESPRITE *s) {
00417         sgeSpriteForceFrame(s,0);
00418 }
00419 
00420 inline void sgeSpriteForceFrame(SGESPRITE *s, Uint32 frame) {
00421         s->currentFrame=frame;
00422         s->lastFrame=frame;
00423 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines