From 2952c4a61eb1838a8d7ada77ecc3b7c2ae3829df Mon Sep 17 00:00:00 2001 From: Ludovic Pouzenc Date: Sun, 28 Nov 2010 16:55:46 +0000 Subject: Amélioration de l'algo de plaquage graphique. Le fichier level2000 est rendu de la même façon sous Lemini et avec mes sources. Les 10 et 14 sont ramenés à 8 et 12 (no_override prime sur remove) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: file:///var/svn/2010-netlemmings/trunk@180 077b3477-7977-48bd-8428-443f22f7bfda --- level/3_test/lvl2000.ini | 43 +++++++++--- src/graphic.c | 129 +++++++++++++++++++---------------- src/include/graphic.h | 7 +- src/loader.c | 12 ++-- src/parser/parse_ini.yy | 1 + src/test/testfunc_004_buildterrain.c | 4 +- 6 files changed, 119 insertions(+), 77 deletions(-) diff --git a/level/3_test/lvl2000.ini b/level/3_test/lvl2000.ini index 296bf2c..b5a1311 100644 --- a/level/3_test/lvl2000.ini +++ b/level/3_test/lvl2000.ini @@ -12,20 +12,45 @@ numBashers = 99 numMiners = 99 numDiggers = 99 xPos = 200 -style = brick +style = crystal # Terrain # id, xpos, ypos, modifier # modifier: 8=NO_OVERWRITE, 4=UPSIDE_DOWN, 2=REMOVE (combining allowed, 0=FULL) -terrain_0 = 19, 0, 0, 0 -terrain_1 = 19, 100, 0, 0 -terrain_2 = 19, 110, 10, 2 -terrain_3 = 19, 200, 0, 4 -terrain_4 = 19, 210, 10, 6 -terrain_5 = 19, 300, 0, 0 -terrain_6 = 19, 310, 10, 8 -terrain_7 = 19, 320, 10, 0 +terrain_0 = 8, -20, -20, 12 +terrain_1 = 8, 3275, 300, 12 +terrain_2 = 8, -20, 300, 0 +terrain_3 = 8, 3275, -20, 0 + +# un gros gems +terrain_4 = 8, 1000, 210, 0 + +# une grile percee en forme de gros gems +terrain_5 = 9, 1100, 200, 0 +terrain_6 = 8, 1110, 210, 2 + +# une grille percee en forme de gros gems à l'envers +terrain_7 = 9, 1300, 200, 4 +terrain_8 = 8, 1310, 210, 6 + +# un gems, une grille par dessus en no override, puis encore un gems +terrain_9 = 8, 1500, 200, 0 +terrain_10 = 9, 1510, 210, 8 +terrain_11 = 8, 1520, 210, 0 + +terrain_12 = 8, 1700, 200, 0 +terrain_13 = 9, 1710, 210, 8 +terrain_14 = 8, 1720, 210, 0 + +terrain_15 = 28, 1900, 200, 0 +terrain_16 = 8, 1900, 210, 10 +terrain_17 = 9, 1910, 220, 0 + +terrain_18 = 28, 2100, 200, 0 +terrain_19 = 8, 2100, 210, 0 +terrain_20 = 9, 2110, 220, 10 + name = test modifiers diff --git a/src/graphic.c b/src/graphic.c index 35d69c6..edbb799 100644 --- a/src/graphic.c +++ b/src/graphic.c @@ -9,14 +9,37 @@ #define SDLSURF_OPTS SDL_HWSURFACE|SDL_HWACCEL|/*SDL_ASYNCBLIT|*/SDL_RLEACCEL Uint32 getPixel(SDL_Surface *s, int x, int y) { - Uint32 res=0; + 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; +} + +Uint32 getPixel8BitPalette(SDL_Surface *s, int x, int y) { + Uint8 index; + SDL_Color c; + Uint32 res=0; + + index=((Uint8 *)s->pixels)[y*s->pitch + x]; + c=s->format->palette->colors[index]; + + //FIXME : Big Endian + res |= c.r << 0; + res |= c.g << 8; + res |= c.b << 16; return res; } +int isTransparent(SDL_Surface *s, int x, int y) { + Uint8 index; + + index=((Uint8 *)s->pixels)[y*s->pitch + x]; + return (index == s->format->colorkey); +} + void putPixel(SDL_Surface *s, int x, int y, Uint32 p) { //printf("putPixel(s, %i, %i, 0x%x)\n", x, y, p); //FIXME : Big Endian @@ -46,51 +69,36 @@ SDL_Surface * createSurface(int width, int height) { } -SDL_Surface * loadGifIn24Bpp(char *filePath) { - int res; - SDL_Surface *s1, *s2; - SDL_Rect dstRect = {0,0,0,0}; - - s1=IMG_Load(filePath); - if (s1==NULL) { return NULL; } - - s2=createSurface(s1->w, s1->h); - if (s2==NULL) { return NULL; } - SDL_SetColorKey(s2, SDL_SRCCOLORKEY, s1->format->colorkey); - - res=SDL_BlitSurface(s1, NULL, s2, &dstRect); - if (res!=0) return NULL; - - return s2; +SDL_Surface * loadGif(char *filePath) { + return IMG_Load(filePath); } -int makeTerrain(gameIni_t *gIni, gameRess_t *gRess, SDL_Surface **terrain, SDL_Surface **stencil) { +int paintTerrain(gameIni_t *gIni, gameRess_t *gRess, SDL_Surface **terrain, SDL_Surface **stencil) { int res, i; - int x,y,xmin,xmax,ymin,ymax,y2,xdst, ydst; + int x,y,xmin,xmax,ymin,ymax,y2,xdst, ydst, paint; Uint32 srcPixel, dstPixel, srcStencil, dstStencil; SDL_Surface *tile; - //SDL_Rect dstRect; *terrain=createSurface(LEVEL_WIDTH, LEVEL_HEIGHT); if (*terrain==NULL) { - logs(LOG_ERROR, "makeTerrain(), SDL_CreateRGBSurface() returns NULL"); + logs(LOG_ERROR, "paintTerrain(), SDL_CreateRGBSurface() returns NULL"); return 1; } *stencil=createSurface(LEVEL_WIDTH, LEVEL_HEIGHT); if (*stencil==NULL) { - logs(LOG_ERROR, "makeTerrain(), SDL_CreateRGBSurface() returns NULL"); + logs(LOG_ERROR, "paintTerrain(), SDL_CreateRGBSurface() returns NULL"); return 2; } res=SDL_FillRect(*terrain, &((*terrain)->clip_rect), gIni->style.bgColor); if (res!=0) { - logs(LOG_WARN, "makeTerrain(), SDL_FillRect() failed"); + logs(LOG_WARN, "paintTerrain(), SDL_FillRect() failed"); return 3; } res=SDL_FillRect(*stencil, &((*stencil)->clip_rect), ccc_nothing); if (res!=0) { - logs(LOG_WARN, "makeTerrain(), SDL_FillRect() failed"); + logs(LOG_WARN, "paintTerrain(), SDL_FillRect() failed"); return 4; } @@ -100,27 +108,36 @@ int makeTerrain(gameIni_t *gIni, gameRess_t *gRess, SDL_Surface **terrain, SDL_S //FIXME : check sanity for id value tile=gRess->style.tiles[gIni->level.terrains[i].id]; if (tile==NULL) { - logs(LOG_ERROR, "makeTerrain(), tile==NULL"); + logs(LOG_ERROR, "paintTerrain(), tile==NULL"); return 5; } -// dstRect.y=gIni->level.terrains[i].ypos; -// dstRect.x=gIni->level.terrains[i].xpos; + + // Special modifier values : + // 15 : Hidden : Lemini hack. Seems to be the same as NO_OVERRIDE + // Combinable modifier : // 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) + // 2 : REMOVE : oublier (rendre transparent) tous les pixels qu'on a déjà plaqué + + if (gIni->level.terrains[i].modifier == 15) { + gIni->level.terrains[i].modifier=8; + } + if ((gIni->level.terrains[i].modifier & 10) == 10) { + gIni->level.terrains[i].modifier &= ~2; + } // For each tile pixel, without going outside of the terrain - ymin=(gIni->level.terrains[i].ypos>0)?0:-gIni->level.terrains[i].ypos; + 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; + 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) == 4 ) { y2=tile->clip_rect.h-1-y; } else { @@ -129,39 +146,35 @@ int makeTerrain(gameIni_t *gIni, gameRess_t *gRess, SDL_Surface **terrain, SDL_S 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) == 2 ) { - dstPixel=gIni->style.bgColor; - } else { - dstPixel=srcPixel; - } - putPixel(*terrain, xdst, ydst, dstPixel); + // Act only if srcPixel is not transparent + if ( ! isTransparent(tile, x, y2) ) { + // Grab current pixel and stencil state (from previous blits) + srcPixel=getPixel8BitPalette(tile, x, y2); + srcStencil=getPixel(*stencil, xdst, ydst); - // 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) == 8 ) { - dstStencil=ccc_nooverride; + paint=( getPixel(*stencil, xdst, ydst) != ccc_terrain ); } else { - dstStencil=ccc_terrain; + paint=1; + } + + if ( paint == 1 ) { + // 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) == 2 ) { + dstPixel=gIni->style.bgColor; + dstStencil=0; + } else { + dstPixel=srcPixel; + dstStencil=ccc_terrain; + } + + putPixel(*terrain, xdst, ydst, dstPixel); + putPixel(*stencil, xdst, ydst, dstStencil); } - 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); diff --git a/src/include/graphic.h b/src/include/graphic.h index 7941210..e8ce669 100644 --- a/src/include/graphic.h +++ b/src/include/graphic.h @@ -6,9 +6,12 @@ #include "data_ress.h" Uint32 getPixel(SDL_Surface *s, int x, int y); +Uint32 getPixel8BitPalette(SDL_Surface *s, int x, int y); +int isTransparent(SDL_Surface *s, int x, int y); + void putPixel(SDL_Surface *s, int x, int y, Uint32 p); SDL_Surface * createSurface(int width, int height); -SDL_Surface * loadGifIn24Bpp(char *filePath); -int makeTerrain(gameIni_t *gIni, gameRess_t *gRess, SDL_Surface **terrain, SDL_Surface **stencil); +SDL_Surface * loadGif(char *filePath); +int paintTerrain(gameIni_t *gIni, gameRess_t *gRess, SDL_Surface **terrain, SDL_Surface **stencil); #endif /*GRAPHIC_H*/ diff --git a/src/loader.c b/src/loader.c index d83087c..de28df9 100644 --- a/src/loader.c +++ b/src/loader.c @@ -20,9 +20,9 @@ int loadRessources(gameIni_t *gIni, gameRess_t *gRess) { } for(i=0; i < gIni->style.tiles ; ++i) { snprintf(filepath, filenamelen, "%s/%s/%s_%d.gif", PATH_STYLE, gIni->style.name, gIni->style.name, i); - gRess->style.tiles[i] = loadGifIn24Bpp(filepath); + gRess->style.tiles[i] = loadGif(filepath); if(gRess->style.tiles[i]==NULL) { - logs2(LOG_WARN, "loadRessources(), loadGifIn24Bpp() error for ", filepath); + logs2(LOG_WARN, "loadRessources(), loadGif() error for ", filepath); return 2; } } @@ -42,9 +42,9 @@ int loadRessources(gameIni_t *gIni, gameRess_t *gRess) { for(i=0; i < gIni->style.objectCount ; ++i) { snprintf(filepath, filenamelen, "%s/%s/%so_%d.gif", PATH_STYLE, gIni->style.name, gIni->style.name, i); - gRess->style.objects[i] = loadGifIn24Bpp(filepath); + gRess->style.objects[i] = loadGif(filepath); if (gRess->style.objects[i]==NULL) { - logs2(LOG_WARN, "loadRessources(), loadGifIn24Bpp() error for ", filepath); + logs2(LOG_WARN, "loadRessources(), loadGif() error for ", filepath); return 2; } @@ -54,9 +54,9 @@ int loadRessources(gameIni_t *gIni, gameRess_t *gRess) { case 7: case 8: snprintf(filepath, filenamelen, "%s/%s/%som_%d.gif", PATH_STYLE, gIni->style.name, gIni->style.name, i); - gRess->style.objectMasks[i] = loadGifIn24Bpp(filepath); + gRess->style.objectMasks[i] = loadGif(filepath); if (gRess->style.objectMasks[i]==NULL) { - logs2(LOG_WARN, "loadRessources(), loadGifIn24Bpp() error for ", filepath); + logs2(LOG_WARN, "loadRessources(), loadGif() error for ", filepath); return 2; } break; diff --git a/src/parser/parse_ini.yy b/src/parser/parse_ini.yy index 39e0fcb..7d0a160 100644 --- a/src/parser/parse_ini.yy +++ b/src/parser/parse_ini.yy @@ -181,6 +181,7 @@ decl: BGCOLOR AFF INTHEX { gIni->style.bgColor = $3; } gIni->level.terrains[$2].xpos = $6; gIni->level.terrains[$2].ypos = $8; gIni->level.terrains[$2].modifier = $10; +if ($10!=0 && $10!=2 && $10!=4 && $10!=6 &&$10!=8 && $10!=10 &&$10!=12 && $10 != 15 ) printf("modifier==%i\n", $10); } } | STEEL INT AFF INT VIR INT VIR INT VIR INT { diff --git a/src/test/testfunc_004_buildterrain.c b/src/test/testfunc_004_buildterrain.c index d802542..882f499 100644 --- a/src/test/testfunc_004_buildterrain.c +++ b/src/test/testfunc_004_buildterrain.c @@ -75,9 +75,9 @@ int main(int argc, char **argv) { } SDL_UnlockSurface(tile); */ - res=makeTerrain(&gIni, &gRess, &terrain, &stencil); + res=paintTerrain(&gIni, &gRess, &terrain, &stencil); if (res!=0) { - fprintf(stderr, "Cannot makeTerrain\n"); + fprintf(stderr, "Cannot paintTerrain\n"); exit(3); } snprintf(filepath, MAX_PATH_LEN, "%s/%s_%s.bmp", PATH_TMP, argv[1], argv[2]); -- cgit v1.2.3