Tutorial: moving sunnyboys ========================== Multiplayer program, where every player moves his own sunnyboy with arrow keys. Up to 4 players are can connect, virtual players replace missing players. step 0 The global declaration of the program in tut-network1.h, used by master player and client players: We declare the network ports: ==>
static char serverport[]="2222"; // port of network-server static char mbcastport[]="2223"; // broadcast/multicast port to get server-ip |
struct { /* player's values */ bitmap * sunboy; /* players sunnyboy */ int xpos,ypos; /* position of sunnyboy */ int keyno,keycount; /* only for virtual player's moving algorithmus */ /* network pointers */ unsigned short * n_xypos; /* pointer to network-x/y-position */ } pl_data[NW_MAXCLIENT]; |
static int set_variables() { memset(pl_data,0,sizeof(pl_data)); /* define network variables: pl_data[].n_xypos[0] */ if (vg_nw_setvar(NWVAR_USHORT,1,"xypos") < 1) {return(-1);} return(0); } /* end set_variables */ |
static int get_pointers(int number_of_pl) { /* 1.arg: total number of players */ int i1; /* selection of colors for sunnyboys */ int sunny_color[8]={CL_RED, CL_YELLOW, CL_GREEN, CL_BLUE, CL_VIOLET, CL_PINK, CL_ORANGE, CL_TURQUOISE}; memset(pl_data,0,sizeof(pl_data)); /* get network pointers */ for (i1=1; i1 <= number_of_pl; i1++) { // for each player pl_data[i1-1].n_xypos=(unsigned short *)vg_nw_getvar("xypos",i1); /* create sunnyboy of player */ pl_data[i1-1].sunboy=create_sunnyboy(vg_color_index(sunny_color[(i1-1)%8],100)); if (pl_data[i1-1].sunboy==NULL) {return(-1);} } return(0); } /* end get_pointers */ |
/* +++ start networking +++ */ /* set network variables */ if (set_variables() < 0) {vg_window_close(); exit(1);} /* start network-server and connect to it, ** pass the number of players we want to have */ if (start_server(nop_from,nop_to) < 0) {vg_window_close(); exit(1);} /* get network pointers and create sunnyboys */ if (get_pointers(vg_nw_maxplayer()) < 0) {vg_nw_close(); vg_window_close(); exit(1);} /* initialize values for network pointers */ init_values(vg_nw_maxplayer()); /* send initial packet to clients */ vg_nw_sendinit(); |
static int start_server(int nop_from,int nop_to) { /* start and make connection to server ** 1.+2.arg: number of players: at least and at most */ if (vg_nw_setplayer(nop_from,nop_to) < nop_from) {return(-1);} /* start network-server ** using UDP, ** timeout for connects 20 sec., ** IPv4, ** timeout for not receiving any packet 30 sec. */ if (vg_nw_startserver(PROTO_UDP,serverport,20,4,mbcastport,30) < 0) {return(-1);} /* wait for all other connects */ if (vg_nw_waitforconnects() < 0) {vg_nw_close(); return(-1);} return(0); } /* end start_server */ |
static void init_values(int number_of_pl) { /* master: set initial values for all players ** 1.arg: total number of players */ int i1; /* set values for players */ for (i1=1; i1 <= number_of_pl; i1++) { /* set initial x- and y-position */ pl_data[i1-1].xpos=SC_WIDTH/2; pl_data[i1-1].ypos=SC_HEIGHT/2; /* set network variable: n_xypos[0]=ypos*SC_WIDTH+xpos */ pl_data[i1-1].n_xypos[0]=(unsigned short)(pl_data[i1-1].ypos*SC_WIDTH+pl_data[i1-1].xpos); } } /* end init_values */ |
/* +++ start networking +++ */ /* set network variables */ if (set_variables() < 0) {vg_window_close(); exit(1);} /* connect to network-server */ if (connect_server() < 0) {vg_window_close(); exit(1);} /* get network pointers and create sunnyboys */ if (get_pointers(vg_nw_maxplayer()) < 0) {vg_nw_close(); vg_window_close(); exit(1);} /* receive initial packet from master */ if (vg_nw_recvinit() < 0) {vg_nw_close(); vg_window_close(); exit(1);} |
static int connect_server() { /* connect to network-server via broadcast/multicast */ if (vg_nw_connect(PROTO_UDP,NULL,serverport,mbcastport) < 0) {return(-1);} /* wait for all other connects */ if (vg_nw_waitforconnects() < 0) {vg_nw_close(); return(-1);} return(0); } /* end connect_server */ |
/* go through all players */ for (plno=1; plno <= vg_nw_maxplayer(); plno++) { /* get keystrokes and set pl_data[] */ rval=getkeys(plno); if (rval < 0) {break;} /* network closed or end of game requested */ /* draw sunnyboy, if it is alive */ if (vg_nw_isalive(plno)) { /* player is alive */ vg_bitmap_copyto(NULL,pl_data[plno-1].xpos,pl_data[plno-1].ypos,pl_data[plno-1].sunboy,0,0,0,0,RGB_TRANS); } else if (plno==vg_nw_myplayer()) { /* master is dead, draw it rotated */ vg_bitmap_copyto(NULL,pl_data[plno-1].xpos,pl_data[plno-1].ypos,vg_bitmap_rotate(pl_data[plno-1].sunboy,180),0,0,0,0,RGB_TRANS); } } // end for each player |
static int getkeys(int plno) { /* get keystrokes (from keyboard or network or via an algorithm) ** and set pl_data[] (moving sunnyboy) ** 1.arg: number of a player ** return: 0=OK ** -1=end of game requested or network closed */ if (vg_nw_isalive(plno)) { /* player is alive */ int x,y; /* get sunnyboys moving request */ x=y=0; if (plno==vg_nw_myplayer()) { /* your sunnyboy, move with keystrokes */ if (vg_key_update() < 0) {return(-1);} /* network closed */ if (vg_key_pressed(KEY_SPACE,SHORTKEY)) { // quit with space-key vg_nw_setdead(plno); // set dead to inform network-server return(0); // do not end the game (wait for the second keystroke) } /* save request values in x,y */ if (vg_key_pressed(KEY_DCURS,LONGKEY)) {y=1;} /* down */ if (vg_key_pressed(KEY_UCURS,LONGKEY)) {y=-1;} /* up */ if (vg_key_pressed(KEY_LCURS,LONGKEY)) {x=-1;} /* left */ if (vg_key_pressed(KEY_RCURS,LONGKEY)) {x=1;} /* right */ } else if (plno >= vg_nw_virtualplayer()) { /* virtual players, move with a simple algorithmus */ if (pl_data[plno-1].keycount==0) { pl_data[plno-1].keyno=ZUFALL(4); /* which arrow key */ pl_data[plno-1].keycount=ZUFALL(25)+5; /* how long pressed */ } pl_data[plno-1].keycount--; /* save request values in x,y */ switch (pl_data[plno-1].keyno) { case 0: y=1; break; case 1: y=-1; break; case 2: x=-1; break; case 3: x=1; break; } } else { /* sunnyboys of other clients, save request values in x,y */ if (vg_nw_recvkeys(plno)) { /* client has sent a request */ if (vg_nw_keypressed(KEY_DCURS,LONGKEY)) {y=1;} /* down */ if (vg_nw_keypressed(KEY_UCURS,LONGKEY)) {y=-1;} /* up */ if (vg_nw_keypressed(KEY_LCURS,LONGKEY)) {x=-1;} /* left */ if (vg_nw_keypressed(KEY_RCURS,LONGKEY)) {x=1;} /* right */ } } /* now really move sunnyboy, checking boundaries before */ if (y==1) { /* down request */ int bound=SC_HEIGHT-vg_bitmap_height(pl_data[plno-1].sunboy)/2; if (++pl_data[plno-1].ypos > bound) { pl_data[plno-1].ypos=bound; pl_data[plno-1].keycount=0; } } else if (y==-1) { /* up request */ int bound=vg_bitmap_height(pl_data[plno-1].sunboy)/2; if (--pl_data[plno-1].ypos < bound) { pl_data[plno-1].ypos=bound; pl_data[plno-1].keycount=0; } } if (x==-1) { /* left request */ int bound=vg_bitmap_width(pl_data[plno-1].sunboy)/2; if (--pl_data[plno-1].xpos < bound) { pl_data[plno-1].xpos=bound; pl_data[plno-1].keycount=0; } } else if (x==1) { /* right request */ int bound=SC_WIDTH-vg_bitmap_width(pl_data[plno-1].sunboy)/2; if (++pl_data[plno-1].xpos > bound) { pl_data[plno-1].xpos=bound; pl_data[plno-1].keycount=0; } } /* update values of network pointers and send data */ pl_data[plno-1].n_xypos[0]=(unsigned short)(pl_data[plno-1].ypos*SC_WIDTH+pl_data[plno-1].xpos); vg_nw_senddata(plno); } else { /* player is not alive */ if (plno==vg_nw_myplayer()) { /* your sunnyboy */ if (vg_key_update() < 0) {return(-1);} /* network closed */ if (vg_key_pressed(KEY_SPACE,SHORTKEY)) { // quit with space-key return(-1); } } } return(0); } /* end getkeys */ |
// get keystrokes and do network-transfer if (vg_key_update() < 0) {break;} // network closed if (vg_key_pressed(KEY_SPACE,SHORTKEY)) { // player wants to quit vg_nw_setdead(vg_nw_myplayer()); break; } /* get sunnyboys position, decompressing value of network-variable n_xypos */ for (plno=1; plno <= vg_nw_maxplayer(); plno++) { pl_data[plno-1].xpos=pl_data[plno-1].n_xypos[0]%SC_WIDTH; pl_data[plno-1].ypos=pl_data[plno-1].n_xypos[0]/SC_WIDTH; } /* go through all players */ for (plno=1; plno <= vg_nw_maxplayer(); plno++) { /* draw sunnyboy, if it is alive */ if (vg_nw_isalive(plno)) { /* player is alive */ vg_bitmap_copyto(NULL,pl_data[plno-1].xpos,pl_data[plno-1].ypos,pl_data[plno-1].sunboy,0,0,0,0,RGB_TRANS); } } // end for each player |