Java-Gaming.org    
Featured games (79)
games approved by the League of Dukes
Games in Showcase (477)
Games in Android Showcase (109)
games submitted by our members
Games in WIP (536)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  [Kryonet] How to efficiently send movement updates?  (Read 3071 times)
0 Members and 1 Guest are viewing this topic.
Offline timeaisis

Junior Newbie





« Posted 2013-05-15 20:31:19 »

Hey all,

So I'm implementing multiplayer movement of other characters in my game now, I have the server getting new players logging in and storing them in a local copy of the player. My question now is how to do the movement updating. I know *how* to do it, just create a packet and send it over the server to everyone to update. But, I don't want to be sending a huge number of packets every second for every player. That just seems like it will overload my server and crash.

My question to you all is: how could I go about doing this efficiently?

I'm posting a snippet of my movement code below:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
    public void updatePlayer(int delta)
    {
        boolean isWalking = false;
        float xChange = 0, yChange = 0;
        Input input = gc.getInput();
 
        int runMod = 1;
        if (input.isKeyDown(Input.KEY_LSHIFT))
        {
            runMod = 2;
        }
        if(input.isKeyDown(Input.KEY_A))
        {
            //LEFT
           sprite = walkingAnimLeft;
            sprite.start();
            xChange -= speed * runMod * delta;
            isWalking = true;
            facing = "left";
        }
 
        if(input.isKeyDown(Input.KEY_D))
        {
            //RIGHT
           sprite = walkingAnimRight;
            sprite.start();
            xChange += speed * runMod * delta;
            isWalking = true;
            facing = "right";
        }
 
        if(input.isKeyDown(Input.KEY_W))
        {
            //UP
           sprite = walkingAnimUp;
            sprite.start();
            yChange -= speed * runMod * delta;
            isWalking = true;
            facing = "up";
        }
        if(input.isKeyDown(Input.KEY_S))
        {
            //DOWN
           sprite = walkingAnimDown;
            sprite.start();
            yChange += speed * runMod * delta;
            isWalking = true;
            facing = "down";
        }
        if (input.isKeyPressed(input.KEY_ENTER))
        {
            if (chat.isChatting())
            {
                chat.sendText();
            }
            else
            {
                chat.setChatting(true);
            }
            //chat.setChatting();
       }
        if(input.isKeyPressed(input.KEY_E))
        {
            toggleEquip();
        }
        //If the player is not walking, stop the animation
       if (isWalking && !currentMap.blocked(x+xChange, y+yChange, facing))
        {
            x += xChange;
            y += yChange;
            //Here's where I would put it, but as you can see updatePlayer is called all the time, so I'd be sending a packet all the time for each player.
           
        }
        if (!isWalking)
        {
            sprite.setCurrentFrame(1);
            sprite.stop();
        }
        isWalking = false;
    }


I was thinking of using some sort of timer and basically lumping the movements into one packet. I.e., aggregating movement updates across X milliseconds into one packet and sending those at once. But this would require a timer of some sort to count every, 20 milliseconds, let's say. The problem there is, I would need the timer to be accurate on each and every client. And no, I haven't just tried sending it every update, because I'm scared of it crashing hardcore.

Any advice?
Offline DeadlyFugu

Senior Newbie


Medals: 3



« Reply #1 - Posted 2013-05-18 23:53:05 »

From my experience, sending them every frame probably isn't as bad as you think, unless you're really strained for resources, e.g. making an MMO (In which case you should probably use something faster than Kryonet).

You should probably try and send around 6-10 packets a second. To counteract the jumpy-ness this causes you should probably use some sort of interpolation. You can do linear interpolation, but I find something like the following is sufficient:

public void clientUpdate() {
   draw_x += (msg_x-draw_x)/10;
   draw_y += (msg_y-draw_y)/10;
}

Where msg_x and msg_y are the last known location of the object, according to server messages, and draw_x and draw_y are the location you want to use for drawing. You may need to change the 10 at the end to suit how often you receive messages - Use a higher number if the time between messages is longer, use a lower number if it's shorter.
Offline HeroesGraveDev

JGO Kernel


Medals: 239
Projects: 11
Exp: 2 years


┬─┬ノ(ಠ_ಠノ)(╯°□°)╯︵ ┻━┻


« Reply #2 - Posted 2013-05-19 00:04:31 »

10% interpolation is a good idea.

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Nate

JGO Kernel


Medals: 145
Projects: 4
Exp: 14 years


Esoteric Software


« Reply #3 - Posted 2013-05-19 01:59:33 »

unless you're really strained for resources, e.g. making an MMO (In which case you should probably use something faster than Kryonet).
Faster how? Smiley

Offline DeadlyFugu

Senior Newbie


Medals: 3



« Reply #4 - Posted 2013-05-19 02:18:16 »

Faster how? Smiley

From my knowledge Kryonet serializes every object before sending it. While it's serialization is pretty fast, it still creates a decent amount of overhead and takes additional computing time compared to simply sending a dozen bytes over UDP. That wouldn't matter too much for games with a few players at once, but I can imagine it'd strain the servers if you had heaps of players at once.

