Oh and also! Great stuff and thank you for sharing! Personally, socket.io is the reason for node to exist. It's a beautiful marriage and I wish more people who learned node learned it in this context.
Yes, it's my first time using socketio. So, yeah, I must have missed a lot. The gain in speed was visible, but maybe it wasn't for the reason I thought
WebSocket has much less latency and overhead than long-polling Ajax. Heroku just doesn't support it yet. The solution for now is to run your own WebSocket server on AWS or subscribe to a service like Pusher.
That's cool, keep up the effort.. I've been working on multiplayer game for the last 6 months. I use HTML5/JS, WebSockets, WebGL and node.js (I rewrote my server 6 times while flicking between node and Java, but eventually stuck with node.js as it was frustrating swapping between languages when developing the client and server at the same time)
My game has real time twitch-based combat, meaning you use the controls to directly move your player around and shoot at 30fps+. This was a real pain to build with TCP as I have to have a lot of client side prediction and lag correction to handle packet resends. I can't wait until UDP is more widely available with HTML5's DataChannel: http://www.thrupoint.com/2012/11/webrtc-data-channel/
I've gone with my own VPS (around £5 a month) but will probably move over to AWS if I get further with the game.
I've actually been working on and off on a multiplayer HTML5 game for a while now.
https://github.com/stevenleeg/thegrid2_client - for anyone who's interested. It's a pretty simple brand of RTS, so a lot of the realtime code could be used for anyone needing a reference for creating their own.
Very interesting to read! I guess I'll have to try my hand at multiplayer HTML5 game as well some time, because even reading you, I believe you, but at the same time it's hard to believe that it's hard like that :)
Care to elaborate a bit on the part where you say communicating the entire board state was too much data? Looking at your game, I don't see how the board state could be much more than 100 bytes or so? Was it the JSON that bloated it up?
If I were you, I'd do it like this: split the state into a static and dynamic part. Player's names won't change during the game. Or if they might, maybe even better to split the state into a high and low latency part. If you see a Player's name update a second too late, it's no big deal, so communicate that via a different, slower, channel. All the other data, the board state, player positions, scores, you don't need JSON if you're transmitting the same fields every time. So make sure everything's a ranged integer and squeeze them together either using a base64 library, or maybe just simply Number.toString and ParseInt with radix 36 (max natively supported radix encoding in JS, and still 5.17 bits/byte), or maybe you hack Unicode/UTF8 to translate integer code-points into bytes and vice versa (you should probably go for the latter, because it'll be awesome).
Oh and then, a tip, when you wrote:
> I added some rules and gameplay elements to make it feel more like something one would like to play, including:
Feedbacks when you get hit
As you can see, all those tricks are "merely cosmetic", but they truly do make the game a lot more fun to play. The second most important thing, almost all of them are simply transformations to the "view" of the game, so they can all be done client-side, cost nothing extra network-wise (apart from loading initial extra gfx). But the first most important thing is that all these extra tweening functions and particle animations help cover up any accidental lag or latency! If you got a bare bones squares-on-a-grid game, any lag and stutter will be super obvious, because that's the only thing to see. But if everything is bouncy and wobbly, and there's explosions and smoke flying all over the screen, those things can keep moving and animating because they don't depend on server information, while the game engine waits for the next data packet, and the player won't suspect a thing. It similar to "suspension of disbelief", in a way.
Please do post follow-ups if you continue developing this game!
The board was not very big, but since every movement would broadcast the entire board to all players, it would add up. I didn't bench exactly how bad it was, but as I was adding data to it I could feel the game slowing down. You have to keep in mind that at that point every movement would make the server send the whole board, and in that game you'd move constantly.
Thanks for the tips. I don't think I'll continue developing this game, but if I get some time I was thinking about doing something cross devices (iPhone / Desktop). I don't know how yet, we'll see.
13 comments
[ 2.8 ms ] story [ 31.8 ms ] threadThe code however is on github: https://github.com/marcgg/websockets-experiments It's VERY poorly written as I kept throwing code away and trying out stuff so don't look at it too closely.
Hmmm even on heroku you should have pretty damn good responsiveness as I assume it should be using what is known as "COMET" http://en.wikipedia.org/wiki/Comet_(programming)
The polling is just to reestablish the kept alive connection. Which while still less than ideal... I wouldn't think would be terrible.
Not saying the author is wrong but being that it seems like his first foray into socket.io it's a possibility.
My game has real time twitch-based combat, meaning you use the controls to directly move your player around and shoot at 30fps+. This was a real pain to build with TCP as I have to have a lot of client side prediction and lag correction to handle packet resends. I can't wait until UDP is more widely available with HTML5's DataChannel: http://www.thrupoint.com/2012/11/webrtc-data-channel/
I've gone with my own VPS (around £5 a month) but will probably move over to AWS if I get further with the game.
https://github.com/stevenleeg/thegrid2_client - for anyone who's interested. It's a pretty simple brand of RTS, so a lot of the realtime code could be used for anyone needing a reference for creating their own.
http://developingthedream.blogspot.com
Care to elaborate a bit on the part where you say communicating the entire board state was too much data? Looking at your game, I don't see how the board state could be much more than 100 bytes or so? Was it the JSON that bloated it up?
If I were you, I'd do it like this: split the state into a static and dynamic part. Player's names won't change during the game. Or if they might, maybe even better to split the state into a high and low latency part. If you see a Player's name update a second too late, it's no big deal, so communicate that via a different, slower, channel. All the other data, the board state, player positions, scores, you don't need JSON if you're transmitting the same fields every time. So make sure everything's a ranged integer and squeeze them together either using a base64 library, or maybe just simply Number.toString and ParseInt with radix 36 (max natively supported radix encoding in JS, and still 5.17 bits/byte), or maybe you hack Unicode/UTF8 to translate integer code-points into bytes and vice versa (you should probably go for the latter, because it'll be awesome).
Oh and then, a tip, when you wrote:
> I added some rules and gameplay elements to make it feel more like something one would like to play, including: Feedbacks when you get hit
I was reminded of this really cool presentation about game-design and "juice": http://www.youtube.com/watch?v=Fy0aCDmgnxg
As you can see, all those tricks are "merely cosmetic", but they truly do make the game a lot more fun to play. The second most important thing, almost all of them are simply transformations to the "view" of the game, so they can all be done client-side, cost nothing extra network-wise (apart from loading initial extra gfx). But the first most important thing is that all these extra tweening functions and particle animations help cover up any accidental lag or latency! If you got a bare bones squares-on-a-grid game, any lag and stutter will be super obvious, because that's the only thing to see. But if everything is bouncy and wobbly, and there's explosions and smoke flying all over the screen, those things can keep moving and animating because they don't depend on server information, while the game engine waits for the next data packet, and the player won't suspect a thing. It similar to "suspension of disbelief", in a way.
Please do post follow-ups if you continue developing this game!
Thanks for the tips. I don't think I'll continue developing this game, but if I get some time I was thinking about doing something cross devices (iPhone / Desktop). I don't know how yet, we'll see.