Today's Web Wednesday project is multiplayer HTML5 based Asteroids like game, showing off some simple HTML5 canvas dev and C# web socket communication.
I always wanted to write an awesome looking multiplayer game - but I did never have the time to achieve my goal at all areas. Either I had a really solid and fast multiplayer code, or I had a good game idea, or I had the right graphics / graphic methods. With HTML5, a world with new possibilities has come up. First of all, there are plenty of possibilities to write games. There are many kind of games possible. Some browsers have even implemented the (certainly not part of the upcoming HTML5 standard) WebGL technology. Some browsers like Google's Chrome have even the so called native client available. All those technologies make (accelerated) 3D in the browser possible.
At the moment, the most games are kind of 2D social games. They follow a simple principle and contain nice 2D graphics with an interface to Facebook / Google+ / Twitter or other kind of social networks. You'll mostly end up playing a single player that is somehow (mostly over AJAX) connected to the databases of the big sites providing you with updates on how the others do or different kinds of feedback and information. However, there is one technology that will change it all.
Since I do love C# I wanted to write the server code with C#. The basis for the server code was an open source code called Fleck. It does call the necessary .NET-Framework classes and methods and supports most of the current protocol specifications. On the client side, I wanted to use the
<canvas> element. I do not want to present here a full game: the one I present here is playable (in multiplayer) and will certainly be quite a fun for a while. I build it to be extensible. It should be possible to include the features you want to. Everything that is in there was provided in order to make this also your game.
It should be noted that there are many problems arising when trying to program such a game with a multiplayer mode. What about latency? What kind of messages are sent and received? Is logic done on the client as well or only on the server? My approach is kind of simple for this example project. However, my goal is to present this approach and tell you about its advantages and disadvantages as well as how to get rid of those.
Every client will send keyboard input shortly before it gets evaluated to the server. The server then distributes the input to the other clients. So everyone will see the same actions. This has the advantage that the game remains nearly unchanged to the single player except that messages do have to be sent before logic is evaluated and except messages can be received which result in additional logic being done. However, there are several severe disadvantages - namely:
- If one client lags, he will receive the logic too late and not be able to see the actions of the opponents.
- Even worse, if messages from this client are not distributed in time n messages from one client will not be sent to the other clients. So the other clients will probably just see one message - the last one being sent. Instead of taking some turns and making some shots, only the last action will be seen resulting in a game that is out of sync.
In order to prevent the syncing problem, every spaceship is sending its current life status and its current position to the server. This data is then distributed to the other clients. This again has some disadvantages:
- One could cheat by altering the own spaceship's life and ammo properties.
- Particles that have been shot are not included, i.e., here the keyboard actions are really crucial.
Most of these disadvantages can be tackled with the following approach:
- The game's important logic is being executed on the server only in multiplayer.
- The game's not so important logic (like moving an asteroid) is also done on the client.
- The clients are only responsible for drawing and sending keyboard commands.
- The server collects one round of keyboard commands - it will not send the keyboard commands unless everyone has send the keyboard data.
- The clients loop is still send to 40 ms but does only send the keyboard information (in multiplayer).
- The rest is done if all the keyboard commands are received. So everyone will stay in sync for sure.
This approach has several advantages. First, if a new player joins, the server can give all required objects including coordinates to the client. This is possible since the server does execute logic by itself - knowing all the positions. Also the server just executes one logic step after it received all keyboard commands. So instead of relying on total time (which is sometimes good but mostly bad), it would rely on synchronized time.
Using the Code
In order to use the code, you do not have to do a lot of things. However, I need to distinguish between the singleplayer mode and the multiplayer mode. The singleplayer mode should run in your browser (if it is not too old!). I tested the game in the following browsers (singleplayer mode):
- Microsoft Internet Explorer 9+
- Opera 11.5+
- Google Chrome 16+
- Apple Safari 5+
- Mozilla Firefox 7+
Since the singleplayer mode is trivial to play around with - let's take a look at the multiplayer mode. First of all, you need to know that in order to run on your
webserver, you probably need to set certain firewall settings. Even if you set them, you should take into consideration that the client side probably sits also behind a firewall (from the local router, your computer, ...). So in order to guarantee a connection, you need to choose your port as well as your testing methods carefully. Otherwise you can do the following:
- Open the provided Visual Studio 2010 solution.
- Change the line with
new WebSocketServer("ws://localhost:8081"); the port you want to pick (instead of 8081).
- Open the file sockets.js.
- Alter the line with
new WebSocket('ws://localhost:8081'); by replacing both, the port you want to use (instead of 8081) and the IP address or DNS name of the computer (e.g. replace localhost with 192.168.0.1 or example.com).
- If you execute the server program in a local network, then serving the HTML code over the internet does not make much sense - however, it should still work if you execute the page locally.
The last two points are quite non-trivial. Why do you still need to host the page on a server (e.g. localhost) instead of hosting the website in the filesystem? The problem is security. Most browsers do have a security setting preventing websites to execute things when being hosted on the local filesystem. Google Chrome does not
WebSocketrequests from locally hosted websites. The same is true for most XHR requests and other features (like
WebWorkers). Some browsers offer options in order to adjust those settings. Since I don't know your browser, I just assume you have a browser that is capable of
WebSockets and give you a set of instructions that should work for sure!
Here's a snap of the Server Solution;
If you're thinking about how you can use web sockets in your game or site, this is an interesting and easy to follow example...