PS: I don't really know anything about making MMOs Tongue. I've never made one before, and I never intend to. The only networking I've ever done is with the java.net.Socket and java.net.DatagramPacket classes, and I used a lot of overhead (16 or so bytes IIRC)
Offline Nate

JGO Kernel


Medals: 145
Projects: 4
Exp: 14 years


Esoteric Software


« Reply #5 - Posted 2013-05-19 06:19:10 »

You need to get your data to bytes somehow, no matter how you are doing your networking, so there will always be some overhead there. Smiley

KryoNet uses Kryo for serialization. When automatically serializing your objects, Kryo is almost as fast as hand written serialization code. It generates bytecodes instead of using reflection when possible. Kryo can optionally use Unsafe on Sun VMs to directly access object memory, which is extremely, ridiculously fast for arrays of primitive types.

Kryo serialization is pluggable, so you can hand write serialization code and Kryo has utilities for making this easy. Hand written serialization code using Kryo is generally faster and smaller than hand written serialization code using java.io.Externalizable. Here are benchmarks. It's a lot of data, so I'll pluck out the interesting parts:



"kryo" in this chart is using automatic serialization. "java-built-in" is Java's automatic serialization. Here's another:



The "kryo-manual" in this chart is hand written serialization code. The "java-manual" is hand written Externalizable code. I won't spam more charts, but the "size" charts are also cool, showing Kryo is also size efficient. Smiley Of course the benchmark data is small and string heavy, so likely not terribly meaningful unless you run it with your own actual data.

TLDR; Kryo is super awesome, fast serialization. Cheesy Back on topic though, KryoNet does have some limitations, mostly with threading. KryoNet is limited to one network thread. Objects are serialized on any thread that calls send() and bytes are usually sent immediately from that thread, though they may be queued for sending later from the network thread. That part is fine, but bytes are always received and queued on the network thread, and deserialization happens on that thread as well. Once you get the deserialized object you can process it on another thread, but doing the deserialization on the network thread limits throughput. This starts to become an issue when exceeding 1Gbit/s.

KryoNet is an easy to use API on top of NIO. The API doesn't really care how the networking is done though. I have a version of KryoNet that uses Netty under the covers, which allows for more threading flexibility. It doesn't have all the minor features of KryoNet though, and I haven't found the time to finish it. Sad

Offline Cero
« Reply #6 - Posted 2013-05-19 13:15:02 »

Showoff Cheesy
Well what I'm lacking is network programming experience, especially with games.
For example I would send/poll positions of everything, every frame. Using UDP i guess but still maybe overkill. So I guess I need general high performance networking knowledge -  nothing to do with kryonet
Gotta read a book or something.

Offline timeaisis

Junior Newbie





« Reply #7 - Posted 2013-05-20 07:51:42 »

Wow! Thanks for all the replies Smiley
Learning network stuff is definitely a trial by fire for me, but you guys help is much appreciated. Smiley

Btw, cero, I'm doing the same thing. Tongue But after reading all this I'm gonna keep trying what I'm doing until I notice some issues.
Offline Shnagenburg

Junior Newbie





« Reply #8 - Posted 2013-07-11 18:29:19 »

A very quick optimization you can make here is to only send player positions for players who moved during that frame. If a client gets a packet that makes no mention of player_foo then player_foo much be in the same place he was last frame. Another trick is to know how little data you can get away with sending, for example, can you use a short instead of a float to update the clients?

Unless you have some sort of client-side interpolation, the game is going to look jumpy since networks are unreliable. The better your interpolation is, the slower the server can run and clients won't notice it. I highly recommend taking the time to read some common tricks that games use to hide the instability and delays of a network. I would suggest these for reading:

https://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking
https://developer.valvesoftware.com/wiki/Latency_Compensating_Methods_in_Client/Server_In-game_Protocol_Design_and_Optimization

Even though these methods are used by a 3d game, they translate over just as well to a 2d game.
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

CogWheelz (18 views)
2014-07-30 21:08:39

Riven (26 views)
2014-07-29 18:09:19

Riven (15 views)
2014-07-29 18:08:52

Dwinin (13 views)
2014-07-29 10:59:34

E.R. Fleming (34 views)
2014-07-29 03:07:13

E.R. Fleming (12 views)
2014-07-29 03:06:25

pw (43 views)
2014-07-24 01:59:36

Riven (44 views)
2014-07-23 21:16:32

Riven (30 views)
2014-07-23 21:07:15

Riven (31 views)
2014-07-23 20:56:16
List of Learning Resources
by SilverTiger
2014-07-31 18:29:50

List of Learning Resources
by SilverTiger
2014-07-31 18:26:06

List of Learning Resources
by SilverTiger
2014-07-31 13:54:12

HotSpot Options
by dleskov
2014-07-08 03:59:08

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:58:24

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:47:22

How do I start Java Game Development?
by ra4king
2014-05-17 11:13:37

HotSpot Options
by Roquen
2014-05-15 09:59:54
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!