6
\$\begingroup\$

I am trying to make a simple sync between two box2d rooms, where you can drag boxes using the mouse.

So every time player clicks (and holds the mousedown) a box, I try send joint parameters to server, and server sends them to other clients. When mouseup occurs, I send command to delete joint.

The problem is that sync breaks too often. Is my way radically wrong, or it just needs some tweaks?

http://www.youtube.com/watch?v=eTN2Gwj6_Lc

Source code https://github.com/agentcooper/Box2d-networking

\$\endgroup\$
2
  • \$\begingroup\$ I don't quite understand. How does it break? What happens? \$\endgroup\$
    – Nate
    Jun 3, 2011 at 14:36
  • \$\begingroup\$ I made a video :-) \$\endgroup\$ Jun 3, 2011 at 18:25

3 Answers 3

4
\$\begingroup\$

I think this is because of some parameters which differ in two computers, for example they are not computing your scene with same speed (their delta_time values are not same), and simulation result is based on them. you either have to sync all these parameters in 2 computers or everyonce in a while send a snapshot of your whole scene, to sync results. the later is much more easier to implement ( at least I think so), be the former has much less network load. you can combine both ideas somehow and increase the time between sending snapshots to take benefit from both. for the diffrence in delta_times I can suggest the following code :

void update(float delta_time)
{
    static float total_elapsed_time = 0;
    total_elapsed_time += delta_time;
    while (total_elapsed_time > 1.0/30)
    {
        total_elapsed_time -= 1.0/30;
        world.step(1.0/30,10,10);
        other_updates(1/30);
    }
}

in this code you are somehow syncing all the timers between two computers. of course you can change 1/30 or other parameters as you like but they should be same in both computers (and also they should be somthing logical not much less than actual processing power)

\$\endgroup\$
1
\$\begingroup\$

I think @Gajet is on the right track; the other thing I think you may be missing, is that the server should define the state. Events should be sent to the server, who does world calculations and then updates each client.

In other words, when a client clicks, it should send the data about that click to the server; the server then calculates where the box ends up, and sends that data to all clients. The client who actually performed the event can start "predicting" where the server is going to tell it to put the box.

Put a different way, each client should tell the server "the user just did X" at the moment it knows that X happened. Then, the server goes about figuring out what that means, and updates all of the clients. As soon as the client finishes telling the server about X, it starts moving the box and when it gets the update from the server, it adjusts the box from its own calculation to the calculation received from the server.

\$\endgroup\$
2
  • \$\begingroup\$ And how often should client check for updates from server? And I think I'm doing eveything like you said. Client starts dragging the box and sends all necessary data to server, which creates move on itself and then pushes updates to all the clients, so they move too... Well, thanks, I try to figure something out. Also added the source code. \$\endgroup\$ Jun 3, 2011 at 19:00
  • \$\begingroup\$ As @Gajet said, sometimes you'll need to send the entire state in order to re-sync, though if you are only sending the actual position of each object when it changes, you shouldn't get that out of sync. Someone with more experience on network code could probably elaborate more on this. \$\endgroup\$
    – Nate
    Jun 3, 2011 at 19:23
0
\$\begingroup\$

What I did for this same problem, javascript implementation Box2D networked system was to create a system in which the players send inputs to the server, and the server is the one running the simulation and sends world-updates to all players at discrete intervals.

Repository:
https://github.com/onedayitwillmake/RealtimeMultiplayerNodeJs

You can see the box2d demo of this here:
http://vimeo.com/24149718

\$\endgroup\$
3
  • \$\begingroup\$ So, when I want to drag a box, I need to send all neccesary data to server, make according joint there, but then make server send only positions to clients, without making actual joints on clients? Now I have network logic almost like this, but i do make joints on the clients, and server pushes position updates every second. Better, but still a little bit buggy youtube.com/watch?v=utQsgDgI5eU \$\endgroup\$ Jun 4, 2011 at 14:54
  • \$\begingroup\$ Looks like it's coming along. What I did for an implementation of this is create a server side version of each client. The client sends MouseDown / MouseMove / MouseUp then I just handle everything on the server creating the joints or etc. I found this way of doing it useful, that way on the server side I actually just code it as if it was working locally. I have a version of this here, although it is in cpp you get the idea: github.com/onedayitwillmake/CinderBox2dOSC/tree/master/src \$\endgroup\$ Jun 4, 2011 at 19:36
  • \$\begingroup\$ @spacevillain : The joint should definitely exist on the client. The joint's basic properties should be synched as well, and you will need to synch more than just position. You need to synch linear and angular velocity, and you also need to wake everything up. But, to give you a better idea of what's going on, for now, don't run the simulation on the client side at all. Just run it server side. Once that works, you can use Box2D client side to do prediction. \$\endgroup\$
    – Blecki
    Jun 5, 2011 at 2:26

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .