summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLudovic Pouzenc <ludovic@pouzenc.fr>2010-11-01 10:40:23 +0000
committerLudovic Pouzenc <ludovic@pouzenc.fr>2010-11-01 10:40:23 +0000
commit71120df4c9e3b0fe999c232b912fb1826dcc015e (patch)
treefafd024a4bc47822b53d888de704e166bd09bafb
parentab86f7c921b4fd18d718c77b7e917ba0d22e1294 (diff)
download2010-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-xcompil.sh16
-rw-r--r--src/CMakeLists.txt3
-rw-r--r--src/netlem.c165
-rw-r--r--src/netlem.h.in2
4 files changed, 137 insertions, 49 deletions
diff --git a/compil.sh b/compil.sh
index a5a2f4e..754be6a 100755
--- a/compil.sh
+++ b/compil.sh
@@ -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*/