Category Archives: Dev logs

Novice UDP Online Game Net Coding

Disclaimer, I’m not a low-level network coding expert, so I’m sure there are easier/better architectures for how to handle this sort of thing. I’ll study them someday

To keep my mind off the world going to shit recently, I redid parts of my game’s networking code last night to add “sync” support to my packet transmissions (make sure a packet was received).  Mini case study below.

Basically since UDP does not guarantee delivery of packets, packets can arrive late, never, out of order, or duplicated, you’re royally fucked if a certain important packet such as (the unit was split in two) arrives twice.  So for packets that aren’t just player position, you have to handle the sync properly.  Each packet starts with the same header

The first step is to add seq and ack to all outgoing packets where seq is the packet number of this packet and ack is the highest number of any packet we’ve received back.  For example, if the client is sending the 100th packet, seq will be 100.  If the server receives this packet, upon it’s next update to this client, it’ll send a packet with the ack containing 100, so the client can know it was received.  This is a super basic well known mechanism for reliability (TCP does something like this but considerably more complex)

So, the issue last night was, how the fuck do I handle a missed ack.  Architecturally it got a bit messy.  Basically my game works on a heartbeat type mechanism where the app is set into a certain state, (like a battle match), and the same packet type is sent over and over again from the client with updated data (the player positions).  If they get lost, no big deal, because another one is coming right away.  The receiver only considers the highest ordered seq packet, and disregards anything older than that.

For packets that must be received once and only once,
I had to start marking these critical packets as “sync” packets, meaning they are important and nothing else will be sent by the client until the server reports back that it got the sync packet, and that it successfully sync’ed it to every client connected to it.

The devil was completely in the details on doing this right.  For example, for a sync packet I had to ensure the seq number was the same during all retransmissions, so they would be processed only once, etc etc.

Key parts of this in the client are below (the server was considerably more complex, since it has to sync to multiple clients where the seqs/acks are different for each one)

..and the actual packet transmission code is below..

Currently, any ClientState (my packet base class) can set itself as a sync packet, once the Client encounters one of those, it’s in syncState mode (and retransmits the same packet over and over) until it’s resolved with an ack as shown above.  In the higher level game code, if the client is in a sync state, I treat the game as if it’s paused (can’t move).

..and lastly, the pertinent sections of the actual UDPConnection class follows below. This is where my game actually touches the OS sockets API. Generally, this API is the lowest level of networking programming available to most applications.

Porting to mobile – A few weeks of work boiled down to one post.

DG on Mobile

After putting roughly 6 months into this project, it seemed stupid not to go the extra mile and release this game for iOS if it was possible to be ran on it.   So that’s what I spent the last few weeks doing, and I eventually reached success (I submitted it to the store for review this weekend).   Disclaimer, much of this post was written using voice dictation so it might not flow as well as a typed document

What it took

Now even though mobile was in the back of my mind, this game was never really designed to run on mobile. The final desktop game took up roughly 1 GB of disk space and 1 gigabyte of RAM running which would slowly rise to 4 GB over time which I suspected and later confirmed to be caused by memory leaks.

To get the game to run on my iPhone 5s, The first thing I did was make some minor modifications to the graphics engine code base to support running OpenGL 3.2 code on an iOS device.  The easiest way to do this, was to simply target the OpenGL ES 3.0 API. The differences between OpenGL 3, and GLES 3.0  are so minor, that this was the best bet that I had for an effortless port of the game.   This sure beat the hell out of the alternative which was to laboriously rewrite my dozens of now-forked shaders in GLSL for OpenGL ES 2.0.   The downside to this however, was that I basically was cutting off any iOS device that could not run OpenGL ES 3.0 (pre-iPhone 5s, pre iPad air).  I still decided to go for it despite all this.

OpenGL ES 3.0 supported so many things that I needed for my game (such as multiple render targets, shadow maps, occlusion queries, etc) that the whole process worked out really well.   Things that used to be near impossible to do on mobile OpenGL were now surprisingly easy to accomplish.

Still, there were some serious challenges that I had to overcome

What sucked and needed fixing

