+ 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;i<nb;i++)
+ {
+ print(screen,150,(i+3)*HEIGHT/14,buf);
+ buf+=strlen(buf)+1;
+ tmp=SDLNet_Read16(buf);
+ buf+=2;
+ pos.x=110;
+ pos.y=(i+3)*HEIGHT/14-8;
+ SDL_BlitSurface(cars[tmp][0],NULL,screen,&pos);
+ }
+ SDL_Flip(screen);
+ SDL_Delay(5000);
+}
+
+
+/* connect to a server */
+void zeRace_connect(char *host,int port)
+{
+ char *tmp;
+ int lag=0;
+ udpsock=SDLNet_UDP_Open(0);
+ if (udpsock==NULL)
+ {
+ fprintf(stderr,"SDLNet_UDP_Open: %s\n",SDLNet_GetError());
+ zeRace_exit();
+ }
+ SDLNet_ResolveHost(&packet->address,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) || lag<MAX_LAG)
+ {
+ tmp=packet->data;
+ 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<len)
+ fprintf(stderr,"SDLNet_TCP_Send: %s\n",SDLNet_GetError());
+ else
+ {
+ len=SDLNet_TCP_Recv(tcpsock,response,10240);
+ tmp=response;
+ for (tmp=response;tmp<response+10240;tmp++) if (*tmp=='\n') *tmp='\0';
+ tmp=response;
+ while (*tmp!='\0' || *(tmp+1)!='\r') tmp++;
+ tmp+=3;
+ for (i=0;i<10;i++)
+ {
+ strcpy(servers[i].name,tmp);
+ tmp+=strlen(tmp)+1;
+ strcpy(servers[i].ip,tmp);
+ tmp+=strlen(tmp)+1;
+ strcpy(servers[i].port,tmp);
+ tmp+=strlen(tmp)+1;
+ }
+ printf("done\n");
+ }
+
+ SDLNet_TCP_Close(tcpsock);
+
+ void update()
+ {
+ int i;
+ SDL_FillRect(screen,NULL,C_BLACK);
+ print(screen,380,HEIGHT/(INTERNET_OPTIONS+4)*(3+active),">");
+ 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):"<press key>");
+ 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):"<press key>");
+ 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):"<press key>");
+ 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):"<press key>");
+ 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):"<press key>");
+ 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;