• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
Martin Radev

Proper multiplayer communication

7 posts in this topic

Hello!

 

I am searching for some suggestions how to improve the multiplayer communication in my game. Currently, it is done in the following way:

 

- I create a server game and other players can connect to it using the ip and the port

- They send information about their player and the server receives it

- Then the server sends the information to every other player

 

The commands are of the following way:

update player Radev 0.0 0.0 100 100 5000 5000 0.0

rotate player Radev -0.4332702160639106

shoot player Radev 0.0001 0.77878

 

Do you think I should try to encode it in some way or just make the commands shorter like:

upRadev 0.0 0.0 100 100 5000 5000 0.0

rpRadev -0.4332702160639106

spRadev 0.0001 0.77878

 

However this does not make the commands a lot shorter in any case.

Any ideas?

0

Share this post


Link to post
Share on other sites

Generally you would transfer data over the network in binary form. So youd have a byte or two for the size of the packet, then a byte or so for the type, and then the data which is interpreted based on the type given.

 

For player positions and such it is often possible to send the delta values (eg change since last state) instead of the full data, and only once in a while send the full state (in case theres an error in the delta-values or some were missed etc.)

 

However, i suggest not to try to compress the data further since its probably unnecessary in your case and is likely to introduce a pile of new bugs.

Just send your data in binary form instead of human readable text. You can find a metric ton of tutorials and articles and forum posts with lots of advice with some googling.

0

Share this post


Link to post
Share on other sites

I made the strings shorter by making the commands to be only by one character and accordingly the numbers to lose their precision.

Now, the commands are of the type:

rp yuyuyu -0.07            where yuyuyu is the name of the player

Before that the command was:

rotate player yuyuyu -0.4332702160639106

 

Since there aren't a lot of commands I think, maybe I can combine rp and -0.07 in a bit representation to save space.

0

Share this post


Link to post
Share on other sites

I think I could help you better if you explain a bit what are you doing and how are you/do you want to do it. Answering those questions would be useful:

 

  1. What kind of game are you working on and what amount of data do you need to send?
  2. Is your game client also in Java?
  3. What classes/libraries are you using for network communication?
  4. How do you transmit the information through network? Are you using a library that allows you to send it as String, do you call String.getBytes and send it as a byte array...?
  5. Is there any reason why aren't you using Serializable objects and alike?

 

If you are really sending the string "rp SomeAwesomeNick -0.07", well... the string "SomeAwesomeNick" is 13 bytes length. And the string "-0.07" is 5 bytes length. Using an int type for the player (relating each player name to an integer id) and a float type for the angle would save you 9 bytes for the player and one byte for the angle. And you could even use shorter types. If I wanted to serialize it manually, I could build a byte array with the first byte identifying the command, the next four bytes for the integer id and the last four bytes for the float angle. In nine bytes I'd had the command, the player and the angle with a lot more precision than the string way. Hey, if I'm sure I'll never have more than 256 players and 256 directions are enough for me, I even could do it in three bytes. My point is use objects, not strings, and serialize to byte arrays.

 

Without any further clarification I find difficult to provide some useful advice, but in case you are just trying to figure out how to do it, I'll explain how I would do it.

 

If your client is also Java, then using plain ol' Serializable objects saves a lot of headaches, and if you are using sockets or something alike, it requires you to send the data as a byte array anyways. I would have a class implementing java.io.Serializable for each command you need, and just serialize it to a byte array and send it through the socket. For instance:

public class RotatePlayer implements Serializable {
	
	private static final long serialVersionUID = -171890897880063974L;

	long playerId;
	
	double angle;
}

Repeat for each command and that's all you need to worry for. You can save some bits by changing the types to a shorter ones, if that worries you. Even you could use 'byte' for angle and transform it to degrees before and after transmission, for many cases I would find 256 possible directions to be enough.

 

Yeah, sure, you can save some bytes by implementing your own serialization system (*), but is really worth it?

 

