ODE and multiplayer

Blitz3D Forums/Blitz3D Programming/ODE and multiplayer

Jeroen(Posted 2005) [#1]
Hi there!

I am thinking to make a new game that will be multiplayer and use ODE for physics and collisions. But, I have some questions on that.

In my previous multiplayer game, I simply sent the local player coordinates to all the other players. On their computers, it was simply a matter of receiving the coordinates and placing the entity using positionEntity (absolute).

But, now with physics, there's a problem. When player A hits player B, it will cause a reaction, for example they will bounce.

In theory, only one computer will actually need to perform physics and send coordinates, right? Or...I really don't have an idea what happens when all clients run physics and what I need to send through the network.

How am I going to implement a right way to do this?
How is this usually done? Sending absolute coordinates and positioning entities here...it feels just wrong, somehow.

Thanks!


Damien Sturdy(Posted 2005) [#2]

In theory, only one computer will actually need to perform physics and send coordinates, right?



Depends how you do it.

I prefer to distribute the power between machines, though this gives an opening for cheaters....


How i did it:

Send position and rotation, plus velocities...
You will have to consider Lag-
I've done a Lag system where i tell the program how many frames each computer can fall behind- and the server waits for everyone to be on the same frame, or within that lag value, before continuing.

To be honest, This works really well over LAN... And its playable over the internet but sometimes you get flung really hard- And physics dont work really well unless synchronised...


IPete2(Posted 2005) [#3]
Can I ask a stupid question???

If the ODE physics engine is active on all players machines, and co-ordinates for initial positions and rotations and velocities are sent, why not just let each players programme run their own physics on the local pc vehicles?

Would this be a disaster? What are the consequences of allowing each local PC determine the outcomes of collisions etc?

Perhaps on collision then the position, rotation, velocity etc are sent to allow everyone to have the same data before attempting the physics reactions?

Would this be too slow? Would lag have too great an effect on everyone?

IPete2.

Just realised that is more than one question, sorry! Lol!


KuRiX(Posted 2005) [#4]
Ok, i will give you a solution. It is called the Dead Reckoning Algorithm. I have implemented it in my Racing Game and is working very good over internet. The only problem with this method is the lag fluctuation.

Dead Reckoning:

- Each computer runs all the simulation.
- Every certain time, all the positions, rotations, linear velocities and angular velocities are broadcasted over the net. Then, if the received values are over some limit (this means that the difference between last pos and actual pos is greater than the limit), then all the values are updated.
- The rest of the time all the computers run their own simulation.

I have adapted this making a matrix of inputs. So each computer knows its ping time. During this ping time the computer saves all the input of the player in a vector, and then sends this vector to the rest of the computers. Then the computers update the remote players with that update.

The matrix of inputs has the advantage of giving very smooth results, but has the disadvantage of positioning players later than they should be, and it is very affected by collisions.

Well, hope this helps. Good Luck.
Cheers, KuRi.


Damien Sturdy(Posted 2005) [#5]
I can confirm this works by the way- I played with it.
However, i chose not to use it because i liked the idea of "more computers=shared power, Less CPU usage per computer"

You simply wont avoid lag. Over the internet, I'd probably use Kurix solution. Over lan, i find mine works well.

Oh, and dont forget to convert everything to floats/bytes before sending over the network :P then recompose the values at the other end.

EG:

A wheel is parented to the car body.... so you can get its local x/y/z coords... Now, usually, you could store the wheel locations LOCAL positions say... in a byte, by dividing the actual local position... so say, 0 means -1 and 256 means 1.... So you can send each wheel's coordinate in 3 bytes....

Usually, this will do fine, but it can give odd results because of its inacuracy with positioning.

you cant really use this with rotation- you can tell when youre not using floats :P so use FloatToStr :)
(Actually, the rotation of a wheel can be done using bytes- because theyre small)


So, just optimise... I hope you understand what i wrote... hehe...


KuRiX(Posted 2005) [#6]
Yes, of course you should use bytes as Cygnus says.

For example, for rotations using quaternions:

qx = dBodyGetQuaternionX(body) / 1000.0

Then you send qx as a byte, because this value will be always in the [-1,1] range!

OR something like that...


Damien Sturdy(Posted 2005) [#7]
I'll just emphasize on the fact that you cant use bytes to position objects globaly...

Reason i may seem like im stating the obvious is that Network Debugging is horrendous, and if you do something like this without thinking.....!

Have fun :)


Picklesworth(Posted 2005) [#8]
Counter-Strike Source has the physics calculated individually on every computer, which saves a lot of bandwidth and nobody really notices unless they're telepathic (or discussing the weird position of a person's dead body). Mind you, the physics in that game aren't much more than ragdolls...

Maybe a player only sends out physics information if they have done something to cause it?

I think KuRiX and Cygnus have the best suggestions so far.


KuRiX(Posted 2005) [#9]
Cygnus, we would make a good team programming racing games hehe :D

Of course, i was talking about global rotations, not positions.


Damien Sturdy(Posted 2005) [#10]
Indeed we would!, and i would worry about why you would use Quartonians to position something :D hehe.


Jeroen(Posted 2005) [#11]
Okay those are really nice solutions! Especially when a game concept involves physics (not CS:Source just using it for rag dolls) it is important to find some kind of system.

I am curious about this:


- Every certain time, all the positions, rotations, linear velocities and angular velocities are broadcasted over the net. Then, if the received values are over some limit (this means that the difference between last pos and actual pos is greater than the limit), then all the values are updated.


How are you going to determin a good limit? What if physics can do lots of weird things (low and high values)?


KuRiX(Posted 2005) [#12]
Hehe, nice question. In my racing game, the limit is small enough to give smooth solutions, but greater than the minimum movement at slow speed (gear 1).

The best is to make some tests...


Tibit(Posted 2005) [#13]
Depending on how advanced you want to make it you could let the server be in charge still let the client do some work like this:

This is the Unreal Model in short:
Client Send --> Server
Client continues to update physics..
Server get msg from Client.
Server checks the time the packet took to arrive. (Your Ping). The message contained position and acceleration. The server predicts where the client should be.
Server Send --> Client with this prediction.
Server sends this prediction to all other players too.
Client receives MSG and checks the time the packet took to arrive. The Client then steps back in time (you need to save some previous data) to where the prediction was. The client now sets the location of this server packet and now steps forward in time with the latency of the message. In this way all clients see the other clients closer to their true positions


A more simple approach would be to send player input (which keys he is holding down) and updating the physics at all clients. To make sure you don't get out-of-sync you need to (once in a while) send Full updates with X,Y,Dir. A good way is also to send more updates when a collision occur. Also when you apply updates you should consider the delay the packet took.

To get the time for a packet I would recommend you to Sync-clocks


Jeroen(Posted 2005) [#14]
Hi Wave,

That sound like a great way to do it! I think I'll try this approach. Thanks.