What's the best way to get a networked game up and running on a smartphone? For his space battle game ErnCon, Ernest Woo investigated existing network techniques and integrated them together, coming up with a solution useful to iOS and Android developers, which he shares within.
One of the greatest benefits of being an indie game developer is the freedom to create the exact game you want to create. Without the bureaucracy of an entire company to discourage ideas, you're free to try whatever crazy idea might work -- even if you have no clue what you're doing!
Based on user feedback from my first Android game FRG, and with inspiration from early multiplayer Android games like Project INF, I wanted the follow-up to be a mobile real time multiplayer shoot 'em-up playable over 3G. The problem was that I had no idea how to make a multiplayer game.
Ultimately I overcame this stumbling block and managed to release ErnCon. Along the way, I learned many of the technical details involved in creating a multiplayer game. Hopefully sharing my experiences will shed light on how a mobile real-time multiplayer game is developed.
Where Do I Start?
I am a Java developer by trade, with experience developing Java web applications and native applications (J2ME, Android, and iOS). I've always implemented communication between web-apps and native-apps with HTTP -- not a suitable technology for real-time games! I focused my initial research on finding answers to key concerns I had regarding developing a multiplayer game:
1. Network Address Translation (NAT). Because ErnCon must be playable over 3G, I had to figure out how to traverse Symmetric NAT typical of cellphone carriers. Symmetric NAT works by mapping an internal address/port (your phone) to a different external address/port (your carrier/ISP's NAT) for every single destination address/port (the game server) connection made.
Games running on a DSL or cable modem connection behind a consumer-grade router use techniques to traverse the more permissive NAT types (Full-cone, Restricted Cone, and Port-restricted Cone), none of which really apply to Symmetric NAT.
After researching UDP Hole Punching and other NAT traversal techniques, I settled on the simpler solution of a client-server architecture where the servers always have a public IP address, i.e. the servers are not NAT'ed themselves. No special NAT traversal tricks are required for communications to a public server. For more information, read the Wikipedia article on NAT.
2. Simple network model. Without experience developing a real-time multiplayer game, I sought information on how other games implemented their networking layer. Epic Games published information on Unreal Tournament's network architecture, although I found it to be tied too tightly to concepts from the Unreal Engine -- I did not want to implement my own version of Unreal Engine 3. Quake III's network model, which I ultimately chose, proved to be much easier to understand, with its simpler notion of sending entire game-state updates delta compressed from the last known received state.
3. Reduced chance of exploits. As an indie developer, I don't have the resources to implement robust cheat detection. The architecture of the game itself must be resilient to hackers, as any data controlled by the client is ripe for exploit. A client-server architecture satisfies this concern by making the server the sole authority for all game data.
4. Worldwide server deployment. A real-time multiplayer game using a client-server architecture will not run well if all players in the world are connecting to servers located in a single location. To reduce lag and improve the game-play experience, servers must be strategically provisioned around the world. Players have to be segregated into regions so that geographically close players are always playing on the same servers. Amazon Web Services (AWS) was a boon for me allowing me to provision servers in various places including the US, Europe, Southeast Asia, and South America.
As the saying goes, “the devil is in the details.” The effort involved in researching a proper architecture, deciding on a networking model, and settling on a provider pales in comparison to actually implementing everything. Without going too far into boring detail, here are some of the hurdles I've cleared:
1. Start with an existing game. Although I wanted to immediately start on ErnCon, which would take full advantage of multiplayer, I decided to implement a multiplayer prototype in my existing game, FRG. This allowed me to focus work on just the networking code and client-server development. Only when I was satisfied with the quality of FRG's multiplayer implementation would I incrementally develop a new game.
2. Use and abuse Java. Because Android apps can be developed in Java, I simplified server development by also using Java. Doing so allowed me to quickly create a web application running in Tomcat that could run the game headless (without graphics and sound). Sharing code between client and server greatly reduced the amount of effort needed to ensure that both were simulating the same game.