Try the effect before reading
These are the techniques I’ve used in my upcoming game
Zom Zok – Realtime multiplayer shmup
0. Einaros
For all examples I will be using einaros/ws websocket implementation which is much more lightweight and straightforward than Socket.io
Einaros/ws: https://github.com/einaros/ws
1. Use BISON to reduce packet size about 50%
Get very nice implementation here https://github.com/BonsaiDen/BiSON.js
var packet = {
command: "something",
data: {
all: "my",
pretty: "data",
number: 1337
}
};
ws.send(BISON.encode(packet));
ws.onmessage = function(event) {
var packet = BISON.decode(message.data);
/* do whatever with the packet */
}
2. Define numeric values for your string constants
This rule applies to everything what is enumerable but you are doing it using strings.
var packet = {
action: "update_entity",
entity: [ ... ]
};
var DEFS = {
UPDATE_ENTITIY: 1
};
var packet = {
action: DEFS.UPADTE_ENTITY,
entity: [ ... ]
};
In this case:
- string consistent of ASCII characters takes 1 byte for each character
- integer takes 1 byte for value up to 128, then another byte for value up to 32768
3. Clever structured packets
All above examples are somewhat wrong – take a look below:
var packet = {
command: "update-something",
minerals: [32, 12, 16],
name: "fancy",
jesus: "christ"
}
var packet = [ DEFS.UPDATE_SOMETHING, [32, 12, 16], "fancy", "christ" ];
tip: You can write a converter between this two formats – however – for performance sake I advise you to just keep the packets well documented.
4. Commands
When something happens from time to time – not at every step you don’t really want to send it in every frame. For example:
var packet = [ ..., player.shooting ];
/* only if the state changes send this */ var packet = [ DEFS.PLAYER_SET_SHOOTING, player.shooting ];
5. It doesn’t changed? DON’T SEND IT
For example – you have static objects like asteroids in mine game (which are randomly spread at the beginning of the game) – you only need to send them once – don’t send them in each snapshot.
6. Ads by google
[inlinead]
7. (again) It doesn’t changed? DON’T SEND IT
This is kind of a tricky thing.
var packet = [ DEFS.UPDATE, "101001", "something", 32, "anything" ];
Now what it does:
8. Bullets
If there are a lot of them you should simulate them 100% at the client side. I am using commands PLAYER_START_SHOOTING, PLAYER_STOP_SHOOTING. Note that this is not fully accurate – and can lead to bullet missing the target yet still damaging it – however it is not very noticeable when the count is great.
9. Grouping/summing events
Instead of sending *Player lost 12 hp* whenever it happens – sum it and send once per some time / snapshot.
10. BISON vs LZW
If your data relies on strings more than numbers you could give a try to LZW algorithm instead of BISON. LZW is very good when it comes to compress strings with a lot of repetitive words/segments.
Here is an example implementation. It is used in the same way as JSON.stringify or BISON.encode
11. Fixed structure packets
If you have done all the optimisation and still not satisfied with the result you can try fixed packets. It means that there is no separators between values but each size has to be constant. It means you have to define how many bits are used by each value in packet. It also means that you will have to add headers for each collection describing how many objects are within.
Prologue
These are the major ideas that made my realtime multiplayer games capable of handling a lot of entities. I’ve wasted a lot of time (and toilet paper) to come out with them as the internet isn’t very generous at multiplayer knowledge. If you have any thoughts – ideas – improvements – please share them below.
If you want to show appreciation consider using share/like buttons or a donation <3,
Comments like awful or awesome with no meritorical value will be deleted as I want to keep this thread helpful.
Cheers.
Readers addendum
You may find some of reddit comments useful
1. Use protocol buffers
by Amit Patel on #bbg
http://en.wikipedia.org/wiki/Protocol_Buffers
https://github.com/sirikata/protojs#readme
2. Use flat structure
This is similar approach to using fixed structure but doesn’t require understanding on binary level.
You can ensure packet structure as a flat array by yourself or use PacketFlattener which converts complex/deep objects structure to flat array.
by Karel Crombecq from Sileni Studios on #bbg



