[Red5] realtime movement ; latency ; dead reckoning ; coordinate prediction

Walter Tak walter at waltertak.com
Wed Nov 7 06:11:54 PST 2007


Management excerpt:

a. Has anyone decent experience with realtime 'smooth' movement of objects in multiplayer environments ?
b. What would be the performance impact of using SO.send() at a decent framerate (say 10 times a second) versus normal usage of SO + onSync.

The long version why option b. would be needed.

I'm working on a realtime multiplayer game and things are going fine but I'm having difficulties syncing movement of all players using a SO and .onSync.

Image a flying game with fast moving planes on a large playground. Each plane travels at least 100 pixels per second ~ 3 pixels per frame (@ 30 fps)

I've studied a lot of available info on dead reckoning (= prediction where a player might go to in the next XXX frames , until a new update of the players coordinates+vector came along).

The default shared ball tutorial for FMS and Red5 shows exactly the problem of onSync ; 
if you move the ball fast then the updates on the other client are horrible ; 
you will see the ball being updated around 10 fps and it moves unnatural.
Increasing the setFps to insane numbers (50 updates per sec for example) don't work ; the other players won't receive 50 onSyncs ! Neither should they.

To prevent the stuttering I calculate the deltaX and deltaY between the last known and previous update of onSync and let the client move the ball (player1) in an onEnterFrame,
with deltaX and deltaY / (framerate / syncrate) . If a plane would travel 100 pixels (on the x-axis) between 2 onsyncs  then the actual displacement of the plane would be
100pixels / (30fps / 10syncs) = ~ 33 pixels per (onEnter) frame ; the plane would fly 3 frames before a new onSync will arive.

E.g. when using setFps(5) (5 updates max per second, to minimize traffic and load on the server) the table of the movement looks like this:

New situation ; plane starts at position 100,100 and flies around.

At timestamp t0 ( 0 ms ) the position of player1 is 100,100 - Data is synced to Red5 , timestamp s0 (0 ms)
At timestamp t1 ( 50 ms )  the position of player1 is 110,101 
At timestamp t2 ( 100 ms )  the position of player1 is 120,102
At timestamp t3 ( 150 ms )  the position of player1 is 130,103
At timestamp t4 ( 200 ms )  the position of player1 is 140,104
At timestamp t5 ( 250 ms )  the position of player1 is 150,105 - Data is synced to Red5 , timestamp s1

As you can see the remote client only receives 2 updates, one at s0 and one at s1. The deltaX is 150-100 = 50 .. The deltaY is 105-100 = 5.

If I'd know the exact update-rate of onSync (which is variable since it only transmits changes) I could calculate the exact 'movement per frame' like this:

If player1 moves from 100,100 to 150,100 in 5 frames then the deltaX,deltaY per frame is (150-100)/5 = 10 (pixels) and (105-100)/5 = 1 (pixels)

This way we can "predict" the movement of the player for the next 5 frames from t5. However this is a prediction and chances are high that the actual position of
player1 at next sync timestamp t9 / s2 will be something like 160,130 (instead of 150 + 5*10 = 200 and 110 + 5*1 = 110) so we have to correct the correct position of player 1
asap from 200,110 to 160,110 (which is tbh a pretty large delta)

The timeline would look like this:

t5 (250 ms) position predicted 160,106
t6 (300 ms) position predicted 170,107
t7 (350 ms) position predicted 180,108
t8 (400 ms) position predicted 190,109
t9 (450 ms) position predicted 200,110 - Data is synced to Red5 from player1, timestamp s2 , actual coordinates of player1 are 160,130

new deltaX : 160 (s2) -150 (s1) = 10 and deltaY : 130 (s2) - 105 (s1) = 25 (per 5 frames)

At this point 2 things need to be done ; 
1. correct the wrong current position of player1 and 
2. recalculate the new delta's 
3. combine 1 + 2

The above is relative simple math and can be implemented in a day.

However ; we don't know at what rate the onSync comes in ; if player1 doesn't move for 3 seconds (!) then nothing will be send to Red5 and the onSync event at player 2 will not trigger ;
if we would keep moving virtual player 1 at the last calculated delta's then he will end up at the edge of the screen while in fact he already had stopped.

To counter this it would be better to get onSyncs that repeat the last position instead of a silent onSync.

E.g. player 1 moves towards position 150,100 ; in an onEnterFrame the Flash-client would transmit 150,100 to the server, no matter if the player stopped.
That way it's easy to calculate delta's between the current and last known position.

--

However this starts to become fairly complicated and I don't want to reinvent the wheel, 
let alone think that I'm the only one capable of solving the problem, so does anyone have a good idea ?

If not I'll try to develop a (Flash) class for this , if needed combined with a Red5-class , and share it with the rest of the community.


Regards,
Walter


-- 
I am using the free version of SPAMfighter for private users.
It has removed 13728 spam emails to date.
Paying users do not have this message in their emails.
Get the free SPAMfighter here: http://www.spamfighter.com/len
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://osflash.org/pipermail/red5_osflash.org/attachments/20071107/9853a046/attachment.html 


More information about the Red5 mailing list