X-Git-Url: http://royale.zerezo.com/git/?p=zeRace;a=blobdiff_plain;f=zeRace.c;h=9277dd3b74bf5935dd74b00a43745bec15f3afbf;hp=7bc2e338a656cbe4f7bee42ee791bc9f5ad72129;hb=HEAD;hpb=f3b6b880f4b72504090898ab825f38f091a68168 diff --git a/zeRace.c b/zeRace.c index 7bc2e33..9277dd3 100644 --- a/zeRace.c +++ b/zeRace.c @@ -1,223 +1,358 @@ -#include +/* + * zeRace 0.7, a funny retro racing game + * http://royale.zerezo.com/zerace/ + * + * Copyright (C) 2004 Antoine Jacquet + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include #include +#include +#include #include #include #include #include -#include +#include #include "sdl.h" +#include "car.h" +#include "tracklist.h" +#include "network.h" +#include -#define MAXLINELENGTH 1000 -#define VERSION "0.1" +/* configuration constants */ +#define COEFF 1 +#define DELAY 7 #define WIDTH 1024 #define HEIGHT 768 +#define MAXRECORDKEYS 9999 +#define NB_CARS 16 + +/* some usefull colors */ +#define C_BLACK SDL_MapRGB(screen->format,0,0,0) +#define C_WHITE SDL_MapRGB(screen->format,255,255,255) +#define C_RED SDL_MapRGB(screen->format,255,0,0) +#define C_ORANGE SDL_MapRGB(screen->format,255,200,0) +#define C_YELLOW SDL_MapRGB(screen->format,255,255,100) +#define T_BLACK SDL_MapRGB(cir->format,0,0,0) -/* global variables */ +/* tracklist */ +struct _tracklist *tracklist; -struct track +/* user setup */ +struct _config { - char *name; - char *title; - char *author; - char *version; - char *full; - char *function; - int x,y,a; - struct track *prev; - struct track *next; -} *tracklist=NULL; - -int fullscreen=0; -int sound=0; -char pseudo[MAXLINELENGTH]="anonymous"; -char url[MAXLINELENGTH]=""; + char pseudo[MAXLINELENGTH]; + char url[MAXLINELENGTH]; + int fullscreen; + int sound; + int tire; + SDLKey up; + SDLKey down; + SDLKey left; + SDLKey right; + int color; + SDLKey boss; + int bynight; + int internet; +} config = {"anonymous","",0,0,1,SDLK_UP,SDLK_DOWN,SDLK_LEFT,SDLK_RIGHT,6,SDLK_b,0,1}; + +/* full script for a lap */ +struct _record +{ + float x,y,angle,speed; + char keys[MAXRECORDKEYS]; + int time; +}; + +/* display and all directions for the car */ SDL_Surface *screen; -SDL_Surface *cars[256]; +SDL_Surface *cars[NB_CARS][256]; + +/* network stuff */ +UDPsocket udpsock=NULL; +UDPpacket *packet; +int network_speed=1; + + +/* read the user configuration file */ +void zeRace_read_config() +{ + FILE *fic; + if ((fic=fopen("zeRace.cfg","rb"))==NULL) + { + fprintf(stderr,"can't open config file \"zeRace.cfg\"\n"); + return; + } + fread(&config,sizeof(struct _config),1,fic); + fclose(fic); +} + + +/* save the user configuration file */ +void zeRace_save_config() +{ + FILE *fic; + if ((fic=fopen("zeRace.cfg","wb"))==NULL) + { + fprintf(stderr,"can't create config file \"zeRace.cfg\"\n"); + return; + } + fwrite(&config,sizeof(struct _config),1,fic); + fclose(fic); +} + +/* exit the game and clean */ void zeRace_exit() { printf("quit\n"); - if (sound) Mix_CloseAudio(); + if (config.sound) Mix_CloseAudio(); SDLNet_Quit(); SDL_Quit(); - /* - save_config(); - zeRace_send_ghosts(); - close_sdl(); - */ + zeRace_save_config(); exit(0); } -void zeRace_read_config() +/* check for a newer version online to warn the user */ +void zeRace_check_version() +{ + IPaddress ip; + TCPsocket tcpsock; + char *request= + "GET /zerace/version.php HTTP/1.0\n" + "Host: royale.zerezo.com\n" + "User-Agent: zeRace " VERSION "\n" + "\n"; + char response[1024],*tmp,*version; + int len,result; + + if (!config.internet) return; + + printf("checking version... "); + fflush(stdout); + + if (SDLNet_ResolveHost(&ip,"royale.zerezo.com",80)==-1) + { + fprintf(stderr,"SDLNet_ResolveHost: %s\n",SDLNet_GetError()); + return; + } + + tcpsock=SDLNet_TCP_Open(&ip); + if (!tcpsock) + { + fprintf(stderr,"SDLNet_TCP_Open: %s\n",SDLNet_GetError()); + return; + } + + len=strlen(request); + result=SDLNet_TCP_Send(tcpsock,request,len); + if (resultd_name)>4) - { - shortname=(char *)realloc(shortname,strlen(dp->d_name)-3); - strncpy(shortname,dp->d_name,strlen(dp->d_name)-4); - shortname[strlen(dp->d_name)-4]='\0'; - for (i=0;i<5;i++) ext[i]=tolower(dp->d_name[strlen(dp->d_name)-4+i]); - if (strcmp(".txt",ext)==0) - { - tmp=(struct track *)malloc(sizeof(struct track)); - if (first==NULL) first=tmp; - tmp->name=(char *)malloc(strlen(shortname)+1); - strcpy(tmp->name,shortname); - tmp->title=""; - tmp->author=""; - tmp->version=""; - tmp->x=10; - tmp->y=10; - tmp->a=0; - configlines=0; - sprintf(line,"tracks/%s.txt",shortname); - if ((fic=fopen(line,"rt"))==NULL) + struct stat buf; + + if (!config.internet) return; + + if (stat(file,&buf)<0) + { + printf("downloading file \"%s\" : ",file); + fflush(stdout); + + if (SDLNet_ResolveHost(&ip,"royale.zerezo.com",80)==-1) + { + fprintf(stderr,"SDLNet_ResolveHost: %s\n",SDLNet_GetError()); + return; + } + + tcpsock=SDLNet_TCP_Open(&ip); + if (!tcpsock) + { + fprintf(stderr,"SDLNet_TCP_Open: %s\n",SDLNet_GetError()); + return; + } + + sprintf(request, + "GET /zerace/%s HTTP/1.0\n" + "Host: royale.zerezo.com\n" + "User-Agent: zeRace " VERSION "\n" + "\n",file); + len=strlen(request); + result=SDLNet_TCP_Send(tcpsock,request,len); + if (resulttitle=(char *)malloc(strlen(line+i+3)+1); - strcpy(tmp->title,line+i+3); - } - else - - if (strcmp("author",line)==0) - { - tmp->author=(char *)malloc(strlen(line+i+3)+1); - strcpy(tmp->author,line+i+3); - } - else - - if (strcmp("x",line)==0) - tmp->x=atoi(line+i+3); - else - - if (strcmp("y",line)==0) - tmp->y=atoi(line+i+3); - else - - if (strcmp("a",line)==0) - tmp->a=atoi(line+i+3); - else - - if (strcmp("version",line)==0) - { - tmp->version=(char *)malloc(strlen(line+i+3)+1); - strcpy(tmp->version,line+i+3); - } - - else { fprintf(stderr,"error in track file \"%s\" : \"%s\" is an unknown keyword (line %d)\n",shortname,line,configlines); exit(1); } - } + fprintf(stderr,"CreateRGBSurface failed: %s\n",SDL_GetError()); + zeRace_exit(); + }; + tcos=cos(2*M_PI*j/256); + tsin=sin(2*M_PI*j/256); + for (x=0;xw;x++) for (y=0;yh;y++) + { + int x2,y2; + x2=(x-cars[i][j]->w/2.0)*tcos+(y-cars[i][j]->h/2.0)*tsin+car->w/2.0; + y2=(x-cars[i][j]->w/2.0)*tsin-(y-cars[i][j]->h/2.0)*tcos+car->h/2.0; + if (x2>0 && x2w && y2>0 && y2h) + putpixel(cars[i][j],x,y,getpixel(car,x2,y2)); } - fclose(fic); - tmp->full=(char *)malloc(strlen(line)+20); - sprintf(tmp->full,"tracks/%s.png",shortname); - tmp->function=(char *)malloc(strlen(line)+30); - sprintf(tmp->function,"tracks/%s_function.png",shortname); - tmp->prev=tracklist; - if (tmp->prev) tmp->prev->next=tmp; - tracklist=tmp; - } - } - if (!tmp) { fprintf(stderr,"no circuits found !\n"); zeRace_exit(); } - while (tmp->prev) tmp=tmp->prev; - tmp->prev=tracklist; - tracklist->next=tmp; + } + SDL_FreeSurface(car); + } } +/* initialize the game */ void zeRace_init() { - SDL_Surface *car; - int i,flags; + int flags; + struct _tracklist *loopcheck; + /* do a clean exit in case of emergency */ signal(SIGINT,zeRace_exit); signal(SIGTERM,zeRace_exit); - zeRace_read_config(); - //zeRace_check_version(); - zeRace_get_tracks(); - //zeRace_get_ghosts(); - - srand(time(NULL)); - + + /* initialize SDL */ if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO)<0) { fprintf(stderr,"could not initialize SDL : %s\n",SDL_GetError()); @@ -225,14 +360,47 @@ void zeRace_init() } atexit(SDL_Quit); - if(SDLNet_Init()==-1) + /* initialize SDLNet */ + if (SDLNet_Init()==-1) { fprintf(stderr,"could not initialize SDLNet : %s\n",SDLNet_GetError()); zeRace_exit(); } + /* read the user configuration file */ + zeRace_read_config(); + + /* check for a newer available version */ + zeRace_check_version(); + + /* update the list of tracks */ + zeRace_update_tracks(); + + /* get the list of local tracks */ + if (!zeRace_get_tracks(&tracklist)) zeRace_exit(); + + /* download missing files */ + loopcheck=tracklist; + do + { + zeRace_download_file(tracklist->full); + zeRace_download_file(tracklist->function); + tracklist=tracklist->next; + } while (tracklist!=loopcheck); + + srand(time(NULL)); + + packet=SDLNet_AllocPacket(1024); + if (!packet) + { + fprintf(stderr,"SDLNet_AllocPacket: %s\n",SDLNet_GetError()); + zeRace_exit(); + } + + SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY,SDL_DEFAULT_REPEAT_INTERVAL); + flags=SDL_HWSURFACE|SDL_ANYFORMAT; - if (fullscreen) flags|=SDL_FULLSCREEN; + if (config.fullscreen) flags|=SDL_FULLSCREEN; if ((screen=SDL_SetVideoMode(WIDTH,HEIGHT,32,flags))==NULL) { @@ -244,45 +412,25 @@ void zeRace_init() SDL_WM_SetCaption("zeRace " VERSION,"zeRace " VERSION); SDL_ShowCursor(SDL_DISABLE); - if (sound) if (Mix_OpenAudio(44100,MIX_DEFAULT_FORMAT,2,512)<0) + if (config.sound) if (Mix_OpenAudio(44100,MIX_DEFAULT_FORMAT,2,512)<0) { fprintf(stderr,"Mix_OpenAudio error\n"); zeRace_exit(); } - car=IMG_Load("sprites/car.png"); - for (i=0;i<256;i++) - { - float x,y; - float tcos,tsin; - cars[i]=SDL_CreateRGBSurface(SDL_SWSURFACE,car->h*2,car->h*2,32,0x000000ff,0x0000ff00,0x00ff0000,0xff000000); - if(cars[i]==NULL) - { - fprintf(stderr,"CreateRGBSurface failed: %s\n",SDL_GetError()); - exit(1); - } - tcos=cos(2*M_PI*i/256); - tsin=sin(2*M_PI*i/256); - for (x=0;xw;x++) for (y=0;yh;y++) - { - int x2,y2; - Uint32 col; - x2=(x-cars[i]->w/2.0)*tcos+(y-cars[i]->h/2.0)*tsin+car->w/2.0; - y2=(x-cars[i]->w/2.0)*tsin-(y-cars[i]->h/2.0)*tcos+car->h/2.0; - if (x2>0 && x2w && y2>0 && y2h) - putpixel(cars[i],x,y,getpixel(car,x2,y2)); - } - } + /* pre-calculate car sprites */ + zeRace_generate_cars(); } -void zeRace_send_time(float x,float y,float speed,float angle,int btime,char *bkeys) +/* send the best time for this race to the web server */ +void zeRace_send_time(struct _record *record) { IPaddress ip; TCPsocket tcpsock; char *temp; char *msg1= - "POST /zerace/time.php HTTP/1.1\n" + "POST /zerace/time.php HTTP/1.0\n" "Host: royale.zerezo.com\n" "User-Agent: zeRace " VERSION "\n" "Content-Type: application/x-www-form-urlencoded\n" @@ -299,80 +447,168 @@ void zeRace_send_time(float x,float y,float speed,float angle,int btime,char *bk char *msg9="&bkeys="; int len,result; + if (!config.internet) return; + + /* if the best time is small enought to save all keys, send it */ + if (record->time>=MAXRECORDKEYS) return; + printf("sending time... "); fflush(stdout); - if(SDLNet_ResolveHost(&ip,"royale.zerezo.com",80)==-1) + if (SDLNet_ResolveHost(&ip,"royale.zerezo.com",80)==-1) { fprintf(stderr,"SDLNet_ResolveHost: %s\n",SDLNet_GetError()); return; } tcpsock=SDLNet_TCP_Open(&ip); - if(!tcpsock) + if (!tcpsock) { fprintf(stderr,"SDLNet_TCP_Open: %s\n",SDLNet_GetError()); return; } - temp=(char *)malloc(strlen(msg1)+strlen(pseudo)+strlen(msg2)+strlen(url)+strlen(msg3)+strlen(tracklist->name)+strlen(msg4)+10+strlen(msg5)+10+strlen(msg6)+10+strlen(msg7)+10+strlen(msg8)+10+strlen(msg9)+strlen(bkeys)+100); - sprintf(temp,"%s%s%s%s%s%s%s%d%s%f%s%f%s%f%s%f%s%s\n",msg1,pseudo,msg2,url,msg3,tracklist->name,msg4,btime,msg5,x,msg6,y,msg7,speed,msg8,angle,msg9,bkeys); + temp=(char *)malloc(strlen(msg1)+strlen(config.pseudo)+strlen(msg2)+strlen(config.url)+strlen(msg3)+strlen(tracklist->name)+strlen(msg4)+10+strlen(msg5)+10+strlen(msg6)+10+strlen(msg7)+10+strlen(msg8)+10+strlen(msg9)+strlen(record->keys)+100); + sprintf(temp,"%s%s%s%s%s%s%s%d%s%f%s%f%s%f%s%f%s%s\n",msg1,config.pseudo,msg2,config.url,msg3,tracklist->name,msg4,record->time,msg5,record->x,msg6,record->y,msg7,record->speed,msg8,record->angle,msg9,record->keys); len=strlen(temp); result=SDLNet_TCP_Send(tcpsock,temp,len); - if(result100) return; + temp[0]=q/10+'0'; + temp[1]=q%10+'0'; + temp[2]='"'; + temp[3]=r/100+'0'; + temp[4]=r%100/10+'0'; + temp[5]=r%10+'0'; + temp[6]='\0'; + print(screen,x,y,temp); +} + + +/* car lights */ +void lights(int x,int y,int r,Uint32 pixel) +{ + putpixel(screen,x,y,pixel); + if (r>1) + { + putpixel(screen,x-1,y,pixel); + putpixel(screen,x+1,y,pixel); + putpixel(screen,x,y-1,pixel); + putpixel(screen,x,y+1,pixel); + } + if (r>2) + { + putpixel(screen,x-2,y,pixel); + putpixel(screen,x+2,y,pixel); + putpixel(screen,x,y-2,pixel); + putpixel(screen,x,y+2,pixel); + putpixel(screen,x-1,y-1,pixel); + putpixel(screen,x-1,y+1,pixel); + putpixel(screen,x+1,y-1,pixel); + putpixel(screen,x+1,y+1,pixel); + } +} + + +/* launch a new race */ +void zeRace_launch(int alltime,int go) { - SDL_Surface *cir,*fun; - SDL_Rect pos,size; + SDL_Surface *cir,*fun,*hilight; + SDL_Rect pos; SDL_Event event; - int ku=0,kd=0,kl=0,kr=0; - int i,time=0,lastcheck=0,btime=10000; - float ox,oy; - float x,y,angle,speed; - float sx,sy,sangle,sspeed; - float bx,by,bangle,bspeed; - int c,r,v,b; - int temp; - char keys[10000]; - char bkeys[10000]; - char text[10]; - Mix_Music *light,*engine,*crash,*slide; - int lastsound_time=-999,alltime=0,lastsound=0; + int ku=0,kd=0,kl=0,kr=0,i; + struct _car car; + struct _record current,best; + Mix_Music *light,*engine,*crash,*slide; + int lastsound_time=-999,lastsound=0; + int delay=DELAY; + int lastack=alltime; + struct _record net; + struct _car oldnetpos[MAX_CLIENTS],newnetpos[MAX_CLIENTS]; + int l=80,o=15; + + /* free memory */ + void free_mem() + { + SDL_FreeSurface(cir); + SDL_FreeSurface(fun); + if (config.sound) + { + Mix_FreeMusic(light); + Mix_FreeMusic(engine); + Mix_FreeMusic(crash); + Mix_FreeMusic(slide); + } + return; + } cir=IMG_Load(tracklist->full); + /* dark the track if it is night */ + if (config.bynight) + { + for (pos.x=0;pos.xw;pos.x++) + for (pos.y=0;pos.yh;pos.y++) + { + Uint32 c; + Uint8 r,g,b; + c=getpixel(cir,pos.x,pos.y); + SDL_GetRGB(c,cir->format,&r,&g,&b); + r*=0.3; + g*=0.3; + b*=0.3; + putpixel(cir,pos.x,pos.y,SDL_MapRGB(cir->format,r,g,b)); + } + } fun=IMG_Load(tracklist->function); + hilight=IMG_Load("sprites/light.png"); - sspeed=speed=0; - sangle=angle=(tracklist->a*2*M_PI/360); - sx=x=tracklist->x; - sy=y=tracklist->y; - lastcheck=0; - time=0; + current.speed=car.speed=0; + current.angle=car.angle=tracklist->a*2*M_PI/360; + current.x=car.ox=car.x=tracklist->x; + current.y=car.oy=car.y=tracklist->y; + car.lastcheck=0; + car.lapflag=0; + car.w=cars[0][0]->w; + car.h=cars[0][0]->h; + current.time=0; + best.time=MAXRECORDKEYS; + net.time=0; + memset(oldnetpos,0,MAX_CLIENTS*sizeof(struct _car)); + memset(newnetpos,0,MAX_CLIENTS*sizeof(struct _car)); - if (sound) if (!(light=Mix_LoadMUS("sounds/light.wav")) || !(engine=Mix_LoadMUS("sounds/engine.wav")) || !(crash=Mix_LoadMUS("sounds/crash.wav")) || !(slide=Mix_LoadMUS("sounds/slide.wav"))) + if (config.sound) if (!(light=Mix_LoadMUS("sounds/light.wav")) || !(engine=Mix_LoadMUS("sounds/engine.wav")) || !(crash=Mix_LoadMUS("sounds/crash.wav")) || !(slide=Mix_LoadMUS("sounds/slide.wav"))) { fprintf(stderr,"Mix_LoadMUS error\n"); zeRace_exit(); } + /* startup countdown */ for (i=4;i>=-1;i--) { char startup[15]="sprites/?.png"; SDL_Surface *temp; startup[8]='0'+i; - pos.x=x; - pos.y=y; + pos.x=car.x-car.w/2; + pos.y=car.y-car.h/2; SDL_BlitSurface(cir,NULL,screen,NULL); - SDL_BlitSurface(cars[(unsigned char)(256*angle/2.0/M_PI)%256],NULL,screen,&pos); + SDL_BlitSurface(cars[config.color][(unsigned char)(256*car.angle/2.0/M_PI)%256],NULL,screen,&pos); if (i!=4 && i!=-1) { temp=IMG_Load(startup); @@ -381,183 +617,435 @@ void zeRace_launch() SDL_BlitSurface(temp,NULL,screen,&pos); SDL_FreeSurface(temp); } - if (sound) if (i!=4) Mix_PlayMusic(light,1); + if (config.sound) if (i!=4) Mix_PlayMusic(light,1); SDL_Flip(screen); + if (!go) break; if (i!=-1) SDL_Delay(1000); } + /* main loop */ for (;;) - { - size.w=cars[0]->w; - size.h=cars[0]->h; - pos.x=x; - pos.y=y; + { + /* look for user interaction */ + while (SDL_PollEvent(&event)) + { + switch (event.type) + { + case SDL_QUIT: + zeRace_exit(); + break; + case SDL_KEYDOWN: + switch (event.key.keysym.sym) + { + case SDLK_ESCAPE: + if (udpsock) + { + print(screen,WIDTH/2-strlen("Disconnecting !")*5,HEIGHT/2-10,"Disconnecting !"); + strcpy(packet->data,"disconnect"); + packet->len=strlen(packet->data)+1; + SDLNet_UDP_Send(udpsock,-1,packet); + SDL_Flip(screen); + } + zeRace_send_time(&best); + free_mem(); + return; + default: + i=event.key.keysym.sym; + if (i==config.up) ku=1; + if (i==config.down) kd=1; + if (i==config.left) kl=1; + if (i==config.right) kr=1; + if (i==config.boss) + { + /* display the boss screen */ + SDL_Surface *boss; + boss=IMG_Load("sprites/boss.png"); + SDL_BlitSurface(boss,NULL,screen,NULL); + SDL_FreeSurface(boss); + SDL_Flip(screen); + /* and wait until the user press another key */ + for (;;) if (SDL_PollEvent(&event)) { if (event.type==SDL_KEYDOWN) break; } else SDL_Delay(10); + SDL_BlitSurface(cir,NULL,screen,NULL); + SDL_Flip(screen); + } + break; + } + break; + case SDL_KEYUP: + i=event.key.keysym.sym; + if (i==config.up) ku=0; + if (i==config.down) kd=0; + if (i==config.left) kl=0; + if (i==config.right) kr=0; + break; + } + } + + /* save pressed keys to validate best time */ + if (current.timedata,"positions")==0) + { + int servertime,clienttime,nb; + servertime=SDLNet_Read32(packet->data+strlen("positions")+1); + clienttime=SDLNet_Read32(packet->data+strlen("positions")+1+4); + nb=SDLNet_Read16(packet->data+strlen("positions")+1+4+4); + if (clienttime>lastack) + { + memcpy(net.keys,net.keys+clienttime-lastack,net.time+1); + net.time-=clienttime-lastack; + if (clienttime>servertime+5) delay+=DELAY; + if (clienttimedata+strlen("positions")+1+4+4+2+i*14); + newnetpos[i].y=SDLNet_Read16(packet->data+strlen("positions")+1+4+4+2+i*14+2); + newnetpos[i].angle=(float)SDLNet_Read16(packet->data+strlen("positions")+1+4+4+2+i*14+2+2)/1000; + newnetpos[i].color=SDLNet_Read16(packet->data+strlen("positions")+1+4+4+2+i*14+2+2+2); + newnetpos[i].lights_brake=SDLNet_Read16(packet->data+strlen("positions")+1+4+4+2+i*14+2+2+2+2); + newnetpos[i].lights_backwards=SDLNet_Read16(packet->data+strlen("positions")+1+4+4+2+i*14+2+2+2+2+2); + newnetpos[i].lights_warning=SDLNet_Read16(packet->data+strlen("positions")+1+4+4+2+i*14+2+2+2+2+2+2); + } + lastack=clienttime; + } + } + else if (strcmp(packet->data,"collision")==0) + { + net.time=-1; + net.keys[0]='\0'; + lastack=SDLNet_Read32(packet->data+strlen("collision")+1); + car.x=(float)SDLNet_Read32(packet->data+strlen("collision")+1+4)/65536-100; + car.y=(float)SDLNet_Read32(packet->data+strlen("collision")+1+4+4)/65536-100; + car.speed=(float)SDLNet_Read32(packet->data+strlen("collision")+1+4+4+4)/65536-100; + car.angle=(float)SDLNet_Read32(packet->data+strlen("collision")+1+4+4+4+4)/65536-100; + } + else /* end of this network race */ + { + zeRace_send_time(&best); + free_mem(); + return; + } + if (strlen(net.keys)!=0) + { + tmp=packet->data; + strcpy(tmp,"keys"); + tmp+=strlen(tmp)+1; + SDLNet_Write32(lastack,tmp); + tmp+=4; + SDLNet_Write32(car.x,tmp); + tmp+=4; + SDLNet_Write32(car.y,tmp); + tmp+=4; + strcpy(tmp,net.keys); + tmp+=strlen(tmp)+1; + packet->len=(void *)tmp-(void *)packet->data+10; + if (net.time%network_speed==0) if (!SDLNet_UDP_Send(udpsock,-1,packet)) + { + fprintf(stderr,"SDLNet_UDP_Send: %s\n",SDLNet_GetError()); + exit(2); + }; + } + } + + /* clear the old network position */ + if (udpsock) for (i=0;iscreen->w-cars[0]->w || y<0 || y>screen->h-cars[0]->h) + /* if the car is braking, display red lights */ + if (car.lights_brake) { - x=ox; - y=oy; - speed=0; + lights(car.x+cos(car.angle)*car.w/3-sin(car.angle)*4,car.y+sin(car.angle)*car.h/3+cos(car.angle)*4,3,C_RED); + lights(car.x+cos(car.angle)*car.w/3+sin(car.angle)*4,car.y+sin(car.angle)*car.h/3-cos(car.angle)*4,3,C_RED); } - pos.x=x; - pos.y=y; - i=(unsigned char)(256*angle/2.0/M_PI)%256; - SDL_BlitSurface(cars[i],NULL,screen,&pos); - SDL_UpdateRect(screen,ox,oy,cars[i]->w,cars[i]->h); - SDL_UpdateRect(screen,x,y,cars[i]->w,cars[i]->h); + /* if the car is going backwards, display white lights */ + if (car.lights_backwards) + { + lights(car.x+cos(car.angle)*car.w/3-sin(car.angle)*4,car.y+sin(car.angle)*car.h/3+cos(car.angle)*4,3,C_WHITE); + lights(car.x+cos(car.angle)*car.w/3+sin(car.angle)*4,car.y+sin(car.angle)*car.h/3-cos(car.angle)*4,3,C_WHITE); + } - if (kl) angle-=0.01; - if (kr) angle+=0.01; - if (ku) speed+=0.01*2; - if (kd) speed-=0.01; - + /* if the car is stopped, then warning */ + if (car.lights_warning && alltime/75%2) + { + lights(car.x-cos(car.angle)*car.w/3-sin(car.angle)*5,car.y-sin(car.angle)*car.h/3+cos(car.angle)*5,2,C_ORANGE); + lights(car.x-cos(car.angle)*car.w/3+sin(car.angle)*5,car.y-sin(car.angle)*car.h/3-cos(car.angle)*5,2,C_ORANGE); + lights(car.x+cos(car.angle)*car.w/3-sin(car.angle)*5,car.y+sin(car.angle)*car.h/3+cos(car.angle)*5,2,C_ORANGE); + lights(car.x+cos(car.angle)*car.w/3+sin(car.angle)*5,car.y+sin(car.angle)*car.h/3-cos(car.angle)*5,2,C_ORANGE); + } + + /* display the lights */ + if (config.bynight) + { + lights(car.x+cos(car.angle)*car.w/3-sin(car.angle)*3,car.y+sin(car.angle)*car.h/3+cos(car.angle)*4,2,C_RED); + lights(car.x+cos(car.angle)*car.w/3+sin(car.angle)*3,car.y+sin(car.angle)*car.h/3-cos(car.angle)*4,2,C_RED); + lights(car.x-cos(car.angle)*car.w/3-sin(car.angle)*4,car.y-sin(car.angle)*car.h/3+cos(car.angle)*4,3,C_YELLOW); + lights(car.x-cos(car.angle)*car.w/3+sin(car.angle)*4,car.y-sin(car.angle)*car.h/3-cos(car.angle)*4,3,C_YELLOW); + pos.x=car.x-cos(car.angle)*l-sin(car.angle)*o; + pos.y=car.y-sin(car.angle)*l+cos(car.angle)*o; + pos.x-=50; + pos.y-=50; + pos.w=100; + pos.h=100; + SDL_BlitSurface(hilight,NULL,screen,&pos); + pos.x=car.x-cos(car.angle)*l+sin(car.angle)*o; + pos.y=car.y-sin(car.angle)*l-cos(car.angle)*o; + pos.x-=50; + pos.y-=50; + pos.w=100; + pos.h=100; + SDL_BlitSurface(hilight,NULL,screen,&pos); + } + + /* update display */ + if (udpsock) + { + for (i=0;iscreen->w) pos.w=screen->w-pos.x; + if (pos.y+pos.h>screen->h) pos.h=screen->h-pos.y; + SDL_UpdateRect(screen,pos.x,pos.y,pos.w,pos.h); + pos.x=car.x-cos(car.angle)*l+sin(car.angle)*15; + pos.y=car.y-sin(car.angle)*l-cos(car.angle)*15; + pos.x-=60; + pos.y-=60; + pos.w=120; + pos.h=120; + if (pos.x<0) pos.x=0; + if (pos.y<0) pos.y=0; + if (pos.x+pos.w>screen->w) pos.w=screen->w-pos.x; + if (pos.y+pos.h>screen->h) pos.h=screen->h-pos.y; + SDL_UpdateRect(screen,pos.x,pos.y,pos.w,pos.h); + } + + memcpy(oldnetpos,newnetpos,MAX_CLIENTS*sizeof(struct _car)); + + /* play engine sound if no sound is currently playing */ if (lastsound_time+1000.5 || speed>2.0 && !ku) + /* if the car is fast or braking, it slides */ + if ((kd && car.speed>0.5) || (car.speed>2.0 && !ku)) { - + /* if the only sound is the engine, play the slide sound */ if (lastsound_time+100w/2+cos(angle)*cars[i]->w/3-sin(angle)*2,y+cars[i]->h/2+sin(angle)*cars[i]->h/3+cos(angle)*2,0); - putpixel(cir,x+cars[i]->w/2+cos(angle)*cars[i]->w/3+sin(angle)*5,y+cars[i]->h/2+sin(angle)*cars[i]->h/3-cos(angle)*5,0); - if (kd) + /* display tires slide */ + if (config.tire) { - putpixel(cir,x+cars[i]->w/2+cos(angle)*cars[i]->w/3-sin(angle)*3,y+cars[i]->h/2+sin(angle)*cars[i]->h/3+cos(angle)*3,0); - putpixel(cir,x+cars[i]->w/2+cos(angle)*cars[i]->w/3+sin(angle)*4,y+cars[i]->h/2+sin(angle)*cars[i]->h/3-cos(angle)*4,0); + putpixel(cir,car.x+cos(car.angle)*car.w/3-sin(car.angle)*4,car.y+sin(car.angle)*car.h/3+cos(car.angle)*4,T_BLACK); + putpixel(cir,car.x+cos(car.angle)*car.w/3+sin(car.angle)*4,car.y+sin(car.angle)*car.h/3-cos(car.angle)*4,T_BLACK); + /* if we are braking the slide is larger */ + if (kd) + { + putpixel(cir,car.x+cos(car.angle)*car.w/3-sin(car.angle)*3,car.y+sin(car.angle)*car.h/3+cos(car.angle)*3,T_BLACK); + putpixel(cir,car.x+cos(car.angle)*car.w/3+sin(car.angle)*3,car.y+sin(car.angle)*car.h/3-cos(car.angle)*3,T_BLACK); + } } } - - c=getpixel(fun,x+cars[i]->w/2,y+cars[i]->h/2); - r=c&0x000000ff; - v=(c&0x0000ff00)>>8; - - if (v==0) + + /* if we crashed */ + if (car.crashflag && (lastsound_time+100MAX_LAG) { - printf("time = %d\"%d\n",time*5/1000,time*5%1000); - if (btime==-1 || timew/2-splash->w/2-1; pos.w=splash->w+2; pos.y=screen->h/2-splash->h/2-1; pos.h=splash->h+2; - SDL_FillRect(screen,&pos,0xffffff); + SDL_FillRect(screen,&pos,C_WHITE); pos.x=screen->w/2-splash->w/2; pos.y=screen->h/2-splash->h/2; SDL_BlitSurface(splash,NULL,screen,&pos); @@ -568,7 +1056,8 @@ void zeRace_splash() } -void zeRace_menu() +/* menu loop to select track */ +void zeRace_local() { SDL_Event event; @@ -576,13 +1065,17 @@ void zeRace_menu() { SDL_Surface *full,*preview; SDL_Rect pos; - SDL_FillRect(screen,NULL,0x000000); + SDL_FillRect(screen,NULL,C_BLACK); print(screen,WIDTH/2-28*5,HEIGHT/6,"* Please choose your race *"); print(screen,WIDTH/2-strlen(tracklist->title)*5,5*HEIGHT/6-20,tracklist->title); print(screen,WIDTH/2-(strlen(tracklist->author)+strlen("Author : "))*5,5*HEIGHT/6+0,"Author : "); print(screen,WIDTH/2-(strlen(tracklist->author)-strlen("Author : "))*5,5*HEIGHT/6+0,tracklist->author); - print(screen,WIDTH/2-(strlen(tracklist->version)+strlen("Version : "))*5,5*HEIGHT/6+20,"Version : "); - print(screen,WIDTH/2-(strlen(tracklist->version)-strlen("Version : "))*5,5*HEIGHT/6+20,tracklist->version); + print(screen,WIDTH/2-( strlen("Version : ")+strlen(tracklist->version))*5,5*HEIGHT/6+20,"Version : "); + print(screen,WIDTH/2-(-strlen("Version : ")+strlen(tracklist->version))*5,5*HEIGHT/6+20,tracklist->version); + print(screen,WIDTH/2-( strlen("Best time : ")+6+strlen(" by ")+strlen(tracklist->best_pseudo))*5,5*HEIGHT/6+40,"Best time : "); + print_time (WIDTH/2-(-strlen("Best time : ")+6+strlen(" by ")+strlen(tracklist->best_pseudo))*5,5*HEIGHT/6+40,tracklist->best_time); + print(screen,WIDTH/2-(-strlen("Best time : ")-6+strlen(" by ")+strlen(tracklist->best_pseudo))*5,5*HEIGHT/6+40," by "); + print(screen,WIDTH/2-(-strlen("Best time : ")-6-strlen(" by ")+strlen(tracklist->best_pseudo))*5,5*HEIGHT/6+40,tracklist->best_pseudo); full=IMG_Load(tracklist->full); preview=(SDL_Surface *)zoomSurface(full,0.5,0.5,1); SDL_FreeSurface(full); @@ -590,7 +1083,7 @@ void zeRace_menu() pos.w=preview->w+2; pos.y=screen->h/2-preview->h/2-1; pos.h=preview->h+2; - SDL_FillRect(screen,&pos,0xffffff); + SDL_FillRect(screen,&pos,C_WHITE); pos.x=WIDTH/2-preview->w/2; pos.y=screen->h/2-preview->h/2; SDL_BlitSurface(preview,NULL,screen,&pos); @@ -611,22 +1104,491 @@ void zeRace_menu() case SDL_KEYDOWN: switch (event.key.keysym.sym) { - case SDLK_ESCAPE: // escape - zeRace_exit(); - break; - case SDLK_RETURN: //enter - case SDLK_SPACE: //space - zeRace_launch(); + case SDLK_ESCAPE: + return; + case SDLK_RETURN: + case SDLK_SPACE: + zeRace_launch(0,1); update(); break; - case SDLK_LEFT: //left + case SDLK_LEFT: tracklist=tracklist->next; update(); break; - case SDLK_RIGHT: //right + case SDLK_RIGHT: tracklist=tracklist->prev; update(); break; + default: + break; + } + break; + } + } + SDL_Delay(10); + } +} + + +/* top 10 screen */ +void zeRace_top10(char *buf) +{ + int i,nb,tmp; + SDL_Rect pos; + SDL_FillRect(screen,NULL,C_BLACK); + nb=SDLNet_Read16(buf); + buf+=2; + print(screen,WIDTH/2-16*5,HEIGHT/14,"* Race results *"); + for (i=0;iaddress,host,port); + tmp=packet->data; + strcpy(tmp,"connect"); + tmp+=strlen(tmp)+1; + strcpy(tmp,config.pseudo); + tmp+=strlen(tmp)+1; + SDLNet_Write16(config.color,tmp); + tmp+=2; + packet->len=(void *)tmp-(void *)packet->data; + SDLNet_UDP_Send(udpsock,-1,packet); + /* network loop */ + while (SDLNet_UDP_Recv(udpsock,packet) || lagdata; + if (strcmp(tmp,"track")==0) + { + struct _tracklist *loopcheck=tracklist; + int time; + char go; + tmp+=strlen(tmp)+1; + go=*tmp++; + printf("server asked for track : %s\n",tmp); + do if (strcmp(tracklist->name,tmp)==0) break; else tracklist=tracklist->next; while (tracklist!=loopcheck); + if (strcmp(tracklist->name,tmp)!=0) + { + fprintf(stderr,"unknown track : %s\n",tmp); + zeRace_exit(); + } + tmp+=strlen(tmp)+1; + time=SDLNet_Read32(tmp); + tmp+=4; + network_speed=SDLNet_Read32(tmp); + zeRace_launch(time,go); + if (strcmp(packet->data,"finish")==0) zeRace_top10(packet->data+strlen(packet->data)+1); + lag=0; + } + SDL_Delay(7); + lag++; + } + SDLNet_UDP_Close(udpsock); + udpsock=NULL; +} + + +/* network game */ +void zeRace_network() +{ + SDL_Event event; + int active=0; + char server[MAXLINELENGTH]="localhost"; + char port[6]=PORT; + #define NETWORK_OPTIONS 4 + + void update() + { + SDL_FillRect(screen,NULL,C_BLACK); + print(screen,380,HEIGHT/(NETWORK_OPTIONS+4)*(3+active),">"); + print(screen,WIDTH/2-18*5,HEIGHT/(NETWORK_OPTIONS+4),"* Network screen *"); + print(screen,400,HEIGHT/(NETWORK_OPTIONS+4)*3,"Server : "); + print(screen,400+10*strlen("Server : "),HEIGHT/(NETWORK_OPTIONS+4)*3,server); + print(screen,400,HEIGHT/(NETWORK_OPTIONS+4)*4,"Port : "); + print(screen,400+10*strlen("Port : "),HEIGHT/(NETWORK_OPTIONS+4)*4,port); + print(screen,400,HEIGHT/(NETWORK_OPTIONS+4)*(NETWORK_OPTIONS+1),"Connect"); + print(screen,400,HEIGHT/(NETWORK_OPTIONS+4)*(NETWORK_OPTIONS+2),"Back to main menu"); + SDL_Flip(screen); + } + + update(); + for (;;) + { + while (SDL_PollEvent(&event)) + { + switch (event.type) + { + case SDL_QUIT: + zeRace_exit(); + break; + case SDL_KEYDOWN: + switch (event.key.keysym.sym) + { + case SDLK_ESCAPE: + return; + case SDLK_RETURN: + case SDLK_SPACE: + case SDLK_LEFT: + case SDLK_RIGHT: + switch (active) + { + case 0: readstring(screen,400+10*strlen("Server : "),HEIGHT/(NETWORK_OPTIONS+4)*3,server,MAXLINELENGTH); break; + case 1: readstring(screen,400+10*strlen("Port : "),HEIGHT/(NETWORK_OPTIONS+4)*4,port,5); break;; + case 2: + zeRace_connect(server,atoi(port)); + break; + case 3: + return; + } + update(); + break; + case SDLK_UP: + active--; if (active<0) active=NETWORK_OPTIONS-1; + update(); + break; + case SDLK_DOWN: + active++; if (active>NETWORK_OPTIONS-1) active=0; + update(); + break; + default: + break; + } + break; + } + } + SDL_Delay(10); + } +} + + +/* internet game */ +void zeRace_internet() +{ + IPaddress ip; + TCPsocket tcpsock; + char *request= + "GET /zerace/servers.php HTTP/1.0\n" + "Host: royale.zerezo.com\n" + "User-Agent: zeRace " VERSION "\n" + "\n"; + char response[10240],*tmp; + int len,result,i; + struct _server + { + char name[MAXLINELENGTH]; + char ip[16]; + char port[6]; + } servers[10]; + SDL_Event event; + int active=0; + #define INTERNET_OPTIONS 11 + + if (!config.internet) return; + + printf("dowloading list of servers... "); + fflush(stdout); + + if (SDLNet_ResolveHost(&ip,"royale.zerezo.com",80)==-1) + { + fprintf(stderr,"SDLNet_ResolveHost: %s\n",SDLNet_GetError()); + return; + } + + tcpsock=SDLNet_TCP_Open(&ip); + if (!tcpsock) + { + fprintf(stderr,"SDLNet_TCP_Open: %s\n",SDLNet_GetError()); + return; + } + + len=strlen(request); + result=SDLNet_TCP_Send(tcpsock,request,len); + if (result"); + print(screen,WIDTH/2-19*5,HEIGHT/(INTERNET_OPTIONS+4),"* Internet screen *"); + for (i=0;i<10;i++) + print(screen,400,HEIGHT/(INTERNET_OPTIONS+4)*(i+3),servers[i].name); + print(screen,400,HEIGHT/(INTERNET_OPTIONS+4)*(INTERNET_OPTIONS+2),"Back to main menu"); + SDL_Flip(screen); + } + + update(); + for (;;) + { + while (SDL_PollEvent(&event)) + { + switch (event.type) + { + case SDL_QUIT: + zeRace_exit(); + break; + case SDL_KEYDOWN: + switch (event.key.keysym.sym) + { + case SDLK_ESCAPE: + return; + case SDLK_RETURN: + case SDLK_SPACE: + case SDLK_LEFT: + case SDLK_RIGHT: + if (active==INTERNET_OPTIONS-1) + return; + else + zeRace_connect(servers[active].ip,atoi(servers[active].port)); + update(); + break; + case SDLK_UP: + active--; if (active<0) active=INTERNET_OPTIONS-1; + update(); + break; + case SDLK_DOWN: + active++; if (active>INTERNET_OPTIONS-1) active=0; + update(); + break; + default: + break; + } + break; + } + } + SDL_Delay(10); + } +} + + +/* configuration screen */ +void zeRace_config() +{ + SDL_Event event; + int active=0; + #define CONFIG_OPTIONS 14 + + void update() + { + SDL_Rect pos; + SDL_FillRect(screen,NULL,C_BLACK); + print(screen,20,HEIGHT/(CONFIG_OPTIONS+4)*(3+active),">"); + print(screen,WIDTH/2-24*5,HEIGHT/(CONFIG_OPTIONS+4),"* Configuration screen *"); + print(screen,40,HEIGHT/(CONFIG_OPTIONS+4)*3,"Pseudo : "); + print(screen,40+10*strlen("Pseudo : "),HEIGHT/(CONFIG_OPTIONS+4)*3,config.pseudo); + print(screen,40,HEIGHT/(CONFIG_OPTIONS+4)*4,"Url : "); + print(screen,40+10*strlen("Url : "),HEIGHT/(CONFIG_OPTIONS+4)*4,config.url); + print(screen,40,HEIGHT/(CONFIG_OPTIONS+4)*5,"Fullscreen : "); + print(screen,40+10*strlen("Fullscreen : "),HEIGHT/(CONFIG_OPTIONS+4)*5,config.fullscreen?"Yes":"No"); + print(screen,40,HEIGHT/(CONFIG_OPTIONS+4)*6,"Sound : "); + print(screen,40+10*strlen("Sound : "),HEIGHT/(CONFIG_OPTIONS+4)*6,config.sound?"Yes":"No"); + print(screen,40,HEIGHT/(CONFIG_OPTIONS+4)*7,"Tire : "); + print(screen,40+10*strlen("Tire : "),HEIGHT/(CONFIG_OPTIONS+4)*7,config.tire?"Yes":"No"); + print(screen,40,HEIGHT/(CONFIG_OPTIONS+4)*8,"Accelerate key : "); + print(screen,40+10*strlen("Accelerate key : "),HEIGHT/(CONFIG_OPTIONS+4)*8,config.up?SDL_GetKeyName(config.up):""); + print(screen,40,HEIGHT/(CONFIG_OPTIONS+4)*9,"Brake key : "); + print(screen,40+10*strlen("Brake key : "),HEIGHT/(CONFIG_OPTIONS+4)*9,config.down?SDL_GetKeyName(config.down):""); + print(screen,40,HEIGHT/(CONFIG_OPTIONS+4)*10,"Turn left key : "); + print(screen,40+10*strlen("Turn left key : "),HEIGHT/(CONFIG_OPTIONS+4)*10,config.left?SDL_GetKeyName(config.left):""); + print(screen,40,HEIGHT/(CONFIG_OPTIONS+4)*11,"Turn right key : "); + print(screen,40+10*strlen("Turn right key : "),HEIGHT/(CONFIG_OPTIONS+4)*11,config.right?SDL_GetKeyName(config.right):""); + print(screen,40,HEIGHT/(CONFIG_OPTIONS+4)*12,"Color : "); + pos.x=123; + pos.y=HEIGHT/(CONFIG_OPTIONS+4)*12-7; + SDL_BlitSurface(cars[config.color][0],NULL,screen,&pos); + print(screen,40,HEIGHT/(CONFIG_OPTIONS+4)*13,"Boss key : "); + print(screen,40+10*strlen("Boss key : "),HEIGHT/(CONFIG_OPTIONS+4)*13,config.boss?SDL_GetKeyName(config.boss):""); + print(screen,40,HEIGHT/(CONFIG_OPTIONS+4)*14,"By night : "); + print(screen,40+10*strlen("By night : "),HEIGHT/(CONFIG_OPTIONS+4)*14,config.bynight?"Yes":"No"); + print(screen,40,HEIGHT/(CONFIG_OPTIONS+4)*15,"Internet : "); + print(screen,40+10*strlen("Internet : "),HEIGHT/(CONFIG_OPTIONS+4)*15,config.internet?"Yes":"No"); + print(screen,40,HEIGHT/(CONFIG_OPTIONS+4)*(CONFIG_OPTIONS+2),"Back to main menu"); + SDL_Flip(screen); + } + + int read_key() + { + for (;;) + { + while (SDL_PollEvent(&event)) switch (event.type) + { + case SDL_KEYDOWN: + return event.key.keysym.sym; + } + SDL_Delay(10); + } + } + + update(); + for (;;) + { + while (SDL_PollEvent(&event)) + { + switch (event.type) + { + case SDL_QUIT: + zeRace_exit(); + break; + case SDL_KEYDOWN: + switch (event.key.keysym.sym) + { + case SDLK_ESCAPE: + return; + case SDLK_RETURN: + case SDLK_SPACE: + case SDLK_LEFT: + case SDLK_RIGHT: + switch (active) + { + case 0: readstring(screen,40+10*strlen("Pseudo : "),HEIGHT/(CONFIG_OPTIONS+4)*3,config.pseudo,MAXLINELENGTH); break; + case 1: readstring(screen,40+10*strlen("Url : "),HEIGHT/(CONFIG_OPTIONS+4)*4,config.url,MAXLINELENGTH); break;; + case 2: config.fullscreen=!config.fullscreen; break; + case 3: config.sound=!config.sound; break; + case 4: config.tire=!config.tire; break; + case 5: config.up=0; update(); config.up=read_key(); break; + case 6: config.down=0; update(); config.down=read_key(); break; + case 7: config.left=0; update(); config.left=read_key(); break; + case 8: config.right=0; update(); config.right=read_key(); break; + case 9: + if (event.key.keysym.sym==SDLK_LEFT) config.color--; else config.color++; + if (config.color<0) config.color=NB_CARS-1; + if (config.color>NB_CARS-1) config.color=0; + break; + case 10: config.boss=0; update(); config.boss=read_key(); break; + case 11: config.bynight=!config.bynight; break; + case 12: config.internet=!config.internet; break; + case 13: + return; + } + update(); + break; + case SDLK_UP: + active--; if (active<0) active=CONFIG_OPTIONS-1; + update(); + break; + case SDLK_DOWN: + active++; if (active>CONFIG_OPTIONS-1) active=0; + update(); + break; + default: + break; + } + break; + } + } + SDL_Delay(10); + } +} + + +/* main menu */ +void zeRace_menu() +{ + SDL_Event event; + int active=0; + SDL_Surface *logo; + #define MENU_OPTIONS 5 + + void update() + { + SDL_Rect pos; + SDL_FillRect(screen,NULL,C_BLACK); + pos.x=WIDTH/2-logo->w/2; + pos.y=HEIGHT/6-logo->h/2; + SDL_BlitSurface(logo,NULL,screen,&pos); + print(screen,650,HEIGHT/6+logo->h/3,"version " VERSION); + print(screen,420,HEIGHT/(MENU_OPTIONS+4)*(3+active),">"); + print(screen,440,HEIGHT/(MENU_OPTIONS+4)*3,"Local game"); + print(screen,440,HEIGHT/(MENU_OPTIONS+4)*4,"Network game"); + print(screen,440,HEIGHT/(MENU_OPTIONS+4)*5,"Internet game"); + print(screen,440,HEIGHT/(MENU_OPTIONS+4)*6,"Configuration"); + print(screen,440,HEIGHT/(MENU_OPTIONS+4)*7,"Exit game"); + SDL_Flip(screen); + } + + logo=IMG_Load("sprites/logo.jpg"); + update(); + for (;;) + { + while (SDL_PollEvent(&event)) + { + switch (event.type) + { + case SDL_QUIT: + zeRace_exit(); + break; + case SDL_KEYDOWN: + switch (event.key.keysym.sym) + { + case SDLK_ESCAPE: + return; + case SDLK_RETURN: + case SDLK_SPACE: + case SDLK_LEFT: + case SDLK_RIGHT: + switch (active) + { + case 0: zeRace_local(); break; + case 1: zeRace_network(); break; + case 2: zeRace_internet(); break; + case 3: zeRace_config(); break; + case 4: return; + } + update(); + break; + case SDLK_UP: + active--; if (active<0) active=MENU_OPTIONS-1; + update(); + break; + case SDLK_DOWN: + active++; if (active>MENU_OPTIONS-1) active=0; + update(); + break; + default: + break; } break; } @@ -636,6 +1598,7 @@ void zeRace_menu() } +/* main program */ int main(int argc,char *argv[]) { zeRace_init();