Saturday, November 25, 2006

Movement Replication Completed

The idea has proven to be good.

Now, any time a vehicle moves (by player or by environment, etc.) the event of that movement is sent to the rest of the players. Those other clients receive a message, read where that vehicle must be, and let the robot handle the operation of the vehicle to achieve the desired position and rotation.

According to my tests, it definitely overcomes lag. The worst case scenario is when an event comes in rather late (lag). The vehicle does lag behind the actual location on the originating client, but the robot does move the vehicle to the desired location and rotation. So, this works great.

I have also implemented accuracy setting. Movement updates are sent every time current position is P units far away from the last sent position, or the rotation is R degrees different from the last rotation sent. Currently, this pair of values (P,R) is (1,5), where P=1 means 1/6 of the vehicle's length.

These values have direct affect on two things. One is the accuracy of replication across the network. Another is how much trouble the robot has to go through to achieve the desired position and rotation.

This last issue can be a problem at low values of P and R. The reason is that vehicle does not turn on a dime, instead its turning mechanism (4 wheels on one side, 4 more on another side) has an error, so the rotation causes the tank to move away from its original position. This means that vehicle gets too far from the desired position (more than P units), and now it must first get back into the position, before continuing to turn. You can now imagine that at low values, this turning error will cause the robot to really struggle to get the vehicle into the position. And that is what it did in my tests.

While the above is not a problem, since I intend to keep values of P and R high, it is an indication that turning mechanism of the tank must be improved. One possible solution is to alter the power of both sides (set of 4 wheels) in order to achieve equal turning power, kind of like ABS for vehicles, which alters the power of the breaks on the wheels to prevent loss of contact with the ground. This is, however, is rather complex, so if I do decide to do it, it won't be soon.

Sunday, November 19, 2006

Improving Movement Replication

By far, the most important events to copy across clients are the movements of the vehicles. In my current implementation, I simply send events that describe what command a player pressed: forward, backward, turn left or right, etc. This works, however, there are two problems that create large difference between clients.

One is lag. Events do not reach other clients right away, so all commands are executed later than they are actually started on the original client. So, this leads to some differences. However, this difference is not that big. The main problem comes from the second problem.

Physical simulations do not run the same way on different computers. This means that if a vehicle turns to the left for one second on computer A, the vehicle may turn 40 degrees, while on computer B it will turn 35 or 45 degrees. This causes large differences very quickly.

So, another solution is required. One roadblock is the way my vehicles move. Their movement is produced by a complex interaction of bodies, joints, and motors. So, I cannot do what many other simpler games do: manually "move" the tank from one position to another, and then smooth out the movement by using dead reckoning. I simply can't do that on my vehicles. They want to be controlled by physical laws (Newtonian), and do not like to be warped from one place to another (This may be limited to the specific engine I am using) or be forced into one position or another (by using direct external forces on vehicles, for example).

However, while these vehicles want to be "manly" and not be pushed around, I can control those vehicles via usual commands, exactly the same way that player controls the vehicles: IVehicle::moveFoward(), etc.

So, my idea is to send updates on vehicles position and orientation, and have vehicles on other clients, try to get into this position. They can turn turn and move, whatever they decide to do to get into desired location. (Btw, control is performed via IRobot's)

This solves one important problem for vehicle movement: even though simulation may run differently, robot-controlled vehicles will take care of the differences by adjusting their movements to get into the position.

Granted, this does not resolve the first problem, the problem of network lag. But this is something I cannot remove at this moment. Lag simply exists. I may decide to predict the movement on remote clients, however, if there will be a need to further improve the movement replication.

Monday, November 13, 2006

Child Steps across the Network

After spending 25 hours of coding in just two days during weekend, I have developed first operational network events.

Server is now operational. Clients can connect at any time. Once connected, they are sent appropriate Id for vehicle and robot for the new player, and those same Id's are sent to existing players. Thus, all players are now replicated.

Current event cover all tank movements, tank's tower rotation, and missile firing. All such events are now broadcasted across the network.

Overall, I had a blast this past weekend. It has been a while, since I made an awesome progress with URumble. And this one was hard earned, but was well worth it. I can feel pride kicking in again. This means I can push harder then before to develop more and more features into the project. I may have a working demo within months now. And possibly a beta for the New Year's Eve! :D

That would be the best gift I ever had.


OK, I have a few technical comments as well. The entire network code runs on RakNet library. It is GPL licensed for free projects, such as mine. Many thanks go to the creator of RakNet for the free version of his library.

RakNet is not a high-level library. It does provide a tons of low level features, and a few medium-level ones, but overall, I had to built an entire event framework on top of RakNet. I will probably release my framework at some point in the future as GPL or similar license.

I first tested the connection on my wireless at home, between my desktop and laptop. I had a really bad lag, though, from 0.25s - 0.5 seconds. This is really bad. I was stunned. I suspected that my wireless connection is really bad, so I tested at my university on 1Gbit LAN. Oh, man, what a difference, I could not notice any lag at all with my eyes. It must have been in the order of a few milliseconds!

Other than that, developing events has been very easy. One thing though is that I have create a new class for every event (by implementing an abstract interface), as well as adding a new type Id for the event, and adding a few lines to EventFactory, so it knows about this new type, and appropriate new class. This is rather annoying. I'll think about a better solution in the future.