Multiplayer Games Programming

This module aimed to demonstrate our ability to produce a simple 2D game using C# and Microsoft's .net framework, we learnt many important programming fundamentals such as thread-safe architecture, concurrency and network package encryption and transfer. The game itself was intended to be relatively simple to allow more time to be spent on the networking architecture.

About The Project



Starting Out


We were given a base framework to expand upon, consisting of a pong-like game, with some basic input controlled movement and blocks affected by physics, from this we could take our own initiative to decide what we wanted to make. I had a few ideas and after discussion with a lecturer decided on a tank combat game inspired by Wii Play's tanks game, I would have up to four players connect to a lobby and have the ability to move and fire projectiles to damage eachother, a very simple gameloop that still required a lot of consideration to play across a network, such as packet types and encryption strateges.



Synchronising Movement


The first challenge I ran into was synchronising player movement across the network, this wasn't done already in the framework and was the first proper type of packet sent across the network, after only the debug message packet created. This would simply contain a sender ID and a message, when introducing the movement packet, it became necessary to make a family of packet classes inherting from a base packet with the essential data. The issue that arose was when the packet was received, the program did not know how to differentiate between the packet types, to solve this, I simply added an enum to allow packet types to be recognised and casted accordingly. Doing this allowed the packets to essentially interpret their structure internally by calling the relevant constructor. They were sent over the network as strings from a json file, this lent itself well to encryption, which will be discussed later on.

Once the movement was synchronised, I was quite easily able to sync rotation, turret rotations and projectile positions etc. The next big challenge was down to the game mechanics themselves, scores, rounds, title screen etc. This was not the focus of the project so I didn't expand on this a great deal, however, using the built in C# frameworks such as Xna was a challenge at first due to the framework's unusual design choices leading to unexpected behavviours that were hard to debug. Most of this time was spent modularising and structuring the framework to help make additions easier. I initially planned on adding mines that could be placed by players, however this would not have added anything of worth to the scope of the framework, so ultimately I decided against it. I added walls and the necessary collision functionality, as well as a health and damage system. This is an area I plan on developing a lot more now that the project has been submitted.

An important step of the synchronisation was ensuring each player was assigned a proper ID, this became more challenging with the addition of lobbies, where a player's network ID would not necessarily match their lobby ID. The server would be tasked with managing the lobby IDs accordingly, and hosting the lobbies themselves. Packets had to be given extra information including lobby ID when encessary to ensure they were only sent to the clients that need the information. This caused a large amount of errors including clients being assigned the incorrect ID, and the server updating a player's position in lobbies other than their own. It took a while to debug and bugfix but eventually worked well. I could then move onto making lobbies joinable on selection as opposed to auto-joining upon logging into the server. Player spawn positions in the level could easily be adjusted depending on how many players connect.



Transfer Protocols


Sending packets over the network, initially was done with Transmission Control Protocol (TCP). TCP is reliable, establishing a port to port connection that guarentees all packets of data are sent together. Either all of them arrive, or none of them do. While this is ideal for sending IDs, network keys etc. It's lack of speed starts to become an issue in realtime games, a good example is player position. In a server running many games, sending many positions over a network, there may be some issues with latency. Packets arrive slow and as such, are always behind on the true position. Ruining the game experience and leading to many potential desynchronisation issues. To combat this issue, I implemented a User Datagram Protocol (UDP). This allows packets to be sent on different routes, it does not guarentee their arrival, but it doesn't need to. It is useful for things like position as dropping a frame or two is not often noticeable. While it sacrifices reliability, it more than makes up for it in terms of speed. Being hugely faster than TCP allows more flexibility in what can be sent, and how much the server can handle. Neither are used in isolation however, as important server information, or game related things that absolutely must be received are still done through TCP.



Encryption


In order to add some security, I opted to encrypt the packets before sending them, this used a popular encryption method called cryptography. Cryptography uses a combination of "keys", which are long strings of characters to encrypt a file. it can then only be decrypted with a corresponding private key. Private keys can only be accessed by a specific device, whereas public keys, as the name implies, are openly available, being sent when the device connects. This is then used to encrypt files for that specific client. This removes any need to send a key over the network, making them highly secure, which is further aided by having a longer key, the longer the key, the harder to brute force decrypt, becoming practically impossible at longer lengths. This was relatively straightforward to implement, and while not necessary for the given project, is an important step in securing any kind of networking application to a reasonable extent. I would very much be interested in further exploring network security protocols further down the line.



Overall Thoughts


Overall, I am relatively happy with the outcome of the game. It is capable of handling several servers of players playing at the same time, and has a robust packet system with plenty of room for future expansion. The game is simple, yet enjoyable, and fully synchronised with eachother including failsafes like UDP packet orders, preventing old positions from overwriting the new ones and causing jittery, inaccurate movement. This is a project I fully intend on expanding on in the future, giving functionality such as being able to leave lobbies, different game modes, and custom nicknames, along with expanding my threading architecture, as it was the artefact's main point of feedback.

Artefact Grade: 1st