From 76331a09ac00aea941f86a80bb95c398b51c7812 Mon Sep 17 00:00:00 2001 From: Ludovic Pouzenc Date: Sun, 12 Dec 2010 21:19:10 +0000 Subject: ATTENTION - Version qui ne compile pas. Gros changements dans le fonctionnement des dirtyRectangles. Le netlem.c est cohérent avec les .h mais par contre les .c correspondants aux .h n'ont pas été modifiés. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: file:///var/svn/2010-netlemmings/trunk@206 077b3477-7977-48bd-8428-443f22f7bfda --- src/include/data_localgame.h | 49 ++++++++----- src/include/data_ress.h | 1 + src/include/game.h | 3 +- src/include/graphic.h | 6 +- src/netlem.c | 165 ++++++++++++++++++++----------------------- 5 files changed, 113 insertions(+), 111 deletions(-) diff --git a/src/include/data_localgame.h b/src/include/data_localgame.h index db6a9dd..b4716f7 100644 --- a/src/include/data_localgame.h +++ b/src/include/data_localgame.h @@ -2,28 +2,15 @@ #define DATA_LOCALGAME_H #include "data_types.h" +#include "SDL/SDL.h" #define DEBUG_DIRTYRECTANGLES 1 // Structures de données pour la partie en cours, sur l'ordinateur local -// Etat des différents objets de la map -typedef struct { - // zOrder < 0 : dessiné avant le terrain, sinon après le terrain (0 est uen valeur réservée) - int zOrder; - // surfId : Index du SDL_Surface de l'objet consiédéré (confère gameGraphSurfaces_t / objectsSurf) - int surfId; - // Information sur l'état de l'animation de l'objet - int animFrames, currentAnimFrame; - // Bounding box (plus petit rectangle qui continet tous les pixels de l'objet, utile pour updateGraphics()) - SDL_Rect *objectsBBox; -} gameGraphObjState_t; - // Ensemble des buffers graphiques du jeu (sauf l'écran) typedef struct { SDL_Surface *screen, *terrain, *stencil, *tmpSurf; - // For loaded Gif tiles, see data_ress.h - gameGraphObjState_t *objectsStat; } gameGraphSurfaces_t; // Gestion de l'écran et de la caméra @@ -33,11 +20,39 @@ typedef struct { gameGraphSurfaces_t surfaces; - int dirtRectsCount; - SDL_Rect *dirtRects; // Dirt rectangles to refresh for current tick +} gameGraphics_t; + +// Etat des différents objets de la map +struct gameObjectState { + // zOrder < 0 : dessiné avant le terrain. zOrder > 0 : déssiné après le terrain. 0 est une valeur réservée. + int zOrder; + // surfId : Index du SDL_Surface de l'objet considéré (confère gameGraphSurfaces_t / objectsSurf) + int surfId; + // Information sur l'état de l'animation de l'objet + int animFrames, currentAnimFrame; + // Flags pour objets dont la procédure de dessin est spéciale + int modifiers; + // Flag disant si l'objet a été déclanché ou non + int triggered; + // date (en ticks) du déclanchement de l'objet + tick_t trigDate; + // Signale que l'objet doit être redessiné + int dirty; + // Position de l'objet (et position précédente, pour updateGraphics()) + pos_t pos, prevPos; + // Pointeur vers la surface correspondante (cf data_ress.h) + SDL_Surface *s; +}; +typedef struct { + int objCount; + struct gameObjectState *allObj, cursor; +} gameObjectsState_t; + +// Paramèters locaux dynamiques +typedef struct { int debugFlags; -} gameGraphics_t; +} localParams_t; // Paramètes de jeu envoyés par le serveur (niveau en cours, etc) typedef struct { diff --git a/src/include/data_ress.h b/src/include/data_ress.h index 2513e81..b09c996 100644 --- a/src/include/data_ress.h +++ b/src/include/data_ress.h @@ -11,6 +11,7 @@ struct miscRess { SDL_Surface **lemmingAnims, **lemmingMasks, **lemmingImasks, **icons; SDL_Surface *font1, *font2, *countdown, *cursor, *explode; }; + // Image ressources loaded from files referenced in the style INI file typedef struct { struct styleRess style; diff --git a/src/include/game.h b/src/include/game.h index fba84db..2b7e33b 100644 --- a/src/include/game.h +++ b/src/include/game.h @@ -2,8 +2,9 @@ #define GAME_H #include "data_types.h" +#include "data_localgame.h" #include "SDL/SDL.h" -void play(tick_t tick, int *dirtRectsCount, SDL_Rect **directRects ); +void play(tick_t tick, gameObjectsState_t *objStates); #endif //GAME_H diff --git a/src/include/graphic.h b/src/include/graphic.h index 52cc031..13ac889 100644 --- a/src/include/graphic.h +++ b/src/include/graphic.h @@ -21,8 +21,8 @@ SDL_Surface * loadGif(char *filePath); int init(char *winCaption, gameConfig_t *conf, gameGraphics_t *gGraph); int paintTerrain(gameIni_t *gIni, gameRess_t *gRess, 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, SDL_Rect *dstRect); +int repaint(gameObjectsState_t *objStates, gameGraphSurfaces_t *srcSurfs, SDL_Rect *srcRect, SDL_Surface *dstSurf, SDL_Rect dstRect); +int findAndZSortObjects(gameObjectsState_t *objectsStat, SDL_Rect *offsetRect, gameObjectsState_t **objectsFound); +int paintObject(gameObjectsState_t *obj, SDL_Rect *srcRect, SDL_Surface *dstSurf, SDL_Rect *dstRect); #endif /*GRAPHIC_H*/ diff --git a/src/netlem.c b/src/netlem.c index 2b62fb2..32b339d 100644 --- a/src/netlem.c +++ b/src/netlem.c @@ -19,6 +19,8 @@ // Application version number #include "netlem.h" +#define STATS_TICKCOUNT 10 + // Thread arguments structures struct _networkReadProc_args { client_t *client; @@ -45,24 +47,27 @@ int loadLevelProc(void *a); // Client-specific functions void signals(int signum); -void processLocalEvents(gameGraphics_t *gGraph); -int act(tick_t *tick, int loadProgress, TCPsocket sockClient, int *dirtRectsCount, SDL_Rect **dirtRects); -int updateGraphics(gameGraphics_t *gGraph); +void processLocalEvents(SDL_Rect *terrain, SDL_Rect *viewport, gameObjectsState_t *objStates, localParams_t *params); +int act(tick_t *tick, int loadProgress, TCPsocket sockClient, gameObjectsState_t *objStates); +int updateGraphics(gameObjectsState_t *objStates, localParams_t *params, gameGraphics_t *gGraph); int main(int argc, char **argv) { int drift_ms=0, endMainLoop, result; tick_t tick=0, lastServerTick=0; - Uint32 timeBefore_ms[10], beforeWait[10], wantWait[10], waited[10], t; + Uint32 timeBefore_ms[STATS_TICKCOUNT], beforeWait[STATS_TICKCOUNT], wantWait[STATS_TICKCOUNT], t; Uint8 loadProgress=0; - double fps, waitedMean, wantWaitMean; + double fps, wantWaitMean; client_t client; serverParams_t serverParams; + localParams_t localParams; + gameConfig_t conf; gameIni_t gIni; gameRess_t gRess; gameGraphics_t gGraph; + gameObjectsState_t gObjStates; char logMsg[128]; struct _networkReadProc_args args; @@ -145,49 +150,36 @@ int main(int argc, char **argv) { return 6; } - memset(timeBefore_ms, 0, 10*sizeof(Uint32)); - memset(beforeWait, 0, 10*sizeof(Uint32)); - memset(wantWait, 0, 10*sizeof(Uint32)); - memset(waited, 0, 10*sizeof(Uint32)); + memset(timeBefore_ms, 0, STATS_TICKCOUNT*sizeof(Uint32)); + memset(beforeWait, 0, STATS_TICKCOUNT*sizeof(Uint32)); + memset(wantWait, 0, STATS_TICKCOUNT*sizeof(Uint32)); t=0; // Main game loop endMainLoop=0; while(!endMainLoop) { - // Store loop begin date in a 10 entries rotate buffer - t=(t+1)%10; + // Store loop begin date in a STATS_TICKCOUNT entries rotate buffer + t=(t+1)%STATS_TICKCOUNT; timeBefore_ms[t] = SDL_GetTicks(); // Process local player keyboard and mouse events // (note: remote events are processed by network read thread) - processLocalEvents(&gGraph); + processLocalEvents(&(gGraph.surfaces.terrain->clip_rect), &(gGraph.viewport), &gObjStates, &localParams ); - endMainLoop=act(&tick, loadProgress, client.sockClient, &(gGraph.dirtRectsCount), &(gGraph.dirtRects)); + endMainLoop=act(&tick, loadProgress, client.sockClient, &gObjStates); // Display that new game state to the local user - updateGraphics(&gGraph); - + updateGraphics(&gObjStates, &localParams, &gGraph); // Delay that we have to wait for the next frame (depends on execution time and network time drift) - beforeWait[t]=SDL_GetTicks(); wantWait[t]=waitForNextTick(timeBefore_ms[t], drift_ms); - waited[t]=SDL_GetTicks(); - waited[t] -= beforeWait[t]; - // Compute & display FPS mean value on 10 loops - if (t==0) { - fps=10000.0/(timeBefore_ms[t]-timeBefore_ms[(t+1)%10]); - wantWaitMean=0; - waitedMean=0; - for(;t<10;t++) { - wantWaitMean+=wantWait[t]; - waitedMean+=waited[t]; - } - t=0; - wantWaitMean/=10.0; - waitedMean/=10.0; -// snprintf(logMsg, 128, "tick:%d\tlastServerTick:%d\tdrift_ms:%d\t\t%.1f FPS\t WW:%.1f\tW:%.1f\n", tick, lastServerTick, drift_ms, fps, wantWaitMean, waitedMean); - snprintf(logMsg, 128, "tick:%d\tlastServerTick:%d\tdrift_ms:%d\t\t%.1f FPS\t WW:%d\tW:%d\n", tick, lastServerTick, drift_ms, fps, wantWait[3], waited[3]); + // Compute & display FPS mean value on STATS_TICKCOUNT ticks + if (t==0) { + fps=(STATS_TICKCOUNT*1000.0)/(timeBefore_ms[t]-timeBefore_ms[(t+1)%STATS_TICKCOUNT]); + wantWaitMean=0; for(;tdebugFlags ^= DEBUG_DIRTYRECTANGLES; + params->debugFlags ^= DEBUG_DIRTYRECTANGLES; break; default: break; @@ -470,19 +460,12 @@ void processLocalEvents(gameGraphics_t *gGraph) { case SDL_MOUSEMOTION: mouseX = event.motion.x; mouseY = event.motion.y; - - //FIXME : utiliser une méthode addDirtRect - gGraph->dirtRects=malloc(1*sizeof(SDL_Rect)); - gGraph->dirtRects[0].x=mouseX-16; - gGraph->dirtRects[0].y=mouseY-16; - gGraph->dirtRects[0].w=32; - gGraph->dirtRects[0].h=32; - gGraph->dirtRectsCount=1; - + objStates->cursor.pos.x = mouseX; + objStates->cursor.pos.y = mouseY; + objStates->cursor.dirty=1; break; case SDL_MOUSEBUTTONDOWN: //err=mouse_action(&gInit, mouseX, mouseY,camera.x,camera.y ); - //if(err!=0){return err;} //FIXME : WTF ? break; case SDL_QUIT: changeState(eEnd); @@ -493,15 +476,15 @@ void processLocalEvents(gameGraphics_t *gGraph) { switch(getState()) { case eMultiGame: if (mouseActive) { - if(mouseY <= gGraph->surfaces.terrain->h){ - if (mouseX > (gGraph->screen->w - MAP_SCROLL_BOUND)){ - if (gGraph->viewport.x < (gGraph->surfaces.terrain->w - gGraph->screen->clip_rect.w ) ) { - gGraph->viewport.x += MAP_SCROLL_SPEED; + if(mouseY <= terrain->h){ + if (mouseX > (viewport->w - MAP_SCROLL_BOUND)){ + if (viewport->x < (terrain->w - viewport->w ) ) { + viewport->x += MAP_SCROLL_SPEED; } } if (mouseX < MAP_SCROLL_BOUND){ - if (gGraph->viewport.x >= MAP_SCROLL_SPEED ) { - gGraph->viewport.x -= MAP_SCROLL_SPEED; + if (viewport->x >= MAP_SCROLL_SPEED ) { + viewport->x -= MAP_SCROLL_SPEED; } } } @@ -514,11 +497,12 @@ void processLocalEvents(gameGraphics_t *gGraph) { return; } -int updateGraphics(gameGraphics_t *gGraph) { +int updateGraphics(gameObjectsState_t *objStates, localParams_t *params, gameGraphics_t *gGraph) { int i, res; - static SDL_Rect lastViewport= {-1,-1,-1,-1}; - SDL_Rect srcRect; + static SDL_Rect lastViewport= {0,0,0,0}; + SDL_Rect srcRect, dstRect; SDL_Surface *tmpSurf; + struct gameObjectState *o; //TODO : modifier les calques switch(getState()) { @@ -527,48 +511,49 @@ int updateGraphics(gameGraphics_t *gGraph) { break; case eMultiGame: // If we had a camera movement, we have to refesh all the screen - //if ( memcmp(&lastViewport, &(gGraph->viewport), sizeof(SDL_Rect)) != 0) { + tmpSurf=gGraph->surfaces.tmpSurf; if ( lastViewport.x != gGraph->viewport.x ) { - //lastViewport=gGraph->viewport; lastViewport.x=gGraph->viewport.x; - if ( gGraph->dirtRectsCount > 0 ) { - free(gGraph->dirtRects); - } - // Put only one dirt rectangle, of the size of the screen - gGraph->dirtRects=malloc(1*sizeof(SDL_Rect)); - memcpy(gGraph->dirtRects, &(gGraph->screen->clip_rect), sizeof(SDL_Rect)); - gGraph->dirtRectsCount=1; - } - - // We use a dirty rectangle method for performance - tmpSurf=gGraph->surfaces.tmpSurf; - for(i=0; idirtRectsCount; i++) { - 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=repaint(&gGraph->surfaces, &srcRect, tmpSurf, srcRect); + srcRect.x=lastViewport.x; + srcRect.y=lastViewport.y; + srcRect.w=gGraph->screen->clip_rect.w; + srcRect.h=gGraph->screen->clip_rect.h; + res=repaint(objStates, &gGraph->surfaces, &srcRect, tmpSurf, srcRect); if ( res != 0 ) { logs(LOG_WARN, "updateGraphics(), repaint() failed"); } - if ( (gGraph->debugFlags & DEBUG_DIRTYRECTANGLES) == 0 ) { - res=SDL_BlitSurface(tmpSurf, &srcRect, gGraph->screen, gGraph->dirtRects+i); - if ( res!=0 ) { - logs2(LOG_DEBUG, "repaint(), SDL_BlitSurface()", SDL_GetError()); - } + } else { + // We use a dirty rectangle method for performance + for(i=0; iobjCount; i++) { + o=objStates->allObj+i; + + dstRect.x=o->pos.x; + dstRect.y=o->pos.y; + dstRect.w=o->s->clip_rect.w; + dstRect.h=o->s->clip_rect.h; + if ( /*TODO intersect(viewport, dstRect) &&*/ o->dirty == 1 ) { + srcRect.x=o->pos.x+lastViewport.x; + srcRect.y=o->pos.y+lastViewport.y; + srcRect.w=o->s->clip_rect.w; + srcRect.h=o->s->clip_rect.h; + + res=repaint(objStates, &gGraph->surfaces, &srcRect, tmpSurf, srcRect); + if ( res != 0 ) { + logs(LOG_WARN, "updateGraphics(), repaint() failed"); + } + if ( (params->debugFlags & DEBUG_DIRTYRECTANGLES) == 0 ) { + res=SDL_BlitSurface(tmpSurf, &srcRect, gGraph->screen, &dstRect); + if ( res!=0 ) { + logs2(LOG_DEBUG, "repaint(), SDL_BlitSurface()", SDL_GetError()); + } - SDL_UpdateRect(gGraph->screen, - gGraph->dirtRects[i].x, gGraph->dirtRects[i].y, - gGraph->dirtRects[i].w, gGraph->dirtRects[i].h); + SDL_UpdateRect(gGraph->screen, dstRect.x, dstRect.y, dstRect.w, dstRect.h); + } + } } } - if (gGraph->dirtRectsCount > 0) { - gGraph->dirtRectsCount=0; - free(gGraph->dirtRects); - } - if ( (gGraph->debugFlags & DEBUG_DIRTYRECTANGLES) == DEBUG_DIRTYRECTANGLES ) { + if ( (params->debugFlags & DEBUG_DIRTYRECTANGLES) == DEBUG_DIRTYRECTANGLES ) { srcRect.x=lastViewport.x; srcRect.y=lastViewport.y; srcRect.w=gGraph->screen->clip_rect.w; -- cgit v1.2.3