diff options
-rw-r--r-- | src/include/data_localgame.h | 49 | ||||
-rw-r--r-- | src/include/data_ress.h | 1 | ||||
-rw-r--r-- | src/include/game.h | 3 | ||||
-rw-r--r-- | src/include/graphic.h | 6 | ||||
-rw-r--r-- | 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(;t<STATS_TICKCOUNT;t++) { wantWaitMean+=wantWait[t]; } + t=0; wantWaitMean/=(double) STATS_TICKCOUNT; + snprintf(logMsg, 128, "tick:%d\tlastServerTick:%d\tdrift_ms:%d\tFPS:%.1f\t wantWait:%.1f ms (%.1f %%)\n", tick, lastServerTick, drift_ms, fps, wantWaitMean, (double)wantWaitMean/TICK_DURATION_MS); logs(LOG_DEBUG, logMsg); } } @@ -235,7 +227,7 @@ void signals(int signum) { } } -int act(tick_t *tick, int loadProgress, TCPsocket sockClient, int *dirtRectsCount, SDL_Rect **dirtRects) { +int act(tick_t *tick, int loadProgress, TCPsocket sockClient, gameObjectsState_t *objStates) { int res; switch(getState()) { @@ -262,7 +254,7 @@ int act(tick_t *tick, int loadProgress, TCPsocket sockClient, int *dirtRectsCoun case eSingleGame: case eMultiGame: // Make game evolve from the current state to the next time chunk (ie. frame, or tick) - play((*tick)++, dirtRectsCount, dirtRects); + play((*tick)++, objStates); break; default: return 1; @@ -422,9 +414,7 @@ int loadLevelProc(void *a) { #define MAP_SCROLL_BOUND 32 #define MAP_SCROLL_SPEED 16 -//FIXME : tous les champs de gGraph utilisés dans cette méthode devraient être déplacés dans une structure autre -//void processLocalEvents(SDL_Rect *viewport, SDL_Rect *screen, SDL_Rect *terrain, int *debugFlags) { -void processLocalEvents(gameGraphics_t *gGraph) { +void processLocalEvents(SDL_Rect *terrain, SDL_Rect *viewport, gameObjectsState_t *objStates, localParams_t *params) { static int mouseActive=1, mouseX=100, mouseY=100; SDL_Event event; @@ -456,7 +446,7 @@ void processLocalEvents(gameGraphics_t *gGraph) { changeState(eEnd); break; case SDLK_d: - gGraph->debugFlags ^= 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; i<gGraph->dirtRectsCount; 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; i<objStates->objCount; 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; |