3D Rad - Free 3D game maker - Forum

This forum is now archived!

This forum is locked, and is a read-only version. A new community-ran forum can be found at classdev.net

News:

The 3DRad community can be found at classdev.net.

Pages: [1]

Author Topic: A Network drivable car ~ Based on the scripted driver  (Read 1783 times)

jestermon

« on: January 25, 2011, 04:16:25 PM »
I finally got around to placing the scripted driver into a network car.
This car can be driven either on the server, or on the client.

You will not be able to drive the car on the client without the server running, since it actually does nothing, but mimic the location and orientation of the car on the server. The client uses iObjectPositionReset to place a 3d Rad car, and not a skinmesh, just to make things a little more interesting

Compile both the server and the client projects, in order to test them properly. A project that runs in the editor "freeze" and will not be responsive if it loses mouse focus. Run the projects windowed, since you wont be able to see both client and server views if one of them is run in full screen (This may be an overstatement, but you never know what silly questions will pop of in this regard)

First start the server, and wait till it says "Server controlled car" at the bottom of the screen, indicating that the server is ready to accept client connections.

Next, start the client, and connect it to the server via the connection dialog.

Once both server and client are running, set focus to the server's window and drive the car. You will notice that the client mimics the server's car exactly.

Press the F2 key to change control to the client, and notice that you will not be able to drive the car from the server window, since it is actually expecting to be controlled from a client

Set focus to the client window, and drive the car from there. Notice that the wheels of the car on the client do not actually turn, yet the car actually turns. All that is happening is that the controls are sent to the server, and the real car is driven on  the server with the scripted driver, and the position of the car is then updated to the client

I had a few headaches using iNetArrays from the client to  the server, so instead send the control info via a string to the server, where it is parsed back into float values

These two projects should have enough information for anyone who wishes to develop network racing games, and should give the newbie a good place to start from, and show what kind of logic needs to be implemented

1.. Client input for control
2.. Send controls to server
3.. Receive conteols
4.. Control vehicle from remote input
5.. Get vehicle location and orientation
6.. Send car info to client
7.. Update client car from server info

Now perhaps we will start seeing some more real technical questions, from people who are really interested in making games, and are wiling to learn from the ground up .... and less of the "help - I don't know what to do" type.

SERVER
Code: [Select]
int CAR = OBJ_0;
int PRINT = OBJ_22;
float steeringAngleDelta=0.02;
float steeringAngle=0;
float steeringResetTimer=0;
string S,STATE;
bool SERVERPLAYER = true;
bool SERVERACTIVE = false;


///-------------------------------------------------------------------------
//array = split(string-to-split, split-on-this-character
string[] split(string s, string c)
{
   int p;
   string[] strList();
   int valve = 0;
   bool done = false;
   string s1,s2,s3;
   int Idx = 0;

   s3 = s;
   strList.resize(0); //clear the array
   while (!done)
   {
      valve++; if(valve == 1000) break; //while pressure valve
      p = iStringFind(s3,c,0,false); //find splitter
      if(p != -1)
      {
         iStringLeft(s1,s3,p-1); //get the 1st part
         iStringRight(s2,s3,iStringLen(s3)-p); //get the second part
         Idx = strList.length();
         Idx++;
         strList.resize(Idx);  //increase list size
         strList[Idx-1] = s1;  //stort string part in array
         s3 = s2;
      }
      else
      {
         if(iStringLen(s3) > 0)  //tail piece of the string
         {
            Idx++;
            strList.resize(Idx);
            strList[Idx-1] = s3;
            done = true;
         }
      }
   }
   return strList;
}