Off the bat, the most serious and challenging problem presented itself almost immediately after running a few levels of the game on my iPhone:  RAM consumption.   Almost immediately, loading the first level resulted in memory warnings and the eventual memory crash caused by allocating too much RAM on the device (this equates to roughly 512 MB on an iPhone 5s).   This almost made me cancel the idea immediately thinking that there’s no way the game could fit as designed on a mobile device.   When I ran the instruments tool, A utility that comes with Xcode to help you trace allocations and such,  I discovered that my sound effects alone were taking up well over 100 megs of RAM.   I also discovered that the heap was growing at an alarming rate between level reloads resulting in the eventual memory crash.   Other assets such as textures and animation data were taking up another hundred megabytes or more (GPU memory is not easily trackable on an iOS device so I could only speculate how much the standard high-resolution desktop textures were taking up).

I used the invaluable “generations” tool of the instruments utility to track down an eliminate my biggest causes of memory leaks.  The funniest one I can remember is the silent failure of the OpenAL alDeleteBuffers call resulting in the leak of ALL sound effects used in the game, including the very large “radio music” buffer which held roughly 1+ minutes of music audio.  Leaking this was wasteful on desktop, but downright devastating on mobile.   Discovering that I had to dequeue the auduo buffer first, solved that issue.  Other stupidities such as bad pointer casting and issues related to C++ 11 smart pointer retain cycles I counted for the other memory leaks.

Apart from the memory leaks, there was a very serious issue that almost crippled the release of the entire game on mobile. This one was not my fault, and it’s related to a arcane bug in the iOS OpenGL 3.0 driver  and how it handles OpenGL occlusion queries.   Leave it to me to always find GL driver bugs in just about every platform I target for my games.   This particular bug caused repeated usage of occlusion queries to eventually crash the whole app inside the driver code. I frustratingly posted this on the Apple developer forums, and got one of the engineers (one of the awesome engineers) to track down the issue and provide a workaround for me which fix the issue.  For those that are curious, the workaround was to run the occlusion queries without an active color buffer attached to the default frame buffer object, bypassing the issue that leads to the crash.

Fixing all these issues however, still would not of been enough to get the game to run on iOS

Optimizations for mobile

To get the game to work “fit” on my iPhone 5s and iOS in general, I had to make the following optimizations

  • UX/controls – The game needed to support a touchscreen interface.  I  accomplished this by adding various touch regions for things like the aiming (touchpad on the left side of the screen), shooting (lower right hand corner of the screen), and vehicle acceleration/deceleration (tilting the device).
  • Compressed reduced-resolution textures – this was probably the biggest deal.   I took advantage of the OpenGL ES 3.0 standard ETC2 compression to pre-compress all textures to this special format.   This allowed me to drastically reduce both the ram and disk space consumption of the texturea for the game.  It also drastically decreased the amount of time it took for the scenes to load, offsetting the load delays caused by the slower CPU on my iPhone.
  • Shortened sound effects – I truncated very long sound effects such as the radio music which were loaded as OGG files.  I reduced these from over one minute to roughly 30 second loops at the longest, drastically reducing the amount of memory taken up by the audio in RAM.  The reason why the sound effects have to exist as full audio buffers has to do with the real-time effects that I apply to them using Open AL in the game.
  • Gzipped scene metadata –  despite already using a binary XML format to store the actual scene data, I found that the disk space usage of all of my scenes was still very high and I could not expect users to download a 1 GB app on iOS.  I fix this by gzipping the project files and live-decompressing them on load (using C++ gzipped file streams).   Despite this adding a very slight CPU performance hit on load, it was worth it for the reduced app size –  which I ultimately got down to roughly 500 MB.
  • Shader optimization –  because many of the game’s shaders were written for a far more powerful desktop GPU,  I had to make optimizations such as reducing precision in some areas and disabling more expensive effects in the game to account for the slower GPUs on mobile.   I also added an option to the game’s main menu to disable the retina display on certain devices and even made this the default on devices such as the iPad Air first-generation.

I also added support for MFI game controllers, a supported API by iOS 7 and above to allow players with physical game pads to get the best gaming experience possible. This was not a big stretch considering the original game was designed for physical buttons in the first place.

After doing all of this crazy stuff, I finally got the game to run reliably without crashing on my iPhone 5s and iPad air.

Victory.

It’s finished! My game is done!

This post was a long time coming.

I can’t believe I’m saying this but over the weekend I completed my longest running game project ever.  At just over six months of development, Driveby Gangster has been finished and submitted to the Mac app store for review!

It almost feels like I’m not really done.  It’s going to take a while for it to settle in the accomplishment of producing and finishing a 3D game of this scale by myself in any reasonable amount of time – especially with a custom from-scratch C++ game engine.  Every 3D Game that I’ve ever tried to make that had any scale larger than a small mini game had to be abandoned due to the loss of focus and eventual giving in to life’s demands.  I definitely wanted to throw in the towel at a couple points and came close to putting the project on hold, but something told me to finish the damn thing now or never!

