diff options
author | Ludovic Pouzenc <ludovic@pouzenc.fr> | 2010-11-01 10:40:23 +0000 |
---|---|---|
committer | Ludovic Pouzenc <ludovic@pouzenc.fr> | 2010-11-01 10:40:23 +0000 |
commit | 71120df4c9e3b0fe999c232b912fb1826dcc015e (patch) | |
tree | fafd024a4bc47822b53d888de704e166bd09bafb | |
parent | ab86f7c921b4fd18d718c77b7e917ba0d22e1294 (diff) | |
download | 2010-netlemmings-71120df4c9e3b0fe999c232b912fb1826dcc015e.tar.gz 2010-netlemmings-71120df4c9e3b0fe999c232b912fb1826dcc015e.tar.bz2 2010-netlemmings-71120df4c9e3b0fe999c232b912fb1826dcc015e.zip |
Amélioration dans netlem.c : vraie machine à état, petites corrections dans la chaine de compilation
git-svn-id: file:///var/svn/2010-netlemmings/trunk@129 077b3477-7977-48bd-8428-443f22f7bfda
-rwxr-xr-x | compil.sh | 16 | ||||
-rw-r--r-- | src/CMakeLists.txt | 3 | ||||
-rw-r--r-- | src/netlem.c | 165 | ||||
-rw-r--r-- | src/netlem.h.in | 2 |
4 files changed, 137 insertions, 49 deletions
@@ -3,9 +3,15 @@ cd bin cmake ../src make; -gnome-terminal -t SERVEUR -e "bash -c './server_on_piou.sh ; sleep 15'"& -sleep 5; -gnome-terminal -t CLIENT1 -e "bash -c './netlem piou.prosoluce.fr; sleep 15'"& -sleep 1; -gnome-terminal -t CLIENT2 -e "bash -c './netlem piou.prosoluce.fr; sleep 15'"& +if [ $# -gt 0 ] +then case $1 in + test) + gnome-terminal -t SERVEUR -e "bash -c './server_on_piou.sh ; sleep 15'"& + sleep 5; + gnome-terminal -t CLIENT1 -e "bash -c './netlem piou.prosoluce.fr; sleep 15'"& + sleep 1; + gnome-terminal -t CLIENT2 -e "bash -c './netlem piou.prosoluce.fr; sleep 15'"& + ;; + esac +fi diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3082691..a1741f8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -6,6 +6,7 @@ set (NetLemmings_VERSION_MAJOR 0) set (NetLemmings_VERSION_MINOR 1) set(SRC_COMMON events.c game.c utils.c) +set(INCLUDE_DIRECTORIES "${PROJECT_SOURCE_DIR}/include/") # Check if all necessary libs are here find_package(SDL REQUIRED) @@ -24,7 +25,7 @@ configure_file ( # add the binary tree to the search path for include files # so that we will find netlem.h and netlem_ds.h -include_directories("${PROJECT_BINARY_DIR}") +include_directories("${INCLUDE_DIRECTORIES}" "${PROJECT_BINARY_DIR}") add_definitions(-Wall -Wextra -pedantic -Werror -std=c99) add_executable(netlem WIN32 netlem.c ${SRC_COMMON}) diff --git a/src/netlem.c b/src/netlem.c index 24e95d8..39b7913 100644 --- a/src/netlem.c +++ b/src/netlem.c @@ -1,5 +1,7 @@ #include <stdlib.h> #include <stdio.h> +#include <signal.h> + #include "SDL/SDL.h" #include "SDL/SDL_net.h" #include "SDL/SDL_thread.h" @@ -16,30 +18,59 @@ typedef struct { SDL_Rect screen; } gameConfig_t; -// Fin trucs brouillon -// Global variables shared between threads -int tick=0; -SDL_sem *semGameStart; +typedef struct { + SDL_Surface *screen, *pTerrain, *pSpr_Lem, *pStencil, *pStencilFixe; + +} gameGraphics_t; + +typedef enum { + e_null, // Pseudo_state for getOrChangeState : do not change state, just return current state + e_launching, // Initial state, during system objects initialization + e_splash, // State for displaying Game Logo + e_menu_main, // State for main menu (next lines are sub-menus) + e_menu_options, // State for general options (screen resolution, music...) + e_menu_single, // State for single player options (level selection...) + e_menu_network_server, // State for network game server selection + e_menu_network_options, // State for network game options selection (level, players, speed...) + e_single_brief, // State for single player level briefing (number of Lemmings to save...) + e_single_game, // State for single player game (user is actually playing) + e_single_report, // State for single player game report (number of saved Lemmings, access code...) + e_multi_wait_start, // State for multi player level briefing and network synchronization + e_multi_game, // + e_multi_report, // + e_credits, // + e_end // State reached when this program is exiting +} state_t; +// Fin trucs brouillon -struct _networkReadProc_args { int *end; int *drift_ms; client_t *client; }; +struct _networkReadProc_args { client_t *client; int *tick; int *drift_ms; SDL_sem *semGameStart; }; // Thread entry points int networkReadProc(void *a); // Client-specific functions +void signals(int signum); +state_t getOrChangeState(state_t s, TCPsocket sockClient); +int init(gameConfig_t *conf, gameGraphics_t *graph); void loadGameConfig(gameConfig_t *conf); -int init(); void processLocalEvents(); int updateGraphics(); + + int main(int argc, char **argv) { - const event_t evReady = {0,0,0,eReady,0,0,NULL,NULL}; - int end=0, drift_ms=0, timeBefore_ms, delay_ms, result, status; + + int drift_ms=0, tick=0, timeBefore_ms, delay_ms, result; + client_t client; + gameConfig_t conf; + gameGraphics_t graph; + struct _networkReadProc_args args; char logMsg[128]; + SDL_sem *semGameStart; IPaddress ip; if(argc!=2) { @@ -66,8 +97,10 @@ int main(int argc, char **argv) { return 3; } + loadGameConfig(&conf); + // Libraries initialization - result=init(); + result=init(&conf, &graph); if(result!=0) { logs(LOG_ERROR,"main(), init()"); return 3; @@ -77,21 +110,27 @@ int main(int argc, char **argv) { semGameStart=SDL_CreateSemaphore(0); // Network reader thread to process remote events and time sync - args.end=&end; - args.drift_ms=&drift_ms; args.client=&client; + args.tick=&tick; + args.drift_ms=&drift_ms; + args.semGameStart=semGameStart; SDL_Thread *networkReadThread = SDL_CreateThread(networkReadProc, &args); if(!networkReadThread) { logs2(LOG_ERROR,"main(), SDL_CreateThread()", SDL_GetError()); return 4; } - // Say to the server that we are ready to start the game and wait game start - result=sendEvent(client.sockClient, &evReady); - if (result!=0) return 6; + + //TODO : faire les menus et ne pas forcer ça ici + if ( getOrChangeState(e_multi_wait_start, client.sockClient) == e_null ) { + return 6; + } + logs(LOG_INFO, "Waiting game start"); result=SDL_SemWait(semGameStart); + //FIXME Utiliser un SemWait avec un timeout de moins d'une seconde dans un while pour inclure la gestion des évènements (SQL_QUIT, touches clavier...) + //Enfait le besoin est plus compliqué : il faut toujours être dans la boucle events/action/refresh, mais les actions dépendent d'une machine à état (menus, attente jeu...) if (result!=0) { logs2(LOG_ERROR, "main(), SDL_SemWait()", SDL_GetError()); return 7; @@ -99,15 +138,22 @@ int main(int argc, char **argv) { logs(LOG_INFO, "Game started !"); // Main game loop - while(!end) { + while(getOrChangeState(e_null,NULL)!=e_end) { timeBefore_ms = SDL_GetTicks(); // Process local player keyboard and mouse events // (note: remote events are processed by network read thread) processLocalEvents(); - // Make game evolve from the current state to the next time chunk (ie. frame, or tick) - play(tick++); + switch(getOrChangeState(e_null,NULL)) { + case e_single_game: + case e_multi_game: + // Make game evolve from the current state to the next time chunk (ie. frame, or tick) + play(tick++); + break; + default: + break; + } // Display that new game state to the local user updateGraphics(); @@ -119,23 +165,57 @@ int main(int argc, char **argv) { // Close communcation with the server, stop threads, close logs and go out SDLNet_TCP_Close(client.sockClient); - SDL_WaitThread(networkReadThread, &status); - sprintf(logMsg, "TimeSync thread terminated with code %i", status); + SDL_WaitThread(networkReadThread, &result); + sprintf(logMsg, "TimeSync thread terminated with code %i", result); logs(LOG_DEBUG, logMsg); closeLog(); return 0; } -int init() { +state_t getOrChangeState(state_t s, TCPsocket sockClient) { + const event_t evReady = {0,0,0,eReady,0,0,NULL,NULL}; + static state_t state=e_launching; int result; - gameConfig_t conf; - //TODO ranger ça ! - SDL_Surface *screen, *pTerrain, *pSpr_Lem, *pStencil, *pStencilFixe; + switch(s) { + case e_multi_wait_start: + //TODO : check current state before switching + // Say to the server that we are ready to start the game and wait game start + result=sendEvent(sockClient, &evReady); + if (result!=0) return e_null; + + state=s; + case e_end: + state=s; + case e_null: + break; + default: + return e_null; + } + + return state; +} + +void signals(int signum) { + static int force=0; + char buf[128]; + sprintf(buf, "Caught signal %i", signum); + logs(LOG_WARN, buf); + + if(!force) { + getOrChangeState(e_end,NULL); + force=1; + logs(LOG_WARN, "Trying to stop smoothly..."); + } else { + logs(LOG_WARN, "Emergency stop"); + exit(1); + } +} + +int init(gameConfig_t *conf, gameGraphics_t *graph) { + int result; - loadGameConfig(&conf); - //TODO : Avoir un struct de paramètre de config (taille écran) et un struct avec tous les éléments SDL manipulés dans le jeu //Initialisation des sous-systèmes de SDL result = SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO ); @@ -144,10 +224,11 @@ int init() { return 1; } atexit(SDL_Quit); + signal(2,signals); //Mise en place de l'écran - screen = SDL_SetVideoMode(conf.screen.w, conf.screen.h, SCREEN_BPP, SDL_HWSURFACE | SDL_DOUBLEBUF ); - if( screen == NULL ) { + graph->screen = SDL_SetVideoMode(conf->screen.w, conf->screen.h, SCREEN_BPP, SDL_HWSURFACE | SDL_DOUBLEBUF ); + if( graph->screen == NULL ) { logs2(LOG_ERROR, "init(), SDL_SetVideoMode()", SDL_GetError()); return 2; } @@ -158,26 +239,26 @@ int init() { //Désactiver le pointeur de la souris SDL_ShowCursor(0); // Allocation et initialisation des différents calques d'affichage et de collision - pTerrain = SDL_CreateRGBSurface(SDL_HWSURFACE, LEVEL_WIDTH, LEVEL_HEIGHT, SCREEN_BPP,0,0,0,0); - if( pTerrain == NULL ) { + graph->pTerrain = SDL_CreateRGBSurface(SDL_HWSURFACE, LEVEL_WIDTH, LEVEL_HEIGHT, SCREEN_BPP,0,0,0,0); + if( graph->pTerrain == NULL ) { logs2(LOG_ERROR, "init(), SDL_CreateRGBSurface()", SDL_GetError()); return 3; } - pSpr_Lem = SDL_CreateRGBSurface(SDL_HWSURFACE, LEVEL_WIDTH, LEVEL_HEIGHT,SCREEN_BPP,0,0,0,0); - if( pSpr_Lem == NULL ) { + graph->pSpr_Lem = SDL_CreateRGBSurface(SDL_HWSURFACE, LEVEL_WIDTH, LEVEL_HEIGHT,SCREEN_BPP,0,0,0,0); + if( graph->pSpr_Lem == NULL ) { logs2(LOG_ERROR, "init(), SDL_CreateRGBSurface()", SDL_GetError()); return 3; } - pStencil = SDL_CreateRGBSurface(SDL_SWSURFACE, LEVEL_WIDTH, LEVEL_HEIGHT, SCREEN_BPP,0,0,0,0); - if( pStencil == NULL ) { + graph->pStencil = SDL_CreateRGBSurface(SDL_SWSURFACE, LEVEL_WIDTH, LEVEL_HEIGHT, SCREEN_BPP,0,0,0,0); + if( graph->pStencil == NULL ) { logs2(LOG_ERROR, "init(), SDL_CreateRGBSurface()", SDL_GetError()); return 3; } - pStencilFixe = SDL_CreateRGBSurface(SDL_SWSURFACE, LEVEL_WIDTH, LEVEL_HEIGHT, SCREEN_BPP,0,0,0,0); - if( pStencil == NULL ) { + graph->pStencilFixe = SDL_CreateRGBSurface(SDL_SWSURFACE, LEVEL_WIDTH, LEVEL_HEIGHT, SCREEN_BPP,0,0,0,0); + if( graph->pStencilFixe == NULL ) { logs2(LOG_ERROR, "init(), SDL_CreateRGBSurface()", SDL_GetError()); return 3; } @@ -188,34 +269,34 @@ int init() { void loadGameConfig(gameConfig_t *conf) { conf->screen.w=640; conf->screen.h=480; - conf->screen.x=0; conf->screen.y=0; + //TODO : charger vraiment le fichier de conf ^^ } int networkReadProc(void *a) { int result; event_t e; char logMsg[128]; - + struct _networkReadProc_args *args = (struct _networkReadProc_args *)a; - while(! *(args->end) ) { + while( getOrChangeState(e_null,NULL) != e_end ) { // logs(LOG_DEBUG, "Waiting event"); result=receiveEvent(args->client,&e); if (result != 0) { logs(LOG_WARN, "networkReadProc(), receiveEvents() error"); - *(args->end)=1; + getOrChangeState(e_end,NULL); continue; //TODO : je doute que ça skipe vriament la syncrho du temps :s } // logs(LOG_DEBUG, "Got event"); - *(args->drift_ms)=( tick - e.serverTick ); - sprintf(logMsg, "serverTick==%i, tick==%i, drift_ms==%i\n", e.serverTick, tick, *(args->drift_ms)); + *(args->drift_ms)=( *(args->tick) - e.serverTick ); + sprintf(logMsg, "serverTick==%i, tick==%i, drift_ms==%i\n", e.serverTick, *(args->tick), *(args->drift_ms)); logs(LOG_DEBUG, logMsg); - result=SDL_SemPost(semGameStart); + result=SDL_SemPost(args->semGameStart); if (result!=0) { logs2(LOG_ERROR, "main(), SDL_SemPost()", SDL_GetError()); return 1; diff --git a/src/netlem.h.in b/src/netlem.h.in index a479ed2..d7729aa 100644 --- a/src/netlem.h.in +++ b/src/netlem.h.in @@ -6,7 +6,7 @@ #define NetLemmings_VERSION_MINOR @NetLemmings_VERSION_MINOR@ #define SCREEN_BPP 24 -#define WIN_CAPTION "NetLemmings v.@NetLemmings_VERSION_MAJOR@.@NetLemmings_VERSION_MINOR@" +#define WIN_CAPTION "NetLemmings v@NetLemmings_VERSION_MAJOR@.@NetLemmings_VERSION_MINOR@" #endif /*NETLEM_H*/ |