More on serializing/deserializing: http://stackoverflow.com/questions/2836646/java-serializable-object-to-byte-array

 

(*) Of course, Serializable objects add some amount of data because Java needs to know how to deserialize the object later. I tested the class above and serialized is 73 bytes lenght, which is like 57 bytes more than the data I really want to send, but in most cases the tradeoff pays for its ease to use. If that amount is too much, I would implement my own serializing system, but I would send bytes, not strings, and I would have one class for each command. You could have the first one or two bytes (depending on the amount of classes you need to serialize) for identifying the class and then provide a constructor that with the rest of bytes could build the object. You'll probably need to do that way also if your client is not writen in Java.

Edited by Avalander
1

Share this post


Link to post
Share on other sites
When you say "improve," what is your goal? Do you have any actual measured problem that you're trying to solve?

If saving space of state updates is very important, as suggested above, using binary marshaled data is more efficient. I typically quantize a position to three sixteen-bit or twenty-four-bit values. I generally quantize an orientation to three ten-bit values as a quaternion (re-constructing the fourth value,) using one of the last two bits out of 32 bits to tell the sign of the lost value. Velocity can often be packed into three bytes, and if that's not enough precision, six bytes certainly will be for almost all cases.

Also, I would recommend against using the Serializable interface/mechanism in Java (or any other language,) for networked games, as those are typically designed for business objects, where space is not of utmost concern. If you already know what the packet format will be, no need describing it in every packet you send.

For player IDs, I can get away with a single byte (or a short, if it's an "M"MOG) if I introduce the player name associated with an ID in a separate packet. For persistent single-shard worlds, it might make sense to send a full, globally unique, user ID, where 4 bytes is sufficient unless you plan on having more than 4 billion registed users :-)

So, a potential binary serialization of the data you suggest might look like this in binary (the lengths are in bits):

<type:4> <fields:4> <player:8> <position:48> <orientation:32> <speed:24> <shoot:24>

"type" lets you determine different packets (for speaking, inventory updates, or whatnot.) For this particular packet type, you assign a particular constant, such as 1.
"fields" is a bitmask of which of the position/orientation/speed/shoot fields are actually included (unless you always include all of them.)
"player" is the player for which this update is, as an ID within the game -- when joining a player is assigned an ID in the range 0..255.
"position" is the position, quantized to 16 bits. If your minimum/maximum position values are -1024..+1023.xxx, you would calculate the quantized value of each component as (short)(pos.x*32), and you'd re-constitute the float by dividing back out: comp_x/32.0
"orientation" is an orientation quaternion encoded as suggested above (the range of each component is -1..1 with 10 bits each)
"speed" is like "position" except smaller range (-4..+3.xxx) -- if this is not enough, use more bits.
"shoot" is a vector just like "speed."
2

Share this post


Link to post
Share on other sites

Thank you. What I wanted was to make the commands shorter. I believe I will use your approaches. The problem was with the latency since the current commands were too long.

0

Share this post


Link to post
Share on other sites

Wait, latency should not depend on the length of your commands, unless you are trying to push through so much data that it saturates the connection.

 

For latency, you need to do something different:

-Make sure your client sends the data soon after you have some and does not lets say buffer it (TCP tends to buffer data for a while before sending using something called nagle's algorithm, if you are using TCP you probably want to disable nagle's algorithm using a flag or something)

-Use UDP if you really need low latency because if TCP loses a packet it will ask the client to send it again, which means all following packets have to wait till the lost packet is resent.

-Hide the latency. All fast paced games need to hide latency, because it is often significant enough for the user to notice and there is nothing you can do to remove that latency (usually a few hundred ms). Essentially the data you receive from the other clients/server is always outdated, and you need to use that old data to predict what the current state of the game is on the other machines so it looks somewhat real time. Then when your predictions are wrong you correct for it (and try to hide these corrections).

0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0