From 97a0f629ae5072931f422574320d4d3680c0752e Mon Sep 17 00:00:00 2001 From: Ludovic Pouzenc Date: Fri, 26 Nov 2010 00:12:44 +0000 Subject: Code de maleTerrain intégrant les modifiers presque fini d'être codé je pense. Suaf que j'ai la vague impression que le getPixel ne pas grand chose d'utile : le niveau sors tout marron. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: file:///var/svn/2010-netlemmings/trunk@175 077b3477-7977-48bd-8428-443f22f7bfda --- src/graphic.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++--- src/include/utils.h | 3 ++ src/utils.c | 2 ++ 3 files changed, 92 insertions(+), 4 deletions(-) diff --git a/src/graphic.c b/src/graphic.c index 10ee0c6..d68c289 100644 --- a/src/graphic.c +++ b/src/graphic.c @@ -3,8 +3,27 @@ #include "graphic.h" #include "utils.h" +#define ccc_nooverride 0x00cc0000 +#define ccc_terrain 0x0000cc00 +#define ccc_nothing 0x00000000 #define SDLSURF_OPTS SDL_HWSURFACE|SDL_HWACCEL|/*SDL_ASYNCBLIT|*/SDL_RLEACCEL +Uint32 getPixel(SDL_Surface *s, int x, int y) { + Uint32 res=0; + //FIXME : Big Endian + res &= ((Uint8 *)s->pixels)[y*s->pitch + x*(s->format->BytesPerPixel+0)] << 0; + res &= ((Uint8 *)s->pixels)[y*s->pitch + x*(s->format->BytesPerPixel+1)] << 8; + res &= ((Uint8 *)s->pixels)[y*s->pitch + x*(s->format->BytesPerPixel+2)] << 16; + return res; +} + +void putPixel(SDL_Surface *s, int x, int y, Uint32 p) { + //FIXME : Big Endian + ((Uint8 *)s->pixels)[y*s->pitch + x*(s->format->BytesPerPixel+0)] = (p & 0x000000ff) >> 0; + ((Uint8 *)s->pixels)[y*s->pitch + x*(s->format->BytesPerPixel+1)] = (p & 0x0000ff00) >> 8; + ((Uint8 *)s->pixels)[y*s->pitch + x*(s->format->BytesPerPixel+2)] = (p & 0x00ff0000) >> 16; +} + SDL_Surface * createSurface(int width, int height) { Uint32 rmask, gmask, bmask, amask; @@ -28,14 +47,20 @@ SDL_Surface * createSurface(int width, int height) { SDL_Surface * makeTerrain(gameIni_t *gIni, gameRess_t *gRess) { int res, i; - SDL_Rect dstRect; - SDL_Surface *terrain, *tile; + int x,y,xmin,xmax,ymin,ymax,y2,xdst, ydst; + Uint32 srcPixel, dstPixel, srcStencil, dstStencil; + SDL_Surface *terrain, *stencil, *tile; terrain=createSurface(LEVEL_WIDTH, LEVEL_HEIGHT); if (terrain==NULL) { logs(LOG_ERROR, "makeTerrain(), SDL_CreateRGBSurface() returns NULL"); return NULL; } + stencil=createSurface(LEVEL_WIDTH, LEVEL_HEIGHT); + if (stencil==NULL) { + logs(LOG_ERROR, "makeTerrain(), SDL_CreateRGBSurface() returns NULL"); + return NULL; + } res=SDL_FillRect(terrain, &(terrain->clip_rect), gIni->style.bgColor); if (res!=0) { @@ -43,6 +68,14 @@ SDL_Surface * makeTerrain(gameIni_t *gIni, gameRess_t *gRess) { return NULL; } + res=SDL_FillRect(stencil, &(stencil->clip_rect), ccc_nothing); + if (res!=0) { + logs(LOG_WARN, "makeTerrain(), SDL_FillRect() failed"); + return NULL; + } + + SDL_LockSurface(terrain); + SDL_LockSurface(stencil); for(i=0 ; i < gIni->level.terrainCount ; i++) { //FIXME : check sanity for id value tile=gRess->style.tiles[gIni->level.terrains[i].id]; @@ -50,15 +83,65 @@ SDL_Surface * makeTerrain(gameIni_t *gIni, gameRess_t *gRess) { logs(LOG_ERROR, "makeTerrain(), tile==NULL"); return NULL; } - dstRect.x=gIni->level.terrains[i].xpos; - dstRect.y=gIni->level.terrains[i].ypos; + // 8 : NO_OVERRIDE : marquer les pixels comme indestructibles pour les prochains plaquages + // 2 : REMOVE : oublier (rendre transparent) tous les pixels qu'on a déjà plaqué + // 4 : Upside Down + // 0 : Full : écrase tous les pixels (sauf ceux no_override) + + // For each tile pixel, without going outside of the terrain + ymin=(gIni->level.terrains[i].ypos>0)?0:-gIni->level.terrains[i].ypos; + ymax=min(tile->clip_rect.h, terrain->clip_rect.h - gIni->level.terrains[i].ypos); + xmin=(gIni->level.terrains[i].xpos>0)?0:-gIni->level.terrains[i].xpos; + xmax=min(tile->clip_rect.w, terrain->clip_rect.w - gIni->level.terrains[i].xpos); + SDL_LockSurface(tile); + for (y=ymin; ylevel.terrains[i].modifier % 4 ) { + y2=tile->clip_rect.h-1-y; + } else { + y2=y; + } + ydst=gIni->level.terrains[i].ypos+y; + xdst=gIni->level.terrains[i].xpos+x; + + // Grab current pixel and stencil state (from previous blits) + srcPixel=getPixel(tile, x, y2); + srcStencil=getPixel(stencil, xdst, ydst); + + // Act only if srcPixel is not transparent and srcStentil doesn't says NO_OVERRIDE + if ( (srcPixel != tile->format->colorkey) && ( srcStencil != ccc_nooverride) ) { + // If we have REMOVE modifier, dstPixel will be rolled back to bgColor, else, it will be identical to the source pixel + if ( gIni->level.terrains[i].modifier % 2 ) { + dstPixel=gIni->style.bgColor; + } else { + dstPixel=srcPixel; + } + putPixel(terrain, xdst, ydst, dstPixel); + + // If we have NO_OVERRIDE modifier, put that info on stencil, else, save that there is a (normal) terrain here + if ( gIni->level.terrains[i].modifier % 8 ) { + dstStencil=ccc_nooverride; + } else { + dstStencil=ccc_terrain; + } + putPixel(stencil, xdst, ydst, dstStencil); + } + + } + } + SDL_UnlockSurface(tile); +/* res=SDL_BlitSurface(tile, NULL, terrain, &dstRect); if (res!=0) { logs2(LOG_WARN, "makeTerrain(), SDL_BlitSurface()", SDL_GetError()); return NULL; } +*/ } + SDL_UnlockSurface(stencil); + SDL_UnlockSurface(terrain); return terrain; } diff --git a/src/include/utils.h b/src/include/utils.h index 021816d..085884d 100644 --- a/src/include/utils.h +++ b/src/include/utils.h @@ -12,4 +12,7 @@ void logs(int level, char msg[]); void logs2(int level, char context[], char msg[]); void logp(int level, char msg[]); +int min(int a, int b); +int max(int a, int b); + #endif //UTILS_H diff --git a/src/utils.c b/src/utils.c index 5d828ab..a470a9f 100644 --- a/src/utils.c +++ b/src/utils.c @@ -36,3 +36,5 @@ void logp(int level, char msg[]) { fprintf(fdLog,"%i - %s : %s\n", level, msg, errMsg); } +int min(int a, int b) { return (ab)?a:b; } -- cgit v1.2.3