I’m going to wait a couple weeks, and then post a proper post-mortem of the project and maybe even discuss some of the initial sales (which I expect to be weak due to the competitive nature of the game market these days).

I also plan on live streaming a full play-through of the game on twitch sometime in the coming weeks so stay tuned for that.

For those of you interested in purchasing & playing the game, it’ll be priced at $4 and will feature no stupid freemium or IAP crap ($4 buys the whole thing).  I’ll post the link to the mac app store as soon as it becomes available.

The Windows version is still pending steam green light which could use your help!  So if you want the game for windows, please head over there and vote via the greenlight link at the top of this page!

 

Latest Screens

It’s 1am and I don’t want to go to bed yet.  Thus, I’ll supplement the last post with some of my latest screenshots.

As shown, I now can select my retina mac book pro’s 2880×1800 resolution (and watch it have a disastrous effect on my framerate) as well as support anti aliasing in combination with post processing effects (which is actually alot more work in OpenGL than it would seem).

Tying things up.

It may not seem it from reading this blog, but this game is actually nearing release. Since I’ve last posted, I’ve put all of my efforts into finishing the game during the month of March. All of the levels 1-30 are functionally complete, and Ive moved on to the remaining items on my master todo list. These include implementing cutscenes such as the game over sequence, implementing graphics options such as resolution settings, pause menus, and otherwise polishing the game as much as possible.

I also stumbled onto a hard to detect bug in the SSAO shader settings that made the quality of the SSAO effect in the actual game to be much poorer.  Once I fixed that, I was able to dial the ambient occlusion for the game scenes as I originally intended and it looks really nice (albeit still subtle).

The steam greenlight campaign has slowed quite a bit.  I’ve decided that unless this picks up, or other more popular windows deployment options become available, that the Mac platform will be the initial release for this game.  In other words, I’ll be holding off on the windows version until it gets approved for steam.

More soon.

Push through to the end

After a long vacation abroad during the past month or so, it is a must that this game will meet it’s goal of completion in march.  I’ve pushed through to level 19 today with great progress.  The new newspaper-esque art style looks really good and at this point, it’s just a race to the finish line.  The coolest thing about experimentation sometimes is how you stumble on to a specific kind of rendering style by accident.  I’ve found that by using the same SSAO technique that I have previously implemented while removing the depth-checking produces a dark outline halo around most models in the scene.  While for generalized SSAO this would be undesirable, I love the way it looks and have decided to make it part of the art style for the dark/noire second-half section of the game.  Combining that effect with a lack of the blur post-processing effect on the noisy SSAO results in the very newspaper/comicbook style that I was already going for.  

Needless to say, things are going well now that I’m back at it.

Ambient Occlusion

So I got the ambient occlusion effect implemented in the actual game shader code.  I followed the technique outlined in this article.  I must say, it’s very subtle, but it looks nice.  The real benefit here is that when I turn off the “check depth range” mechanism, I get a very awesome surreal dark outline around all of the models in the scene.  This will be an excellent effect to use when I work on the second half of the game (which will use an artistic black and white noire post processing style signifying the protagonists slowly weakening grip on reality).

I didn’t understand how ambient occlusion worked at all before implementing the effect, but now I must say, I have a pretty reasonable grasp on it.  Basically in one brief description, it takes random samples at every point on the surface to determine how much ambient light from the rest of the scene can reach that point.  In other words, how much of the ambient light is occluded by other nearby surfaces.  This is done by randomly sampling points within a small hemisphere emanating from the surface.  What makes SSAO so nice, is that this technique is approximated entirely in screen space, making it reasonable for real-time rendering in a game.  The downside is it seems to be a little noisy and I see artifacts from time to time on the screen, but hopefully I’ll be able to clean some of that up in time.

Below are some more progress shots showing the kinds of subtle shadowing I can achieve using SSAO in the VGLPP/DrivebyGangster engine.

Ambient Occlusion!

Today was huge!  I am exhausted.  I busted my ass today to get an affect known as screen-space ambient occlusion (SSAO) working in a prototype scene in verto studio.  Right when I was about to give up, I got it working!  I’m too groggy to explain anything about it, so I’ll just post pictures!

This is going to add a huge boost to the visual look-and-feel of the game without a severe performance penalty.  Needless to say, I’m pretty stoked!