2 * zeRace 0.4, a funny retro racing game
3 * http://royale.zerezo.com/zerace/
5 * Copyright (C) 2004 Antoine Jacquet <royale@zerezo.com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include <SDL_image.h>
30 #include <SDL_mixer.h>
31 #include <SDL_rotozoom.h>
34 #include "tracklist.h"
38 /* configuration constants */
43 #define MAXRECORDKEYS 9999
46 struct _tracklist *tracklist;
51 char pseudo[MAXLINELENGTH];
52 char url[MAXLINELENGTH];
62 } config = {"anonymous","",0,0,1,SDLK_UP,SDLK_DOWN,SDLK_LEFT,SDLK_RIGHT,6,SDLK_b};
64 /* full script for a lap */
67 float x,y,angle,speed;
68 char keys[MAXRECORDKEYS];
72 /* display and all directions for the car */
74 SDL_Surface *cars[12][256];
77 UDPsocket udpsock=NULL;
82 /* read the user configuration file */
83 void zeRace_read_config()
86 if ((fic=fopen("zeRace.cfg","rt"))==NULL)
88 fprintf(stderr,"can't open config file \"zeRace.cfg\"\n");
91 fread(&config,sizeof(struct _config),1,fic);
96 /* save the user configuration file */
97 void zeRace_save_config()
100 if ((fic=fopen("zeRace.cfg","wt"))==NULL)
102 fprintf(stderr,"can't create config file \"zeRace.cfg\"\n");
105 fwrite(&config,sizeof(struct _config),1,fic);
110 /* exit the game and clean */
114 if (config.sound) Mix_CloseAudio();
117 zeRace_save_config();
122 /* check for a newer version online to warn the user */
123 void zeRace_check_version()
128 "GET /zerace/version.php HTTP/1.0\n"
129 "Host: royale.zerezo.com\n"
130 "User-Agent: zeRace " VERSION "\n"
132 char response[1024],*tmp,*version;
135 printf("checking version... ");
138 if (SDLNet_ResolveHost(&ip,"royale.zerezo.com",80)==-1)
140 fprintf(stderr,"SDLNet_ResolveHost: %s\n",SDLNet_GetError());
144 tcpsock=SDLNet_TCP_Open(&ip);
147 fprintf(stderr,"SDLNet_TCP_Open: %s\n",SDLNet_GetError());
152 result=SDLNet_TCP_Send(tcpsock,request,len);
154 fprintf(stderr,"SDLNet_TCP_Send: %s\n",SDLNet_GetError());
158 len=SDLNet_TCP_Recv(tcpsock,response,1024);
160 fprintf(stderr,"SDLNet_TCP_Recv: %s\n",SDLNet_GetError());
164 while (*tmp++!='\0') if (strncmp(tmp,"version=",8)==0)
167 while (*tmp!='\n') tmp++;
169 if (strcmp(version,VERSION)>0) printf("new version available !\nhttp://royale.zerezo.com/zerace/\n");
173 SDLNet_TCP_Close(tcpsock);
177 /* get remote list of tracks */
178 void zeRace_update_tracks()
183 "GET /zerace/tracks.php HTTP/1.0\n"
184 "Host: royale.zerezo.com\n"
185 "User-Agent: zeRace " VERSION "\n"
187 char response[10240],*tmp;
191 printf("checking version and updating tracks... ");
194 if (SDLNet_ResolveHost(&ip,"royale.zerezo.com",80)==-1)
196 fprintf(stderr,"SDLNet_ResolveHost: %s\n",SDLNet_GetError());
200 tcpsock=SDLNet_TCP_Open(&ip);
203 fprintf(stderr,"SDLNet_TCP_Open: %s\n",SDLNet_GetError());
208 result=SDLNet_TCP_Send(tcpsock,request,len);
210 fprintf(stderr,"SDLNet_TCP_Send: %s\n",SDLNet_GetError());
213 if ((fic=fopen("tracks/list.txt","wt"))==NULL)
215 fprintf(stderr,"can't create track list\n");
218 len=SDLNet_TCP_Recv(tcpsock,response,10240);
220 while (*tmp!='\n' || *(tmp+1)!='\r') tmp++;
222 fwrite(tmp,1,len+response-tmp,fic);
227 SDLNet_TCP_Close(tcpsock);
231 /* download the file if it is missing */
232 void zeRace_download_file(char *file)
237 char response[10240],*tmp;
242 if (stat(file,&buf)<0)
244 printf("downloading file \"%s\" : ",file);
247 if (SDLNet_ResolveHost(&ip,"royale.zerezo.com",80)==-1)
249 fprintf(stderr,"SDLNet_ResolveHost: %s\n",SDLNet_GetError());
253 tcpsock=SDLNet_TCP_Open(&ip);
256 fprintf(stderr,"SDLNet_TCP_Open: %s\n",SDLNet_GetError());
261 "GET /zerace/%s HTTP/1.0\n"
262 "Host: royale.zerezo.com\n"
263 "User-Agent: zeRace " VERSION "\n"
266 result=SDLNet_TCP_Send(tcpsock,request,len);
268 fprintf(stderr,"SDLNet_TCP_Send: %s\n",SDLNet_GetError());
271 if ((fic=fopen(file,"wt"))==NULL)
273 fprintf(stderr,"can't create \"%s\" file\n",file);
276 len=SDLNet_TCP_Recv(tcpsock,response,10240);
278 while (*tmp!='\n' || *(tmp+1)!='\r') tmp++;
280 fwrite(tmp,1,len+response-tmp,fic);
281 while ((len=SDLNet_TCP_Recv(tcpsock,response,10240))) fwrite(response,1,len,fic);
286 SDLNet_TCP_Close(tcpsock);
291 /* load the car sprite and rotate it for every angles */
292 void zeRace_generate_cars()
296 char temp[20]="sprites/carX.png";
300 /* load the car sprite */
302 /* and rotate it for all available angles */
307 if ((cars[i][j]=SDL_CreateRGBSurface(SDL_SWSURFACE,30,30,32,0xff<<RSHIFT,0xff<<GSHIFT,0xff<<BSHIFT,0xff<<ASHIFT))==NULL)
309 fprintf(stderr,"CreateRGBSurface failed: %s\n",SDL_GetError());
312 tcos=cos(2*M_PI*j/256);
313 tsin=sin(2*M_PI*j/256);
314 for (x=0;x<cars[i][j]->w;x++) for (y=0;y<cars[i][j]->h;y++)
317 x2=(x-cars[i][j]->w/2.0)*tcos+(y-cars[i][j]->h/2.0)*tsin+car->w/2.0;
318 y2=(x-cars[i][j]->w/2.0)*tsin-(y-cars[i][j]->h/2.0)*tcos+car->h/2.0;
319 if (x2>0 && x2<car->w && y2>0 && y2<car->h)
320 putpixel(cars[i][j],x,y,getpixel(car,x2,y2));
323 SDL_FreeSurface(car);
328 /* initialize the game */
332 struct _tracklist *loopcheck;
334 /* do a clean exit in case of emergency */
335 signal(SIGINT,zeRace_exit);
336 signal(SIGTERM,zeRace_exit);
338 /* read the user configuration file */
339 zeRace_read_config();
341 /* check for a newer available version */
342 zeRace_check_version();
344 /* update the list of tracks */
345 zeRace_update_tracks();
347 /* get the list of local tracks */
348 if (!zeRace_get_tracks(&tracklist)) zeRace_exit();
350 /* download missing files */
352 while (tracklist->next!=loopcheck)
354 zeRace_download_file(tracklist->full);
355 zeRace_download_file(tracklist->function);
356 tracklist=tracklist->next;
361 if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO)<0)
363 fprintf(stderr,"could not initialize SDL : %s\n",SDL_GetError());
368 if (SDLNet_Init()==-1)
370 fprintf(stderr,"could not initialize SDLNet : %s\n",SDLNet_GetError());
374 packet=SDLNet_AllocPacket(1024);
377 fprintf(stderr,"SDLNet_AllocPacket: %s\n",SDLNet_GetError());
381 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY,SDL_DEFAULT_REPEAT_INTERVAL);
383 flags=SDL_HWSURFACE|SDL_ANYFORMAT;
384 if (config.fullscreen) flags|=SDL_FULLSCREEN;
386 if ((screen=SDL_SetVideoMode(WIDTH,HEIGHT,32,flags))==NULL)
388 fprintf(stderr,"could not create a surface : %s\n",SDL_GetError());
392 SDL_WM_SetIcon(SDL_LoadBMP("icon.bmp"),NULL);
393 SDL_WM_SetCaption("zeRace " VERSION,"zeRace " VERSION);
394 SDL_ShowCursor(SDL_DISABLE);
396 if (config.sound) if (Mix_OpenAudio(44100,MIX_DEFAULT_FORMAT,2,512)<0)
398 fprintf(stderr,"Mix_OpenAudio error\n");
402 /* pre-calculate car sprites */
403 zeRace_generate_cars();
407 /* send the best time for this race to the web server */
408 void zeRace_send_time(struct _record record)
414 "POST /zerace/time.php HTTP/1.0\n"
415 "Host: royale.zerezo.com\n"
416 "User-Agent: zeRace " VERSION "\n"
417 "Content-Type: application/x-www-form-urlencoded\n"
418 "Content-Length: 99999\n"
422 char *msg3="&track=";
423 char *msg4="&btime=";
426 char *msg7="&speed=";
427 char *msg8="&angle=";
428 char *msg9="&bkeys=";
431 /* if the best time is small enought to save all keys, send it */
432 if (record.time>=MAXRECORDKEYS) return;
434 printf("sending time... ");
437 if (SDLNet_ResolveHost(&ip,"royale.zerezo.com",80)==-1)
439 fprintf(stderr,"SDLNet_ResolveHost: %s\n",SDLNet_GetError());
443 tcpsock=SDLNet_TCP_Open(&ip);
446 fprintf(stderr,"SDLNet_TCP_Open: %s\n",SDLNet_GetError());
450 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);
451 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);
454 result=SDLNet_TCP_Send(tcpsock,temp,len);
456 fprintf(stderr,"SDLNet_TCP_Send: %s\n", SDLNet_GetError());
460 SDLNet_TCP_Close(tcpsock);
464 /* print a time for a lap */
465 void print_time(int x,int y,int time)
477 temp[4]=r%100/10+'0';
480 print(screen,x,y,temp);
484 /* launch a new race */
485 void zeRace_launch(int alltime,int go)
487 SDL_Surface *cir,*fun;
490 int ku=0,kd=0,kl=0,kr=0,i;
492 struct _record current,best;
493 Mix_Music *light,*engine,*crash,*slide;
494 int lastsound_time=-999,lastsound=0;
498 struct _car oldnetpos[MAX_CLIENTS],newnetpos[MAX_CLIENTS];
503 SDL_FreeSurface(cir);
504 SDL_FreeSurface(fun);
507 Mix_FreeMusic(light);
508 Mix_FreeMusic(engine);
509 Mix_FreeMusic(crash);
510 Mix_FreeMusic(slide);
515 cir=IMG_Load(tracklist->full);
516 fun=IMG_Load(tracklist->function);
518 current.speed=car.speed=0;
519 current.angle=car.angle=tracklist->a*2*M_PI/360;
520 current.x=car.ox=car.x=tracklist->x;
521 current.y=car.oy=car.y=tracklist->y;
526 best.time=MAXRECORDKEYS;
528 memset(oldnetpos,0,MAX_CLIENTS*sizeof(struct _car));
529 memset(newnetpos,0,MAX_CLIENTS*sizeof(struct _car));
531 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")))
533 fprintf(stderr,"Mix_LoadMUS error\n");
537 /* startup countdown */
540 char startup[15]="sprites/?.png";
545 SDL_BlitSurface(cir,NULL,screen,NULL);
546 SDL_BlitSurface(cars[config.color][(unsigned char)(256*car.angle/2.0/M_PI)%256],NULL,screen,&pos);
549 temp=IMG_Load(startup);
550 pos.x=screen->w/2-temp->w/2;
551 pos.y=screen->h/2-temp->h/2;
552 SDL_BlitSurface(temp,NULL,screen,&pos);
553 SDL_FreeSurface(temp);
555 if (config.sound) if (i!=4) Mix_PlayMusic(light,1);
558 if (i!=-1) SDL_Delay(1000);
564 /* look for user interaction */
565 while (SDL_PollEvent(&event))
573 switch (event.key.keysym.sym)
578 print(screen,WIDTH/2-strlen("Disconnecting !")*5,HEIGHT/2-10,"Disconnecting !");
579 strcpy(packet->data,"disconnect");
580 packet->len=strlen(packet->data)+1;
581 SDLNet_UDP_Send(udpsock,-1,packet);
584 zeRace_send_time(best);
588 i=event.key.keysym.sym;
589 if (i==config.up) ku=1;
590 if (i==config.down) kd=1;
591 if (i==config.left) kl=1;
592 if (i==config.right) kr=1;
595 /* display the boss screen */
597 boss=IMG_Load("sprites/boss.png");
598 SDL_BlitSurface(boss,NULL,screen,NULL);
599 SDL_FreeSurface(boss);
601 /* and wait until the user press another key */
602 for (;;) if (SDL_PollEvent(&event)) { if (event.type==SDL_KEYDOWN) break; } else SDL_Delay(10);
603 SDL_BlitSurface(cir,NULL,screen,NULL);
610 i=event.key.keysym.sym;
611 if (i==config.up) ku=0;
612 if (i==config.down) kd=0;
613 if (i==config.left) kl=0;
614 if (i==config.right) kr=0;
619 /* save pressed keys to validate best time */
620 if (current.time<MAXRECORDKEYS) current.keys[current.time]=(ku<<3 | kd<<2 | kl<<1 | kr)+'A';
621 current.keys[current.time+1]='\0';
622 /* and to send to server if needed */
625 net.keys[net.time]=(ku<<3 | kd<<2 | kl<<1 | kr)+'A';
626 net.keys[net.time+1]='\0';
630 /* if we are in network mode */
634 while (SDLNet_UDP_Recv(udpsock,packet)) if (strcmp(packet->data,"positions")==0)
636 int servertime,clienttime,nb;
637 servertime=SDLNet_Read32(packet->data+strlen("positions")+1);
638 clienttime=SDLNet_Read32(packet->data+strlen("positions")+1+4);
639 nb=SDLNet_Read16(packet->data+strlen("positions")+1+4+4);
640 if (clienttime>lastack)
642 memcpy(net.keys,net.keys+clienttime-lastack,net.time+1);
643 net.time-=clienttime-lastack;
644 if (clienttime>servertime+5) delay+=DELAY;
645 if (clienttime<servertime-5) delay-=DELAY;
646 if (delay<0) delay=0;
647 for (i=0;i<MAX_CLIENTS;i++) newnetpos[i].w=0;
650 newnetpos[i].w=newnetpos[i].h=30;
651 newnetpos[i].x=SDLNet_Read16(packet->data+strlen("positions")+1+4+4+2+i*8);
652 newnetpos[i].y=SDLNet_Read16(packet->data+strlen("positions")+1+4+4+2+i*8+2);
653 newnetpos[i].angle=(float)SDLNet_Read16(packet->data+strlen("positions")+1+4+4+2+i*8+2+2)/1000;
654 newnetpos[i].color=SDLNet_Read16(packet->data+strlen("positions")+1+4+4+2+i*8+2+2+2);
659 else /* end of this network race */
661 zeRace_send_time(best);
665 if (strlen(net.keys)!=0)
670 SDLNet_Write32(lastack,tmp);
672 strcpy(tmp,net.keys);
674 packet->len=(void *)tmp-(void *)packet->data+10;
675 if (net.time%network_speed==0) if (!SDLNet_UDP_Send(udpsock,-1,packet))
677 fprintf(stderr,"SDLNet_UDP_Send: %s\n",SDLNet_GetError());
683 /* clear the old network position */
684 if (udpsock) for (i=0;i<MAX_CLIENTS;i++) if (oldnetpos[i].w)
686 pos.x=oldnetpos[i].x-car.w/2;
687 pos.y=oldnetpos[i].y-car.h/2;
690 SDL_BlitSurface(cir,&pos,screen,&pos);
693 /* clear the old position */
694 pos.x=car.ox-car.w/2;
695 pos.y=car.oy-car.h/2;
698 SDL_BlitSurface(cir,&pos,screen,&pos);
700 /* display the network car at the new position */
701 if (udpsock) for (i=0;i<MAX_CLIENTS;i++) if (newnetpos[i].w)
703 pos.x=newnetpos[i].x-car.w/2;
704 pos.y=newnetpos[i].y-car.h/2;
707 SDL_BlitSurface(cars[newnetpos[i].color][(unsigned char)(256*newnetpos[i].angle/2.0/M_PI)%256],NULL,screen,&pos);
710 /* display the car at the new position */
715 SDL_BlitSurface(cars[config.color][(unsigned char)(256*car.angle/2.0/M_PI)%256],NULL,screen,&pos);
720 for (i=0;i<MAX_CLIENTS;i++)
722 if (oldnetpos[i].w) SDL_UpdateRect(screen,oldnetpos[i].x-car.w/2,oldnetpos[i].y-car.h/2,car.w,car.h);
723 if (newnetpos[i].w) SDL_UpdateRect(screen,newnetpos[i].x-car.w/2,newnetpos[i].y-car.h/2,car.w,car.h);
725 memcpy(oldnetpos,newnetpos,MAX_CLIENTS*sizeof(struct _car));
727 SDL_UpdateRect(screen,car.ox-car.w/2,car.oy-car.h/2,car.w,car.h);
728 SDL_UpdateRect(screen,car.x-car.w/2,car.y-car.h/2,car.w,car.h);
730 memcpy(oldnetpos,newnetpos,MAX_CLIENTS*sizeof(struct _car));
733 move_car(&car,(ku<<3 | kd<<2 | kl<<1 | kr),fun);
735 /* play engine sound if no sound is currently playing */
736 if (lastsound_time+100<alltime)
739 lastsound_time=alltime;
740 if (config.sound) Mix_PlayMusic(engine,1);
743 /* if the car is fast or braking, it slides */
744 if ((kd && car.speed>0.5) || (car.speed>2.0 && !ku))
746 /* if the only sound is the engine, play the slide sound */
747 if (lastsound_time+100<alltime || lastsound<1)
750 lastsound_time=alltime;
751 if (config.sound) Mix_PlayMusic(slide,1)==-1;
754 /* display tires slide */
757 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,0);
758 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,0);
759 /* if we are braking the slide is larger */
762 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,0);
763 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,0);
769 if (car.crashflag && (lastsound_time+100<alltime || lastsound<2))
772 lastsound_time=alltime;
773 if (config.sound) Mix_PlayMusic(crash,1)==-1;
779 if (udpsock && net.time>MAX_LAG)
781 print(screen,WIDTH/2-strlen("Timeout !")*5,HEIGHT/2-10,"Timeout !");
783 zeRace_send_time(best);
789 /* if we completed a lap */
792 printf("time = %d\"%d\n",current.time*DELAY/1000,current.time*DELAY%1000);
793 print(screen,0,0,"Last lap : ");
794 print_time(110,0,current.time);
795 SDL_UpdateRect(screen,0,0,170,19);
796 /* if it is the first turn of the best turn, save it */
797 if (best.time==-1 || current.time<best.time)
798 memcpy(&best,¤t,sizeof(struct _record));
799 /* reset turn variables */
803 current.angle=car.angle;
804 current.speed=car.speed;
807 /* let the system breath */
813 /* display a random splash screen at startup */
818 char temp[20]="splashs/0.jpg";
820 SDL_FillRect(screen,NULL,0x000000);
821 temp[8]=rand()%3+'1';
822 splash=IMG_Load(temp);
823 pos.x=screen->w/2-splash->w/2-1;
825 pos.y=screen->h/2-splash->h/2-1;
827 SDL_FillRect(screen,&pos,0xffffff);
828 pos.x=screen->w/2-splash->w/2;
829 pos.y=screen->h/2-splash->h/2;
830 SDL_BlitSurface(splash,NULL,screen,&pos);
831 print(screen,screen->w/2-strlen("zeRace " VERSION)*5,screen->h/2-splash->h/2-20,"zeRace " VERSION);
832 SDL_FreeSurface(splash);
838 /* menu loop to select track */
845 SDL_Surface *full,*preview;
847 SDL_FillRect(screen,NULL,0x000000);
848 print(screen,WIDTH/2-28*5,HEIGHT/6,"* Please choose your race *");
849 print(screen,WIDTH/2-strlen(tracklist->title)*5,5*HEIGHT/6-20,tracklist->title);
850 print(screen,WIDTH/2-(strlen(tracklist->author)+strlen("Author : "))*5,5*HEIGHT/6+0,"Author : ");
851 print(screen,WIDTH/2-(strlen(tracklist->author)-strlen("Author : "))*5,5*HEIGHT/6+0,tracklist->author);
852 print(screen,WIDTH/2-( strlen("Version : ")+strlen(tracklist->version))*5,5*HEIGHT/6+20,"Version : ");
853 print(screen,WIDTH/2-(-strlen("Version : ")+strlen(tracklist->version))*5,5*HEIGHT/6+20,tracklist->version);
854 print(screen,WIDTH/2-( strlen("Best time : ")+6+strlen(" by ")+strlen(tracklist->best_pseudo))*5,5*HEIGHT/6+40,"Best time : ");
855 print_time (WIDTH/2-(-strlen("Best time : ")+6+strlen(" by ")+strlen(tracklist->best_pseudo))*5,5*HEIGHT/6+40,tracklist->best_time);
856 print(screen,WIDTH/2-(-strlen("Best time : ")-6+strlen(" by ")+strlen(tracklist->best_pseudo))*5,5*HEIGHT/6+40," by ");
857 print(screen,WIDTH/2-(-strlen("Best time : ")-6-strlen(" by ")+strlen(tracklist->best_pseudo))*5,5*HEIGHT/6+40,tracklist->best_pseudo);
858 full=IMG_Load(tracklist->full);
859 preview=(SDL_Surface *)zoomSurface(full,0.5,0.5,1);
860 SDL_FreeSurface(full);
861 pos.x=WIDTH/2-preview->w/2-1;
863 pos.y=screen->h/2-preview->h/2-1;
865 SDL_FillRect(screen,&pos,0xffffff);
866 pos.x=WIDTH/2-preview->w/2;
867 pos.y=screen->h/2-preview->h/2;
868 SDL_BlitSurface(preview,NULL,screen,&pos);
869 SDL_FreeSurface(preview);
876 while (SDL_PollEvent(&event))
884 switch (event.key.keysym.sym)
894 tracklist=tracklist->next;
898 tracklist=tracklist->prev;
913 void zeRace_top10(char *buf)
917 SDL_FillRect(screen,NULL,0x000000);
918 nb=SDLNet_Read16(buf);
920 print(screen,WIDTH/2-16*5,HEIGHT/14,"* Race results *");
923 print(screen,150,(i+3)*HEIGHT/14,buf);
925 tmp=SDLNet_Read16(buf);
928 pos.y=(i+3)*HEIGHT/14-8;
929 SDL_BlitSurface(cars[tmp][0],NULL,screen,&pos);
936 /* connect to a server */
937 void zeRace_connect(char *host,int port)
941 udpsock=SDLNet_UDP_Open(0);
944 fprintf(stderr,"SDLNet_UDP_Open: %s\n",SDLNet_GetError());
947 SDLNet_ResolveHost(&packet->address,host,port);
949 strcpy(tmp,"connect");
951 strcpy(tmp,config.pseudo);
953 SDLNet_Write16(config.color,tmp);
955 packet->len=(void *)tmp-(void *)packet->data;
956 SDLNet_UDP_Send(udpsock,-1,packet);
958 while (SDLNet_UDP_Recv(udpsock,packet) || lag<MAX_LAG)
961 if (strcmp(tmp,"track")==0)
963 struct _tracklist *loopcheck=tracklist;
968 printf("server asked for track : %s\n",tmp);
969 while (tracklist->next!=loopcheck) if (strcmp(tracklist->name,tmp)==0) break; else tracklist=tracklist->next;
970 if (strcmp(tracklist->name,tmp)!=0)
972 fprintf(stderr,"unknown track : %s\n",tmp);
976 time=SDLNet_Read32(tmp);
978 network_speed=SDLNet_Read32(tmp);
979 zeRace_launch(time,go);
980 if (strcmp(packet->data,"finish")==0) zeRace_top10(packet->data+strlen(packet->data)+1);
986 SDLNet_UDP_Close(udpsock);
992 void zeRace_network()
996 char server[MAXLINELENGTH]="localhost";
998 #define NETWORK_OPTIONS 4
1002 SDL_FillRect(screen,NULL,0x000000);
1003 print(screen,380,HEIGHT/(NETWORK_OPTIONS+4)*(3+active),">");
1004 print(screen,WIDTH/2-18*5,HEIGHT/(NETWORK_OPTIONS+4),"* Network screen *");
1005 print(screen,400,HEIGHT/(NETWORK_OPTIONS+4)*3,"Server : ");
1006 print(screen,400+10*strlen("Server : "),HEIGHT/(NETWORK_OPTIONS+4)*3,server);
1007 print(screen,400,HEIGHT/(NETWORK_OPTIONS+4)*4,"Port : ");
1008 print(screen,400+10*strlen("Port : "),HEIGHT/(NETWORK_OPTIONS+4)*4,port);
1009 print(screen,400,HEIGHT/(NETWORK_OPTIONS+4)*(NETWORK_OPTIONS+1),"Connect");
1010 print(screen,400,HEIGHT/(NETWORK_OPTIONS+4)*(NETWORK_OPTIONS+2),"Back to main menu");
1017 while (SDL_PollEvent(&event))
1025 switch (event.key.keysym.sym)
1035 case 0: readstring(screen,400+10*strlen("Server : "),HEIGHT/(NETWORK_OPTIONS+4)*3,server,MAXLINELENGTH); break;
1036 case 1: readstring(screen,400+10*strlen("Port : "),HEIGHT/(NETWORK_OPTIONS+4)*4,port,5); break;;
1038 zeRace_connect(server,atoi(port));
1046 active--; if (active<0) active=NETWORK_OPTIONS-1;
1050 active++; if (active>NETWORK_OPTIONS-1) active=0;
1065 void zeRace_internet()
1070 "GET /zerace/servers.php HTTP/1.0\n"
1071 "Host: royale.zerezo.com\n"
1072 "User-Agent: zeRace " VERSION "\n"
1074 char response[10240],*tmp;
1078 char name[MAXLINELENGTH];
1084 #define INTERNET_OPTIONS 11
1086 printf("dowloading list of servers... ");
1089 if (SDLNet_ResolveHost(&ip,"royale.zerezo.com",80)==-1)
1091 fprintf(stderr,"SDLNet_ResolveHost: %s\n",SDLNet_GetError());
1095 tcpsock=SDLNet_TCP_Open(&ip);
1098 fprintf(stderr,"SDLNet_TCP_Open: %s\n",SDLNet_GetError());
1102 len=strlen(request);
1103 result=SDLNet_TCP_Send(tcpsock,request,len);
1105 fprintf(stderr,"SDLNet_TCP_Send: %s\n",SDLNet_GetError());
1108 len=SDLNet_TCP_Recv(tcpsock,response,10240);
1110 for (tmp=response;tmp<response+10240;tmp++) if (*tmp=='\n') *tmp='\0';
1112 while (*tmp!='\0' || *(tmp+1)!='\r') tmp++;
1116 strcpy(servers[i].name,tmp);
1118 strcpy(servers[i].ip,tmp);
1120 strcpy(servers[i].port,tmp);
1126 SDLNet_TCP_Close(tcpsock);
1131 SDL_FillRect(screen,NULL,0x000000);
1132 print(screen,380,HEIGHT/(INTERNET_OPTIONS+4)*(3+active),">");
1133 print(screen,WIDTH/2-19*5,HEIGHT/(INTERNET_OPTIONS+4),"* Internet screen *");
1135 print(screen,400,HEIGHT/(INTERNET_OPTIONS+4)*(i+3),servers[i].name);
1136 print(screen,400,HEIGHT/(INTERNET_OPTIONS+4)*(INTERNET_OPTIONS+2),"Back to main menu");
1143 while (SDL_PollEvent(&event))
1151 switch (event.key.keysym.sym)
1159 if (active==INTERNET_OPTIONS-1)
1162 zeRace_connect(servers[active].ip,atoi(servers[active].port));
1166 active--; if (active<0) active=INTERNET_OPTIONS-1;
1170 active++; if (active>INTERNET_OPTIONS-1) active=0;
1184 /* configuration screen */
1185 void zeRace_config()
1189 #define CONFIG_OPTIONS 12
1194 SDL_FillRect(screen,NULL,0x000000);
1195 print(screen,20,HEIGHT/(CONFIG_OPTIONS+4)*(3+active),">");
1196 print(screen,WIDTH/2-24*5,HEIGHT/(CONFIG_OPTIONS+4),"* Configuration screen *");
1197 print(screen,40,HEIGHT/(CONFIG_OPTIONS+4)*3,"Pseudo : ");
1198 print(screen,40+10*strlen("Pseudo : "),HEIGHT/(CONFIG_OPTIONS+4)*3,config.pseudo);
1199 print(screen,40,HEIGHT/(CONFIG_OPTIONS+4)*4,"Url : ");
1200 print(screen,40+10*strlen("Url : "),HEIGHT/(CONFIG_OPTIONS+4)*4,config.url);
1201 print(screen,40,HEIGHT/(CONFIG_OPTIONS+4)*5,"Fullscreen : ");
1202 print(screen,40+10*strlen("Fullscreen : "),HEIGHT/(CONFIG_OPTIONS+4)*5,config.fullscreen?"Yes":"No");
1203 print(screen,40,HEIGHT/(CONFIG_OPTIONS+4)*6,"Sound : ");
1204 print(screen,40+10*strlen("Sound : "),HEIGHT/(CONFIG_OPTIONS+4)*6,config.sound?"Yes":"No");
1205 print(screen,40,HEIGHT/(CONFIG_OPTIONS+4)*7,"Tire : ");
1206 print(screen,40+10*strlen("Tire : "),HEIGHT/(CONFIG_OPTIONS+4)*7,config.tire?"Yes":"No");
1207 print(screen,40,HEIGHT/(CONFIG_OPTIONS+4)*8,"Accelerate key : ");
1208 print(screen,40+10*strlen("Accelerate key : "),HEIGHT/(CONFIG_OPTIONS+4)*8,config.up?SDL_GetKeyName(config.up):"<press key>");
1209 print(screen,40,HEIGHT/(CONFIG_OPTIONS+4)*9,"Brake key : ");
1210 print(screen,40+10*strlen("Brake key : "),HEIGHT/(CONFIG_OPTIONS+4)*9,config.down?SDL_GetKeyName(config.down):"<press key>");
1211 print(screen,40,HEIGHT/(CONFIG_OPTIONS+4)*10,"Turn left key : ");
1212 print(screen,40+10*strlen("Turn left key : "),HEIGHT/(CONFIG_OPTIONS+4)*10,config.left?SDL_GetKeyName(config.left):"<press key>");
1213 print(screen,40,HEIGHT/(CONFIG_OPTIONS+4)*11,"Turn right key : ");
1214 print(screen,40+10*strlen("Turn right key : "),HEIGHT/(CONFIG_OPTIONS+4)*11,config.right?SDL_GetKeyName(config.right):"<press key>");
1215 print(screen,40,HEIGHT/(CONFIG_OPTIONS+4)*12,"Color : ");
1217 pos.y=HEIGHT/(CONFIG_OPTIONS+4)*12-7;
1218 SDL_BlitSurface(cars[config.color][0],NULL,screen,&pos);
1219 print(screen,40,HEIGHT/(CONFIG_OPTIONS+4)*13,"Boss key : ");
1220 print(screen,40+10*strlen("Boss key : "),HEIGHT/(CONFIG_OPTIONS+4)*13,config.boss?SDL_GetKeyName(config.boss):"<press key>");
1221 print(screen,40,HEIGHT/(CONFIG_OPTIONS+4)*(CONFIG_OPTIONS+2),"Back to main menu");
1229 while (SDL_PollEvent(&event)) switch (event.type)
1232 return event.key.keysym.sym;
1241 while (SDL_PollEvent(&event))
1249 switch (event.key.keysym.sym)
1259 case 0: readstring(screen,40+10*strlen("Pseudo : "),HEIGHT/(CONFIG_OPTIONS+4)*3,config.pseudo,MAXLINELENGTH); break;
1260 case 1: readstring(screen,40+10*strlen("Url : "),HEIGHT/(CONFIG_OPTIONS+4)*4,config.url,MAXLINELENGTH); break;;
1261 case 2: config.fullscreen=!config.fullscreen; break;
1262 case 3: config.sound=!config.sound; break;
1263 case 4: config.tire=!config.tire; break;
1264 case 5: config.up=0; update(); config.up=read_key(); break;
1265 case 6: config.down=0; update(); config.down=read_key(); break;
1266 case 7: config.left=0; update(); config.left=read_key(); break;
1267 case 8: config.right=0; update(); config.right=read_key(); break;
1269 if (event.key.keysym.sym==SDLK_LEFT) config.color--; else config.color++;
1270 if (config.color<0) config.color=11;
1271 if (config.color>11) config.color=0;
1273 case 10: config.boss=0; update(); config.boss=read_key(); break;
1280 active--; if (active<0) active=CONFIG_OPTIONS-1;
1284 active++; if (active>CONFIG_OPTIONS-1) active=0;
1304 #define MENU_OPTIONS 5
1309 SDL_FillRect(screen,NULL,0x000000);
1310 pos.x=WIDTH/2-logo->w/2;
1311 pos.y=HEIGHT/6-logo->h/2;
1312 SDL_BlitSurface(logo,NULL,screen,&pos);
1313 print(screen,650,HEIGHT/6+logo->h/3,"version " VERSION);
1314 print(screen,420,HEIGHT/(MENU_OPTIONS+4)*(3+active),">");
1315 print(screen,440,HEIGHT/(MENU_OPTIONS+4)*3,"Local game");
1316 print(screen,440,HEIGHT/(MENU_OPTIONS+4)*4,"Network game");
1317 print(screen,440,HEIGHT/(MENU_OPTIONS+4)*5,"Internet game");
1318 print(screen,440,HEIGHT/(MENU_OPTIONS+4)*6,"Configuration");
1319 print(screen,440,HEIGHT/(MENU_OPTIONS+4)*7,"Exit game");
1323 logo=IMG_Load("sprites/logo.jpg");
1327 while (SDL_PollEvent(&event))
1335 switch (event.key.keysym.sym)
1345 case 0: zeRace_local(); break;
1346 case 1: zeRace_network(); break;
1347 case 2: zeRace_internet(); break;
1348 case 3: zeRace_config(); break;
1354 active--; if (active<0) active=MENU_OPTIONS-1;
1358 active++; if (active>MENU_OPTIONS-1) active=0;
1373 int main(int argc,char *argv[])