///-------------------------------------------------------------------------
void Main()
{
   Quaternion orientation;
   Vector3 location;
   int len=0;
   float acceleration;
   string driveString;
   string []msg();

   if(iInitializing()){                         //when script starts
      if(!SERVERACTIVE){                        //if the server is not active
         SERVERACTIVE = iNetServerStart(        //start server
                        "Network Driver Tester",//game name
                         "Test Server 00",      //server name
                         2111,                  //game port
                         0,                     //game number
                         100000);               //buffer length
      }
   }


   if (iKeyDown(iKeyCode("DIK_F1"))) SERVERPLAYER = true;
   if (iKeyDown(iKeyCode("DIK_F2"))) SERVERPLAYER = false;

   //Server controlled car input
   if(SERVERPLAYER){
      STATE = "Server controlled car";
      //Accelerate
      OUT_1 = 0;
      acceleration = 0;
      if (iKeyDown(iKeyCode("DIK_UP"))){
         OUT_1 = 1;
         acceleration = 1;
      }
      if (iKeyDown(iKeyCode("DIK_DOWN"))){
         OUT_1 = -1;
         acceleration = -1;
      }
      //steering
      steeringResetTimer++;
      if(steeringResetTimer > 1){
         steeringResetTimer = 0;
         if(steeringAngle > 0) steeringAngle -= steeringAngleDelta*4;
         if(steeringAngle < 0) steeringAngle += steeringAngleDelta*4;
      }
      if (iKeyDown(iKeyCode("DIK_LEFT"))){
         steeringAngle += steeringAngleDelta;
         if(steeringAngle > 1) steeringAngle = 1;
         steeringResetTimer = 0;
      }
      if (iKeyDown(iKeyCode("DIK_RIGHT"))){
         steeringAngle -= steeringAngleDelta;
         if(steeringAngle < -1) steeringAngle = -1;
         steeringResetTimer = 0;
      }
      OUT_0 = steeringAngle;
   }

   //Client controlled car
   len = iNetStringReceive(driveString);
   if(!SERVERPLAYER && SERVERACTIVE){
      STATE = "Client controlled car";
      if(len > 0){
         msg = split(driveString,";");
         acceleration = iStringVal(msg[0]);
         steeringAngle = iStringVal(msg[1]);
         OUT_1 = acceleration;              //set car acceleration
         OUT_0 = steeringAngle;             //set car steering
      }
   }

   if(SERVERACTIVE){
      //Send car info to all connected players
      iObjectLocation(CAR,location);         
      iObjectOrientation(CAR,orientation);
      iNetFloatArraySet(0,1);            //car ID, useful for multiple cars
      iNetFloatArraySet(1,location.x);   //car location values
      iNetFloatArraySet(2,location.y);
      iNetFloatArraySet(3,location.z);
      iNetFloatArraySet(4,orientation.x);//car orientation values
      iNetFloatArraySet(5,orientation.y);
      iNetFloatArraySet(6,orientation.z);
      iNetFloatArraySet(7,orientation.w);
      iNetFloatArraySet(8,IN_2);         //send steering angle as well
      iNetFloatArraySendEx(0,9,0,false);
   }


   //Cleanup
   if (iDeinitializing())
   {
      //De-activate the network
      if (SERVERACTIVE)
      {
         iNetStop();
         SERVERACTIVE = false;
      }
   }

   iPrint("CLIENT: "+len+" "+driveString,-14,-9,PRINT);
   iPrint(STATE,-14,-11,PRINT);
   iPrint(S=acceleration+"    "+steeringAngle,-14,-10,PRINT);
}



CLIENT
Code: [Select]
int CAR = OBJ_0;
int PRINT = OBJ_22;
float steeringAngleDelta=0.02;
float steeringAngle=0;
float steeringResetTimer=0;
string S;
bool CLIENTACTIVE = false;

