|
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 SGEPOSITION *sgePositionNew(int x, int y) { 00012 SGEPOSITION *ret; 00013 00014 sgeNew(ret, SGEPOSITION); 00015 ret->x=x; 00016 ret->y=y; 00017 return ret; 00018 } 00019 00020 void sgePositionDestroy(SGEPOSITION *p) { 00021 sgeFree(p); 00022 } 00023 00024 SGEPIXELINFO *sgePixelInfoNew(Uint8 r, Uint8 g, Uint8 b, Uint8 a) { 00025 SGEPIXELINFO *ret; 00026 00027 sgeNew(ret, SGEPIXELINFO); 00028 ret->r=r; 00029 ret->g=g; 00030 ret->b=b; 00031 ret->a=a; 00032 00033 return ret; 00034 } 00035 00036 void sgePixelInfoDestroy(SGEPIXELINFO *i) { 00037 sgeFree(i); 00038 } 00039 00040 inline Uint32 sgeMakeColor(SDL_Surface *surface, int r, int g, int b, int a) { 00041 Uint32 color; 00042 if (a<0) { 00043 color=SDL_MapRGB(surface->format,r,g,b); 00044 } else { 00045 color=SDL_MapRGBA(surface->format,r,g,b,a); 00046 } 00047 return color; 00048 } 00049 00050 inline void sgeFillRect(SDL_Surface *dest, int x, int y, int w, int h, Uint32 color) { 00051 SDL_Rect rect; 00052 rect.x=x; 00053 rect.y=y; 00054 rect.w=w; 00055 rect.h=h; 00056 SDL_FillRect(dest, &rect, color); 00057 } 00058 00059 inline void sgeDrawRect(SDL_Surface *dest, int x, int y, int w, int h, int linewidth, Uint32 color) { 00060 sgeFillRect(dest, x, y, w, linewidth, color); 00061 sgeFillRect(dest, x, y, linewidth, h, color); 00062 sgeFillRect(dest, x+w-linewidth, y, linewidth, h, color); 00063 sgeFillRect(dest, x, y+h-linewidth, w, linewidth, color); 00064 } 00065 00066 inline void sgeDrawPixel(SDL_Surface *dest, int x, int y, Uint32 color) { 00067 Uint8 *buf8=NULL; 00068 Uint16 *buf16=NULL; 00069 Uint32 *buf32=NULL; 00070 00071 if (x<0 || y<0) return; 00072 if (x>=dest->w || y>=dest->h) return; 00073 00074 switch (dest->format->BitsPerPixel) { 00075 case 8: 00076 buf8=(Uint8 *)dest->pixels+y*dest->w+x; 00077 *buf8=(Uint8)color; 00078 break; 00079 case 16: 00080 buf16=(Uint16 *)dest->pixels+y*dest->w+x; 00081 *buf16=(Uint16)color; 00082 break; 00083 default: 00084 buf32=(Uint32 *)dest->pixels+y*dest->w+x; 00085 *buf32=color; 00086 break; 00087 } 00088 } 00089 00090 inline SGEPIXELINFO *sgeGetPixel(SDL_Surface *dest, int x, int y) { 00091 Uint8 p8, *buf8; 00092 Uint16 p16, *buf16; 00093 Uint32 p32, *buf32; 00094 SGEPIXELINFO *ret; 00095 00096 switch (dest->format->BitsPerPixel) { 00097 case 8: 00098 buf8=(Uint8 *)dest->pixels; 00099 p8=buf8[y*dest->w+x]; 00100 p32=p8; 00101 break; 00102 case 16: 00103 buf16=(Uint16 *)dest->pixels; 00104 p16=buf16[y*dest->w+x]; 00105 p32=p16; 00106 break; 00107 default: 00108 buf32=(Uint32 *)dest->pixels; 00109 p32=buf32[y*dest->w+x]; 00110 break; 00111 } 00112 sgeNew(ret, SGEPIXELINFO); 00113 SDL_GetRGBA(p32, dest->format, &ret->r, &ret->g, &ret->b, &ret->a); 00114 return ret; 00115 } 00116 00117 inline void sgeDrawLine(SDL_Surface *dest, int x, int y, int x2, int y2, Uint32 color) { 00118 int steep=0; 00119 int tmp=0; 00120 int dx=0; 00121 int dy=0; 00122 int err=0; 00123 int ystep=1; 00124 int yy=0; 00125 int xx=0; 00126 00127 if (abs(y2-y)>abs(x2-x)) steep=1; 00128 if (steep) { 00129 tmp=x; 00130 x=y; 00131 y=tmp; 00132 tmp=x2; 00133 x2=y2; 00134 y2=tmp; 00135 } 00136 if (x>x2) { 00137 tmp=x; 00138 x=x2; 00139 x2=tmp; 00140 tmp=y; 00141 y=y2; 00142 y2=tmp; 00143 } 00144 00145 if (y>y2) { 00146 ystep=-1; 00147 } 00148 00149 dx=x2-x; 00150 dy=abs(y2-y); 00151 err=-dx>>1; 00152 yy=y; 00153 00154 for (xx=x;xx<=x2;xx++) { 00155 if (!steep) { 00156 sgeDrawPixel(dest, xx, yy, color); 00157 } else { 00158 sgeDrawPixel(dest, yy, xx, color); 00159 } 00160 err+=dy; 00161 if (err>0) { 00162 yy+=ystep; 00163 err-=dx; 00164 } 00165 } 00166 } 00167 00168 inline void sgeDrawImage(SDL_Surface *dest, SDL_Surface *image, int x, int y) { 00169 SDL_Rect r; 00170 r.w=image->w; 00171 r.h=image->h; 00172 r.x=x; 00173 r.y=y; 00174 SDL_BlitSurface(image, NULL, dest, &r); 00175 } 00176 00177 void sgeIgnoreAlpha(SDL_Surface *s) { 00178 SDL_SetAlpha(s, s->flags^SDL_SRCALPHA, SDL_ALPHA_OPAQUE); 00179 } 00180 00181 void sgeUseAlpha(SDL_Surface *s) { 00182 SDL_SetAlpha(s, SDL_SRCALPHA, SDL_ALPHA_OPAQUE); 00183 } 00184 00185 SDL_Surface *sgeRotoZoom(SDL_Surface *source, float rotation, float zoom) { 00186 Uint32 *src32=(Uint32*)source->pixels; 00187 Uint16 *src16=(Uint16*)source->pixels; 00188 Uint8 *src8=(Uint8*)source->pixels; 00189 SDL_Surface *ret; 00190 SDL_Surface *target=SDL_CreateRGBSurface( 00191 source->flags, 00192 (int)((float)source->w*zoom)*3, 00193 (int)((float)source->h*zoom)<<1, 00194 source->format->BitsPerPixel, 00195 source->format->Rmask, 00196 source->format->Gmask, 00197 source->format->Bmask, 00198 source->format->Amask 00199 ); 00200 SDL_Rect r; 00201 Uint32 *dst32=(Uint32*)target->pixels; 00202 Uint16 *dst16=(Uint16*)target->pixels; 00203 Uint8 *dst8=(Uint8*)target->pixels; 00204 00205 int sinfp=(int)((sin(rotation)*65536.0)/zoom); 00206 int cosfp=(int)((cos(rotation)*65536.0)/zoom); 00207 00208 int xc; 00209 int yc; 00210 00211 int tx,ty; 00212 int x,y; 00213 int tempx,tempy; 00214 00215 int targetpitch; 00216 int sourcepitch; 00217 int divider; 00218 00219 int minx=target->w; 00220 int miny=target->h; 00221 int maxx=0; 00222 int maxy=0; 00223 00224 switch (source->format->BitsPerPixel) { 00225 case 8: 00226 divider=0; 00227 break; 00228 case 16: 00229 divider=1; 00230 break; 00231 default: 00232 divider=2; 00233 break; 00234 } 00235 00236 targetpitch=target->pitch>>divider; 00237 sourcepitch=source->pitch>>divider; 00238 xc=(source->w<<15) - ((target->w>>1)*(cosfp+sinfp)); 00239 yc=(source->h<<15) - ((target->h>>1)*(cosfp-sinfp)); 00240 00241 sgeLock(target); 00242 for ( y=0; y<target->h; y++ ) { 00243 00244 tx=xc; 00245 ty=yc; 00246 00247 for( x=0; x<target->w; x++ ) { 00248 00249 00250 tempx=(tx>>16); 00251 tempy=(ty>>16); 00252 00253 if( (tempx>=0) && (tempx<source->w) && (tempy>=0) && (tempy<source->h) ) { 00254 if (x>maxx) { 00255 maxx=x; 00256 } 00257 if (y>maxy) { 00258 maxy=y; 00259 } 00260 if (x<minx) { 00261 minx=x; 00262 } 00263 if (y<miny) { 00264 miny=y; 00265 } 00266 switch (source->format->BitsPerPixel) { 00267 case 8: 00268 *(dst8+x+y*targetpitch) = *(src8+tempx+tempy*sourcepitch); 00269 break; 00270 case 16: 00271 *(dst16+x+y*targetpitch) = *(src16+tempx+tempy*sourcepitch); 00272 break; 00273 default: 00274 *(dst32+x+y*targetpitch) = *(src32+tempx+tempy*sourcepitch); 00275 break; 00276 } 00277 } 00278 00279 tx+=cosfp; 00280 ty-=sinfp; 00281 } 00282 xc+=sinfp; 00283 yc+=cosfp; 00284 } 00285 sgeUnlock(target); 00286 00287 r.x=minx; 00288 r.y=miny; 00289 r.w=maxx-minx; 00290 r.h=maxy-miny; 00291 00292 ret=SDL_CreateRGBSurface( 00293 source->flags, 00294 r.w, 00295 r.h, 00296 source->format->BitsPerPixel, 00297 source->format->Rmask, 00298 source->format->Gmask, 00299 source->format->Bmask, 00300 source->format->Amask 00301 ); 00302 00303 SDL_SetAlpha(target, 0, 0); 00304 00305 SDL_BlitSurface(target, &r, ret, NULL); 00306 SDL_FreeSurface(target); 00307 00308 return ret; 00309 } 00310 00311 SDL_Surface *sgeChangeSDLSurfaceAlpha(SDL_Surface *s, Uint8 alpha) { 00312 int x,y; 00313 SDL_Surface *ret=sgeDuplicateSDLSurface(s); 00314 SGEPIXELINFO *pi; 00315 00316 sgeLock(ret); 00317 for (y=0;y<ret->h;y++) { 00318 for (x=0;x<ret->w;x++) { 00319 pi=sgeGetPixel(ret,x,y); 00320 pi->a=pi->a*alpha/256; 00321 sgeDrawPixel(ret,x,y,sgeMakeColor(ret,pi->r,pi->g,pi->b,pi->a)); 00322 sgePixelInfoDestroy(pi); 00323 } 00324 } 00325 sgeUnlock(ret); 00326 return ret; 00327 } 00328 00329 SDL_Surface *sgeCreateSDLSurface(int width, int height, int depth, Uint32 sdlflags) { 00330 SDL_Surface *ret; 00331 Uint32 rmask,gmask,bmask,amask; 00332 00333 #if SDL_BYTEORDER == SDL_BIG_ENDIAN 00334 rmask = 0xff000000; 00335 gmask = 0x00ff0000; 00336 bmask = 0x0000ff00; 00337 amask = 0x000000ff; 00338 #else 00339 rmask = 0x000000ff; 00340 gmask = 0x0000ff00; 00341 bmask = 0x00ff0000; 00342 amask = 0xff000000; 00343 #endif 00344 00345 if (sdlflags==0) { 00346 sdlflags=SDL_SWSURFACE; 00347 } 00348 00349 ret=SDL_CreateRGBSurface(sdlflags, width, height, depth, rmask, gmask, bmask, amask); 00350 if (ret==NULL) { 00351 sgeBailOut("cannot create new surface: %s\n", SDL_GetError ()); 00352 } 00353 return ret; 00354 } 00355 00356 SDL_Surface *sgeCreateVideoSurface(int width, int height, int depth, Uint32 sdlflags) { 00357 SDL_Surface *s=sgeCreateSDLSurface(width, height, depth, sdlflags); 00358 SDL_Surface *ret; 00359 00360 ret=SDL_DisplayFormatAlpha(s); 00361 if (ret!=NULL) { 00362 SDL_FreeSurface(s); 00363 return ret; 00364 } 00365 00366 return s; 00367 } 00368 00369 SDL_Surface *sgeConvertToGrey(SDL_Surface *src) { 00370 SGEPIXELINFO *info; 00371 SDL_Surface *ret=sgeDuplicateSDLSurface(src); 00372 int x,y; 00373 int grey; 00374 00375 sgeLock(ret); 00376 for (y=0;y<src->h;y++) { 00377 for (x=0;x<src->w;x++) { 00378 info=sgeGetPixel(src, x, y); 00379 grey=(int)(0.3*(float)info->r+0.59*(float)info->g+0.11*(float)info->b); 00380 sgeDrawPixel(ret, x, y, sgeMakeColor(ret, grey, grey, grey, info->a)); 00381 sgeFree(info); 00382 } 00383 } 00384 sgeUnlock(ret); 00385 return ret; 00386 }