SDLGameEngine

- Main Page
- Related Pages
- Modules
- Data Structures
- Files

- File List
- Globals

# 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