|
SDLGameEngine
|
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 }