Jump to content
  • Advertisement

Archived

This topic is now archived and is closed to further replies.

Memir

How do you keep a game in sync? (multiplayer)

This topic is 5613 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I''ve got a problem that has been plaguing my Online Snooker (Pool) game ever since I''ve begun six months ago... When people play online and take shots, sometimes one of the players/watchers in the table experiences a different outcome. We''ve been thru the code and combed out all the bugs that could cause an incorrect simulation. Eventually, we found out that when you do simple floating point calculations e.g. y = a+b; Certain computers calculate the result ever-so slightly differently. e.g. 5*5 = 25.000000 on one person''s processor, and on another''s 5*5 = 25.0000001. Now that small difference becomes bigger and bigger, eventually resulting in one player seeing the balls in different positions. Our current solution is to update all the balls'' positions at the end of each shot. That solves the problem of players going out of sync and staying out of sync. However, it also causes people to say "Hey this game has bugs, cause the balls are moving after the shot has been completed". What I want to know is is there a way to use floating point math without causing this problem? Is there any ''Emulation'' mode floating point that I can use which gaurantees that all players across the world, regardless of CPU/FPU/Hardware/OS will carry out floating point calcs the EXACT same way. The only other solution I can think of is changing the ***WHOLE*** thing over to fixed point, and thats gonna be a mission. Especially figuring out how to convert the 4x4 Matrix calcuations, 3D ball/table detections etc. over to Fixed point. There''s gotta be an easy way out? Anyway, if you''re curious to see what my Snooker game looks like click the following url & download, you can play as a guest for free: TheSnookerClub /Memir

Share this post


Link to post
Share on other sites
Advertisement
hm...thats weird. how can 5*5 = 25.000000000001? anyways, the best answer i can give you (i have virtually no idea of networking) is to keep original values so as to keep the effects of erroneous values from adding up... sorry for lame answer but its the best i can give you...


Check out our website!
Clicky!

I am Ciph, and that is what I am

Share this post


Link to post
Share on other sites
What about having one computer designated as server and one as client.. and one does the calculations and sends the results to the other.. or perhaps they alternate?

Share this post


Link to post
Share on other sites
Problem is... this is a Snooker game, i.e. like Yahoo Pool! ...

Means there are a lot of balls that collide into eachother when someone breaks & smashes the pack. Not only does the person taking the shot see what''s going on live, but his/her opponent and all the people watching in the game see this live.
Now I''m not gonna send over the coordinates of 20-odd balls * float(X,Y,Z) * 60*say 5 seconds (20*12*300 bytes) to all the players watching me take a shot! - At present I only send over the strike vector and target ball, aswell as a 32-bit CRC value of the current table state (present ball coordinates) - i.e. to detect out of syncs.

I read an article on Gamasutra about Reproducibility, by Peter Lindcroft (dude who helped develop X-Wing vs TIE Fighter). His answer was the easy "Just use fixed point math" OR "Do a complete update every now and then".

Looks like no one knows how to "beat the float" head on.

If the game was a simple Snooker/Pool game like the rest of the online games, then I would''ve just coded it all fixed point (especially if I knew that floats+networking doesn''t mix), but this game has a lot of complex vector & matrix calculations as we tried to make it as realistic as possible.

I guess I''ll have to just go over the code line by line, function by function changing it.

/Memir

Share this post


Link to post
Share on other sites
Just do the shots like you normally do, then at the end of the turn, sync all the ball positions to that of one computer. If you do this every turn, the balls will only move minutely after the turn is done.

This will avoid having to send constant details about the motion of the balls, and it will keep the game in-sync.

Share this post


Link to post
Share on other sites
I suspect a bigger problem is timing differences between computers. Would a different frame rate result in different collision results or different integration results (because the time-step is different)? If so, then fixed-point won''t make a difference.

Share this post


Link to post
Share on other sites
glassJAw: That''s what we do already! - The thing about this problem is that it doesn''t always come out, it''s pretty rare, and most times when it does come out, it only causes the balls to move a little at the end of the shot. But sometimes, you can clearly see that the balls have move a lot. It really depends on the shot, and how the balls interact with eachother. So when someone smashes the pack, theres lots of ball collisions, meaning a small error can quickly propagate up, and become quite noticable.

JohnBolton: The timing differences doesn''t matter in this game, coz it''s like a "You take a turn, Then I''ll take a turn" game. And everyone waits until everyone has completed the simulation of the shot.

At one point a few months ago, we did find a solution to the floating point problem, and that was to simplify the operations.

e.g. instead of having y = (a+b)*c;
we would do y = a;
then y+=b;
then y*=c;

and somehow doing this made all math processsors (FPU) produce the same result.

I think it has something to do with the fact that the FPU does calculations at 80bit. and these values are stored as 32bit floats.
so when you''re doing:

1) y= (a+b)*c [32bit = FPU((a+b)*c)]
2) y= a; [32bit = CPU(a)]
y+=b; [32bit+= CPU(b)]
y*=c; [32bit*= CPU(c)]
Basically I think the compiler realises that a complex one liner, will be calculated faster by converting the 32-bit floats into 80bit FPU values, then calcuated by the FPU, then converted back into 32-bit floats.
Whereas simple operations on seperate lines, can be evaluated faster just using the CPU''s own math processor, rather than converting the 32bit values into 80bit then firing up the FPU then converting back to 32bit.

It''s a small problem in my game, not one of the high priorities, as it doesn''t happen that often, and when it does, it usually only happens to one person in the game. But nevertheless I''d like to get rid of it completely, without having to just avoid floats.

/Memir

Share this post


Link to post
Share on other sites
quote:
Original post by Memir

JohnBolton: The timing differences doesn't matter in this game, coz it's like a "You take a turn, Then I'll take a turn" game. And everyone waits until everyone has completed the simulation of the shot.



Hmmm, that sounds extremly strange I think that timing does not affect the movement... Unless you use frame dependent animation, the timing will of course affect the movments, even if you have a turned based game. That it is turned based has nothing to do with it.

However, maybe I have misunderstood something here, but the fact that one computer might calc a collision 3 times over 60 ms (1 time each 20 ms) and another 2 times over 60 ms (1 time each 30 ms) will of course affect all the calculations due to round offs. Of course, in general, a ball that moves from A to B with a certain speed and direction and acceleration/deacceleration will move from A and end up in B even if the ball moves in 2 steps or 3 steps over 60 ms... However, in your case where you have a lot of floats you will get a lot of round offs and those round off will differ if you use 1, 2, 3, 4....n steps and will in the end cause different results. So timing is for sure an issue here I think.

However, is you lock your framerate to for example 30 FPS and do calcs each frame then all should be in sync. But I assume you to calculations based on time that has passed and then you will be affected by the above facts.




[edited by - calvincoder on July 27, 2003 8:37:14 AM]

Share this post


Link to post
Share on other sites
Try using doubles instead of floats.

If push comes to shove do all the ball calculations in assembly using the highest precision registers and the least amount of conversions.

------------
- outRider -

Share this post


Link to post
Share on other sites
What I can suggest is to have one computer designated as the computational master doing all of the floating point math ahead of time and to then relay that information to the other computers.

Besides that, I can say you could try using doubles (you might end up with the same problem). However, if you check regularly to make sure the game is in sync then at most the balls would move like a single pixel. It shouldn''t be detected by the human eye.

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!