///-------------------------------------------------------------------------
void Main()
{
   int numFloats;
   float steeringDegrees;
   Quaternion orientation;
   Vector3 location;

   if(iInitializing()){
      if(!CLIENTACTIVE){
         CLIENTACTIVE = iNetClientStart(
                        "127.0.0.1:2111",
                        "client 01",
                        0,    //game number
                        100000,
                        "Select Game",
                        -1,    //select a game
                        30);
      }
   }
   

   ///Get car acceleration
   float acceleration = 0;
   if (iKeyDown(iKeyCode("DIK_UP"))){
      acceleration = 1;
   }
   if (iKeyDown(iKeyCode("DIK_DOWN"))){
      acceleration = -1;
   }


   ///Get steering
   steeringResetTimer++;
   if(steeringResetTimer > 1){
      steeringResetTimer = 0;
      if(steeringAngle > 0) steeringAngle -= steeringAngleDelta*4;
      if(steeringAngle < 0) steeringAngle += steeringAngleDelta*4;
   }
   if (iKeyDown(iKeyCode("DIK_LEFT"))){
      steeringAngle += steeringAngleDelta;
      if(steeringAngle > 1) steeringAngle = 1;
      steeringResetTimer = 0;
   }
   if (iKeyDown(iKeyCode("DIK_RIGHT"))){
      steeringAngle -= steeringAngleDelta;
      if(steeringAngle < -1) steeringAngle = -1;
      steeringResetTimer = 0;
   }

   ///Update the car location and orientation from the server
   if(CLIENTACTIVE){
      numFloats = iNetFloatArrayReceive();
      if(numFloats == 9){
         //car ID (0) not used in this example
         location.x = iNetFloatArrayGet(1);
         location.y = iNetFloatArrayGet(2);
         location.z = iNetFloatArrayGet(3);
         orientation.x = iNetFloatArrayGet(4);
         orientation.y = iNetFloatArrayGet(5);
         orientation.z = iNetFloatArrayGet(6);
         orientation.w = iNetFloatArrayGet(7);
         steeringDegrees = iNetFloatArrayGet(8);
         iObjectPositionReset(CAR,orientation,location);
      }
   }

   ///Send acceleration and steering info to the server
   ///Sending as a string, since inetArray screws up from a client
   if(CLIENTACTIVE){
      S = acceleration+";"+steeringAngle;
      iNetStringSend(S,0,true);
   }

   ///Cleanup
   if(iDeinitializing()){
      if(CLIENTACTIVE){
         iNetStop();
      }
   }

   iPrint(S=acceleration+"    "+steeringAngle,-14,-10,PRINT);
}

« Reply #1 on: January 25, 2011, 04:54:59 PM »
Thanks J... this is a resource long over due.

One thing RAD has been missing is a car network resource like this.

I have don't have the knowledge of network stuff to develop something like this so it would have taken me months and a lots of frustration.

Again thanks

n_iron
« Reply #2 on: January 25, 2011, 05:35:20 PM »
this is really cool...

one thing i see though...  i don't think you need to update the car location to the clients...

RAD already does this for you... just sync the car mesh on the server to the ones on the client... it'll automatically be placed in the right position and orientation... you won't need a car on the client... just the meshes...


--Mike

jestermon

« Reply #3 on: January 25, 2011, 09:12:43 PM »
.  i don't think you need to update the car location to the clients...

Aware.. note I said "....just to make things a little more interesting"
« Reply #4 on: January 25, 2011, 11:36:30 PM »
And interesting it is, the whole lot.  ;D

Thank you for introducing me to another thing I am clueless about but certainly not without interest in.  As n_iron said, a resource long overdue.   :)
« Reply #5 on: January 26, 2011, 11:52:13 AM »
Quote
Aware.. note I said "....just to make things a little more interesting"

ahhhh... i see...

k...

--Mike

leon

« Reply #6 on: April 27, 2011, 03:41:18 PM »
 :o How did i miss this  ;D

cheers jestermon
« Reply #7 on: August 07, 2011, 01:09:46 PM »
I'm kind of new here so i don't understand what client driving does and what server driving?
« Last Edit: August 26, 2011, 01:59:54 AM by PlayDasher »
New 3DFoundry:3DFoundry.tk
Pages: [1]