int lasttime;
struct _car car;
IPaddress address;
+ int dx,dy;
} clients [MAX_CLIENTS];
/* UDP stuff */
struct _tracklist *tracklist;
SDL_Surface *fun;
+SDL_Surface *cars[256];
/* return the id of a connected address */
}
+/* load the car sprite and rotate it for every angles */
+void zeRace_generate_cars()
+{
+ int j;
+ SDL_Surface *car;
+ char temp[20]="sprites/carX.png";
+ temp[11]='A';
+ /* load the car sprite */
+ car=IMG_Load(temp);
+ /* and rotate it for all available angles */
+ for (j=0;j<256;j++)
+ {
+ float x,y;
+ float tcos,tsin;
+ if ((cars[j]=SDL_CreateRGBSurface(SDL_SWSURFACE,30,30,32,RMASK,GMASK,BMASK,AMASK))==NULL)
+ {
+ fprintf(stderr,"CreateRGBSurface failed: %s\n",SDL_GetError());
+ };
+ tcos=cos(2*M_PI*j/256);
+ tsin=sin(2*M_PI*j/256);
+ for (x=0;x<cars[j]->w;x++) for (y=0;y<cars[j]->h;y++)
+ {
+ int x2,y2;
+ x2=(x-cars[j]->w/2.0)*tcos+(y-cars[j]->h/2.0)*tsin+car->w/2.0;
+ y2=(x-cars[j]->w/2.0)*tsin-(y-cars[j]->h/2.0)*tcos+car->h/2.0;
+ if (x2>0 && x2<car->w && y2>0 && y2<car->h)
+ putpixel(cars[j],x,y,getpixel(car,x2,y2));
+ }
+ }
+ SDL_FreeSurface(car);
+}
+
+
/* main program */
int main(int argc,char *argv[])
{
int id,i,j,time=0,nb;
char *tmp;
unsigned char ip[4];
- int nb_laps,network_speed,pub;
+ int nb_laps,network_speed,pub,col;
- if (argc!=5)
+ if (argc!=6)
{
fprintf(stderr,
- "usage: %s 'server_name' nb_laps network_speed (public|private)\n"
+ "Usage: %s 'server_name' nb_laps network_speed (public|private) (col|nocol)\n"
" server_name : the name of the server\n"
" nb_laps : the number of laps to complete for each race\n"
" network_speed : frequency of network messages (1 for fast network, 10 for slow network...)\n"
" private : this server will not be listed in the 'internet games'\n"
+ " col : the server will compute collisions between cars\n"
,argv[0]
);
exit(1);
printf("nb_laps : %d\n",nb_laps=atoi(argv[2]));
printf("network_speed : %d\n",network_speed=atoi(argv[3]));
printf("public : %d\n",pub=strcmp("private",argv[4]));
+ printf("col : %d\n",col=strcmp("nocol",argv[5]));
if (!zeRace_get_tracks(&tracklist)) exit(1);
fprintf(stderr,"SDLNet_AllocPacket: %s\n",SDLNet_GetError());
exit(2);
}
-
+
+ zeRace_generate_cars();
+
for (;;)
{
/* announce the server on internet if wanted */
/* look for type of message */
tmp=packet->data;
- /*printf("%s\n",tmp);*/
/* new connection ? */
if (strcmp(tmp,"connect")==0)
}
else
{
- int temp;
+ int temp,x,y,x2,y2;
tmp+=strlen(tmp)+1;
temp=SDLNet_Read32(tmp);
tmp+=4;
+ x=SDLNet_Read32(tmp);
+ tmp+=4;
+ y=SDLNet_Read32(tmp);
+ tmp+=4;
if (clients[id].lasttime<=temp)
{
tmp+=temp-clients[id].lasttime;
- /* printf("servertime = %d lasttime = %d temp = %d strlen(tmp) = %d\n",time,clients[id].lasttime,temp,strlen(tmp)); */
- /*printf("keys = %s\n",tmp);*/
while (*tmp)
{
move_car(&clients[id].car,*tmp-'A',fun);
- /*printf("%d = %f\n",id,clients[id].car.angle);*/
clients[id].lasttime++;
tmp++;
}
+ /* check that the server and the client are still synchronized */
+ x2=clients[id].car.x;
+ y2=clients[id].car.y;
+ if (x!=x2 || y!=y2)
+ {
+ int round;
+ /* this should not happen with a perfect network protocol :) */
+ printf("client %d unsync at %d\n",id,time);
+ /* instead of dropping the client, we send him a "dumb" collision to resync him */
+ tmp=packet->data;
+ strcpy(tmp,"collision");
+ tmp+=strlen(tmp)+1;
+ SDLNet_Write32(time,tmp);
+ tmp+=4;
+ round=(clients[id].car.x+100)*65536;
+ clients[id].car.x=(float)round/65536-100;
+ SDLNet_Write32(round,tmp);
+ tmp+=4;
+ round=(clients[id].car.y+100)*65536;
+ clients[id].car.y=(float)round/65536-100;
+ SDLNet_Write32(round,tmp);
+ tmp+=4;
+ round=(clients[id].car.speed+100)*65536;
+ clients[id].car.speed=(float)round/65536-100;
+ SDLNet_Write32(round,tmp);
+ tmp+=4;
+ round=(clients[id].car.angle+100)*65536;
+ clients[id].car.angle=(float)round/65536-100;
+ SDLNet_Write32(round,tmp);
+ tmp+=4;
+ packet->len=(void *)tmp-(void *)packet->data;
+ packet->address=clients[id].address;
+ SDLNet_UDP_Send(udpsock,-1,packet);
+ clients[id].lasttime=time;
+ }
}
}
}
clients[i].connected=0;
}
+ /* should we check for collisions ? */
+ if (col)
+ {
+ /* check for collisions */
+ for (i=0;i<MAX_CLIENTS;i++) clients[i].dx=clients[i].dy=0;
+ for (i=0;i<MAX_CLIENTS;i++) if (clients[i].connected)
+ for (j=i+1;j<MAX_CLIENTS;j++) if (clients[j].connected)
+ if (i!=j)
+ if (abs(clients[i].car.x-clients[j].car.x)<30 && abs(clients[i].car.y-clients[j].car.y)<30)
+ {
+ int x1,y1,x2,y2;
+ for (x1=0;x1<30;x1++)
+ for (y1=0;y1<30;y1++)
+ if (getpixel(cars[(unsigned char)(256*clients[i].car.angle/2.0/M_PI)%256],x1,y1)!=0)
+ {
+ x2=x1+clients[i].car.x-clients[j].car.x;
+ y2=y1+clients[i].car.y-clients[j].car.y;
+ if (x2>0 && x2<30 && y2>0 && y2<30)
+ {
+ if (getpixel(cars[(unsigned char)(256*clients[j].car.angle/2.0/M_PI)%256],x2,y2)!=0)
+ {
+ if (x1<30/2) { clients[i].dx++; clients[j].dx--; } else { clients[i].dx--; clients[j].dx++; }
+ if (y1<30/2) { clients[i].dy++; clients[j].dy--; } else { clients[i].dy--; clients[j].dy++; }
+ }
+ }
+ }
+ }
+
+ /* now compute the collisions */
+ for (i=0;i<MAX_CLIENTS;i++) if (clients[i].connected) if (clients[i].dx || clients[i].dy)
+ {
+ Uint32 c;
+ Uint8 g,t;
+ int dx=clients[i].dx;
+ int dy=clients[i].dy;
+ /* do not jump to much */
+ while (abs(dx)>5) dx/=2;
+ while (abs(dy)>5) dy/=2;
+ /* get the pixel color under the center of car in the function map */
+ c=getpixel(fun,clients[i].car.x+dx,clients[i].car.y+dy);
+ /* green layer (road quality) */
+ SDL_GetRGB(c,fun->format,&t,&g,&t);
+ /* if the destination is not a wall and not outside of the track */
+ if (g!=0 && clients[i].car.x>cars[0]->w && clients[i].car.x<fun->w-cars[0]->w && clients[i].car.y>cars[0]->h && clients[i].car.y<fun->h-cars[0]->h)
+ {
+ int round;
+ clients[i].car.x+=dx;
+ clients[i].car.y+=dy;
+ tmp=packet->data;
+ strcpy(tmp,"collision");
+ tmp+=strlen(tmp)+1;
+ SDLNet_Write32(time,tmp);
+ tmp+=4;
+ round=(clients[i].car.x+100)*65536;
+ clients[i].car.x=(float)round/65536-100;
+ SDLNet_Write32(round,tmp);
+ tmp+=4;
+ round=(clients[i].car.y+100)*65536;
+ clients[i].car.y=(float)round/65536-100;
+ SDLNet_Write32(round,tmp);
+ tmp+=4;
+ round=(clients[i].car.speed+100)*65536;
+ clients[i].car.speed=(float)round/65536-100;
+ SDLNet_Write32(round,tmp);
+ tmp+=4;
+ round=(clients[i].car.angle+100)*65536;
+ clients[i].car.angle=(float)round/65536-100;
+ SDLNet_Write32(round,tmp);
+ tmp+=4;
+ packet->len=(void *)tmp-(void *)packet->data;
+ packet->address=clients[i].address;
+ SDLNet_UDP_Send(udpsock,-1,packet);
+ clients[i].lasttime=time;
+ }
+ }
+ }
+
/* send update to clients */
if (time%network_speed==0) for (i=0;i<MAX_CLIENTS;i++) if (clients[i].connected)
{
tmp+=2;
SDLNet_Write16(clients[j].car.color,tmp);
tmp+=2;
+ SDLNet_Write16(clients[j].car.lights_brake,tmp);
+ tmp+=2;
+ SDLNet_Write16(clients[j].car.lights_backwards,tmp);
+ tmp+=2;
+ SDLNet_Write16(clients[j].car.lights_warning,tmp);
+ tmp+=2;
nb++;
}
SDLNet_Write16(nb,packet->data+strlen("positions")+1+4+4);
}
/* did someone finish the track ? */
+ for (i=0;i<MAX_CLIENTS;i++) { if (clients[i].car.lapflag==1) printf("client %d : %d laps\n",i,clients[i].car.lap); clients[i].car.lapflag=0; }
for (i=0;i<MAX_CLIENTS;i++) if (clients[i].connected && clients[i].car.lap==nb_laps) finish=1;
if (finish) break;