summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLudovic Pouzenc <ludovic@pouzenc.fr>2010-12-11 10:14:22 +0000
committerLudovic Pouzenc <ludovic@pouzenc.fr>2010-12-11 10:14:22 +0000
commit1eac9d1f82dc92722ecaeb9fbe9cbbfa7726651c (patch)
tree94246767f2c471dd3aa5d2c3aaad3477bc59b509
parenta1a8ffa6a66367db634065a94a6eec2b36f63864 (diff)
download2010-netlemmings-1eac9d1f82dc92722ecaeb9fbe9cbbfa7726651c.tar.gz
2010-netlemmings-1eac9d1f82dc92722ecaeb9fbe9cbbfa7726651c.tar.bz2
2010-netlemmings-1eac9d1f82dc92722ecaeb9fbe9cbbfa7726651c.zip
Fin de création de l'architecture pour les dirty rectangle. La méthode findAndSortZOrder pourra faire un bête scan des objets ou utiliser un R-Tree pour gagner en perfs. Il faut déplacer les dernières fonctions ajoutées dans netlem.c vers graphic.c et implémenter ce qui ne l'est pas.
git-svn-id: file:///var/svn/2010-netlemmings/trunk@189 077b3477-7977-48bd-8428-443f22f7bfda
-rw-r--r--src/graphic.c42
-rw-r--r--src/include/data_localgame.h22
-rw-r--r--src/netlem.c89
-rw-r--r--src/test/testfunc_004_buildterrain.c4
4 files changed, 113 insertions, 44 deletions
diff --git a/src/graphic.c b/src/graphic.c
index b9990f6..b596be8 100644
--- a/src/graphic.c
+++ b/src/graphic.c
@@ -76,31 +76,31 @@ int paintTerrain(gameIni_t *gIni, gameRess_t *gRess, gameGraphics_t *gGraph) {
Uint32 dstPixel, dstStencil;
SDL_Surface *tile;
- gGraph->terrain=createSurface(LEVEL_WIDTH, LEVEL_HEIGHT);
- if (gGraph->terrain==NULL) {
+ gGraph->surfaces.terrain=createSurface(LEVEL_WIDTH, LEVEL_HEIGHT);
+ if (gGraph->surfaces.terrain==NULL) {
logs(LOG_ERROR, "paintTerrain(), SDL_CreateRGBSurface() returns NULL");
return 1;
}
- gGraph->stencil=createSurface(LEVEL_WIDTH, LEVEL_HEIGHT);
- if (gGraph->stencil==NULL) {
+ gGraph->surfaces.stencil=createSurface(LEVEL_WIDTH, LEVEL_HEIGHT);
+ if (gGraph->surfaces.stencil==NULL) {
logs(LOG_ERROR, "paintTerrain(), SDL_CreateRGBSurface() returns NULL");
return 2;
}
- res=SDL_FillRect(gGraph->terrain, &(gGraph->terrain->clip_rect), gIni->style.bgColor);
+ res=SDL_FillRect(gGraph->surfaces.terrain, &(gGraph->surfaces.terrain->clip_rect), gIni->style.bgColor);
if (res!=0) {
logs(LOG_WARN, "paintTerrain(), SDL_FillRect() failed");
return 3;
}
- res=SDL_FillRect(gGraph->stencil, &(gGraph->stencil->clip_rect), ccc_nothing);
+ res=SDL_FillRect(gGraph->surfaces.stencil, &(gGraph->surfaces.stencil->clip_rect), ccc_nothing);
if (res!=0) {
logs(LOG_WARN, "paintTerrain(), SDL_FillRect() failed");
return 4;
}
- SDL_LockSurface(gGraph->terrain);
- SDL_LockSurface(gGraph->stencil);
+ SDL_LockSurface(gGraph->surfaces.terrain);
+ SDL_LockSurface(gGraph->surfaces.stencil);
for(i=0 ; i < gIni->level.terrainCount ; i++) {
//FIXME : check sanity for id value
tile=gRess->style.tiles[gIni->level.terrains[i].id];
@@ -131,9 +131,9 @@ int paintTerrain(gameIni_t *gIni, gameRess_t *gRess, gameGraphics_t *gGraph) {
// 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, gGraph->terrain->clip_rect.h - gIni->level.terrains[i].ypos);
+ ymax=min(tile->clip_rect.h, gGraph->surfaces.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, gGraph->terrain->clip_rect.w - gIni->level.terrains[i].xpos);
+ xmax=min(tile->clip_rect.w, gGraph->surfaces.terrain->clip_rect.w - gIni->level.terrains[i].xpos);
SDL_LockSurface(tile);
for (y=ymin; y<ymax; y+=2) {
@@ -152,7 +152,7 @@ int paintTerrain(gameIni_t *gIni, gameRess_t *gRess, gameGraphics_t *gGraph) {
// Always paint pixel, except in one case:
// If we are in NO_OVERRIDE mode and there is already a terrain on the current (source) pixel
if ( !( (modifier & 8) == 8 &&
- getPixel(gGraph->stencil, xdst, ydst) == ccc_terrain ) ) {
+ getPixel(gGraph->surfaces.stencil, xdst, ydst) == ccc_terrain ) ) {
// If we have REMOVE modifier, dstPixel will be rolled back to bgColor, else, it will be identical to the source pixel. We have to update stencil consistenly.
if ( (modifier & 2) == 2 ) {
dstPixel=gIni->style.bgColor;
@@ -163,22 +163,22 @@ int paintTerrain(gameIni_t *gIni, gameRess_t *gRess, gameGraphics_t *gGraph) {
}
//FIXME : optimiser le nombre d'appels ici !
- putPixel(gGraph->terrain, xdst, ydst, dstPixel);
- putPixel(gGraph->terrain, xdst+1, ydst, dstPixel);
- putPixel(gGraph->terrain, xdst, ydst+1, dstPixel);
- putPixel(gGraph->terrain, xdst+1, ydst+1, dstPixel);
- putPixel(gGraph->stencil, xdst, ydst, dstStencil);
- putPixel(gGraph->stencil, xdst+1, ydst, dstStencil);
- putPixel(gGraph->stencil, xdst, ydst+1, dstStencil);
- putPixel(gGraph->stencil, xdst+1, ydst+1, dstStencil);
+ putPixel(gGraph->surfaces.terrain, xdst, ydst, dstPixel);
+ putPixel(gGraph->surfaces.terrain, xdst+1, ydst, dstPixel);
+ putPixel(gGraph->surfaces.terrain, xdst, ydst+1, dstPixel);
+ putPixel(gGraph->surfaces.terrain, xdst+1, ydst+1, dstPixel);
+ putPixel(gGraph->surfaces.stencil, xdst, ydst, dstStencil);
+ putPixel(gGraph->surfaces.stencil, xdst+1, ydst, dstStencil);
+ putPixel(gGraph->surfaces.stencil, xdst, ydst+1, dstStencil);
+ putPixel(gGraph->surfaces.stencil, xdst+1, ydst+1, dstStencil);
}
}
}
}
SDL_UnlockSurface(tile);
}
- SDL_UnlockSurface(gGraph->stencil);
- SDL_UnlockSurface(gGraph->terrain);
+ SDL_UnlockSurface(gGraph->surfaces.stencil);
+ SDL_UnlockSurface(gGraph->surfaces.terrain);
return 0;
}
diff --git a/src/include/data_localgame.h b/src/include/data_localgame.h
index 9153d6e..01f5008 100644
--- a/src/include/data_localgame.h
+++ b/src/include/data_localgame.h
@@ -5,15 +5,27 @@
typedef struct {
SDL_Rect screen;
-
} gameConfig_t;
typedef struct {
- SDL_Surface *screen, *terrain, *stencil;
- SDL_Rect viewport; // Viewport top-left corner coords in screen
- int dirtRectsCount; // Dirt rectangle to refresh for current tick
- SDL_Rect *dirtRects;
+ int zOrder, surfId, animFrames, currentAnimFrame;
+ SDL_Rect *objectsBBox;
+} gameGraphObjState_t;
+
+typedef struct {
+ SDL_Surface *screen, *terrain, *stencil, **objectsSurf;
+ gameGraphObjState_t *objectsStat;
+} gameGraphSurfaces_t;
+
+typedef struct {
+ SDL_Surface *screen;
+ SDL_Rect viewport; // Viewport top-left corner coords in screen
+
+ gameGraphSurfaces_t surfaces;
+
+ int dirtRectsCount;
+ SDL_Rect *dirtRects; // Dirt rectangles to refresh for current tick
} gameGraphics_t;
typedef struct {
diff --git a/src/netlem.c b/src/netlem.c
index 8e43d13..9628050 100644
--- a/src/netlem.c
+++ b/src/netlem.c
@@ -51,6 +51,10 @@ void processLocalEvents(SDL_Rect *viewport, SDL_Rect *screen, SDL_Rect *terrain)
int act(tick_t *tick, int loadProgress, TCPsocket sockClient, int *dirtRectsCount, SDL_Rect **dirtRects);
int updateGraphics(gameGraphics_t *gGraph);
+int repaint(gameGraphSurfaces_t *srcSurfs, SDL_Rect *srcRect, SDL_Surface *dstSurf, SDL_Rect dstRect);
+int findAndZSortObjects(gameGraphObjState_t *objectsStat, SDL_Rect *offsetRect, gameGraphObjState_t **objectsFound);
+int paintObject(gameGraphObjState_t *obj, SDL_Rect *srcRect, SDL_Surface *dstSurf);
+
int main(int argc, char **argv) {
@@ -161,7 +165,7 @@ int main(int argc, char **argv) {
// Process local player keyboard and mouse events
// (note: remote events are processed by network read thread)
- processLocalEvents(&(gGraph.viewport), &(gGraph.screen->clip_rect), &(gGraph.terrain->clip_rect));
+ processLocalEvents(&(gGraph.viewport), &(gGraph.screen->clip_rect), &(gGraph.surfaces.terrain->clip_rect));
endMainLoop=act(&tick, loadProgress, client.sockClient, &(gGraph.dirtRectsCount), &(gGraph.dirtRects));
@@ -247,14 +251,14 @@ int init(gameConfig_t *conf, gameGraphics_t *gGraph) {
SDL_ShowCursor(0);
// Memory allocation and initialization for all display layers
- gGraph->terrain = createSurface(LEVEL_WIDTH, LEVEL_HEIGHT);
- if( gGraph->terrain == NULL ) {
+ gGraph->surfaces.terrain = createSurface(LEVEL_WIDTH, LEVEL_HEIGHT);
+ if( gGraph->surfaces.terrain == NULL ) {
logs2(LOG_ERROR, "init(), SDL_createSurface()", SDL_GetError());
return 3;
}
- gGraph->stencil = createSurface(LEVEL_WIDTH, LEVEL_HEIGHT);
- if( gGraph->stencil == NULL ) {
+ gGraph->surfaces.stencil = createSurface(LEVEL_WIDTH, LEVEL_HEIGHT);
+ if( gGraph->surfaces.stencil == NULL ) {
logs2(LOG_ERROR, "init(), SDL_createSurface()", SDL_GetError());
return 3;
}
@@ -546,25 +550,21 @@ int updateGraphics(gameGraphics_t *gGraph) {
memcpy(gGraph->dirtRects, &(gGraph->screen->clip_rect), sizeof(SDL_Rect));
gGraph->dirtRectsCount=1;
}
- // We use a dirt rectangle method for performance
+ // We use a dirt rectangle method for performance
for(i=0; i<gGraph->dirtRectsCount; i++) {
- //FIXME : faire une vrai procedure qui va chercher les objets sur une zone donnée, qui paint tout dans l'ordre
srcRect.x=gGraph->dirtRects[i].x+lastViewport.x;
srcRect.y=gGraph->dirtRects[i].y+lastViewport.y;
srcRect.w=gGraph->dirtRects[i].w;
srcRect.h=gGraph->dirtRects[i].h;
- res=SDL_BlitSurface(gGraph->terrain, &srcRect, gGraph->screen, gGraph->dirtRects+i);
- if ( res!=0 ) {
- logs2(LOG_DEBUG, "updateGraphics(), SDL_BlitSurface()", SDL_GetError());
- return res;
- }
+ res=repaint(&gGraph->surfaces, &srcRect, gGraph->screen, gGraph->dirtRects[i]);
+ if ( res != 0 ) {
+ logs(LOG_WARN, "updateGraphics(), repain() failed");
+ }
SDL_UpdateRect(gGraph->screen,
- gGraph->dirtRects[i].x,
- gGraph->dirtRects[i].y,
- gGraph->dirtRects[i].w,
- gGraph->dirtRects[i].h);
+ gGraph->dirtRects[i].x, gGraph->dirtRects[i].y,
+ gGraph->dirtRects[i].w, gGraph->dirtRects[i].h);
}
gGraph->dirtRectsCount=0;
free(gGraph->dirtRects);
@@ -575,3 +575,60 @@ int updateGraphics(gameGraphics_t *gGraph) {
return 0;
}
+
+int repaint(gameGraphSurfaces_t *srcSurfs, SDL_Rect *srcRect, SDL_Surface *dstSurf, SDL_Rect dstRect) {
+ int objToRepaintCount, i, res;
+ gameGraphObjState_t *objToRepaint;
+ SDL_Surface *tmpSurf;
+
+ tmpSurf=createSurface(srcRect->w, srcRect->h);
+ if (tmpSurf==NULL) {
+ logs(LOG_ERROR, "repain(), createSurface() has failed");
+ return 1;
+ }
+ objToRepaintCount=findAndZSortObjects(srcSurfs->objectsStat, srcRect, &objToRepaint);
+
+ for(i=0;i<objToRepaintCount;++i) {
+ if(objToRepaint[i].zOrder>0) break;
+ res=paintObject(objToRepaint+i, srcRect, tmpSurf);
+ if ( res!=0 ) {
+ logs(LOG_DEBUG, "repaint(), paintObject() failed");
+ return res;
+ }
+ }
+
+ res=SDL_BlitSurface(srcSurfs->terrain, srcRect, tmpSurf, NULL);
+ if ( res!=0 ) {
+ logs2(LOG_DEBUG, "repaint(), SDL_BlitSurface()", SDL_GetError());
+ return res;
+ }
+
+ for(;i<objToRepaintCount;++i) {
+ res=paintObject(objToRepaint+i, srcRect, tmpSurf);
+ if ( res!=0 ) {
+ logs(LOG_DEBUG, "repaint(), paintObject() failed");
+ return res;
+ }
+ }
+
+ res=SDL_BlitSurface(tmpSurf, NULL, dstSurf, &dstRect);
+ if ( res!=0 ) {
+ logs2(LOG_DEBUG, "repaint(), SDL_BlitSurface()", SDL_GetError());
+ return res;
+ }
+
+ return 0;
+}
+
+int findAndZSortObjects(gameGraphObjState_t *objectsStat, SDL_Rect *offsetRect, gameGraphObjState_t **objectsFound) {
+ //TODO
+ fprintf(stderr, "TODO findAndZSortObjects(%p, %p, %p)\n", (void *)objectsStat,(void *)offsetRect,(void *)objectsFound);
+ *objectsFound=NULL;
+ return 0;
+}
+
+int paintObject(gameGraphObjState_t *obj, SDL_Rect *srcRect, SDL_Surface *dstSurf) {
+ //TODO
+ fprintf(stderr, "TODO paintObject(%p, %p, %p)\n", (void *)obj,(void *)srcRect,(void *)dstSurf);
+ return 0;
+}
diff --git a/src/test/testfunc_004_buildterrain.c b/src/test/testfunc_004_buildterrain.c
index 6be0015..6aec988 100644
--- a/src/test/testfunc_004_buildterrain.c
+++ b/src/test/testfunc_004_buildterrain.c
@@ -72,13 +72,13 @@ int main(int argc, char **argv) {
exit(3);
}
snprintf(filepath, MAX_PATH_LEN, "%s/%s_%s.bmp", PATH_TMP, argv[1], argv[2]);
- res=SDL_SaveBMP(gGraph.terrain, filepath);
+ res=SDL_SaveBMP(gGraph.surfaces.terrain, filepath);
if (res!=0) {
fprintf(stderr, "Cannot SaveBMP\n");
exit(4);
}
snprintf(filepath, MAX_PATH_LEN, "%s/%s_%s-stencil.bmp", PATH_TMP, argv[1], argv[2]);
- res=SDL_SaveBMP(gGraph.stencil, filepath);
+ res=SDL_SaveBMP(gGraph.surfaces.stencil, filepath);
if (res!=0) {
fprintf(stderr, "Cannot SaveBMP\n");
exit(4);