The following blog post, unless otherwise noted, was written by a member of Gamasutras community.
The thoughts and opinions expressed are those of the writer and not Gamasutra or its parent company.
Community-driven development is all the rage these days, and for startup indie developers like Payload Studios
this approach allows you to build an audience and raise your profile, at the same time as exploring and developing core gameplay. Game communities are powered by social interaction between players and developers, so if you're trying to grow one, it's essential to find ways to empower and encourage that.
is a game all about creativity and expression. Shared experiences are central to our vision, but synchronous networked multiplayer is a big feature that we don't yet have the resources to add. So, in order to grow our fledgling community, we need to come up with other ways of allowing players to share their creativity with each other (and with us).
It's tough, as a small team, when you have limited resources to draw on and lots of really important things to do! It's always easy to come up with ideas that would be cool; much harder to find ideas that are cool and practical, without sacrificing other priorities. A vehicle design sharing system was something we really wanted to try; but any kind of digital sharing requires network communications and online back-end services, and the prospect of building then maintaining these systems (even using existing components) was not very appealing at this stage of development.
Then we had an idea. What if we could build our sharing system on an existing social network, like Twitter? Send vehicle designs in tweets so Twitter would provide us with a reliable hosting solution, plus built-in social sharing and virality.
Of course, 140 characters is not much data to work with, but tweets can link to other services. What kind of free public service could we piggyback on to host small packages of binary data? Well, a picture sharing service would be perfect. So, all we would need is to encode our vehicle designs into a nice, arresting image (say, a screenshot of the vehicle in question), and we're golden.
And as it turns out, there exists a technology that does exactly that! And it has an amazing name...
The concept of encoding information in a picture goes back at least 500 years in recorded history, and has typically been used as a form of cryptography. The Greek roots of the word mean "hidden writing", and the appeal of the technique for secret communications stems from the fact that a picture can seem innocuous, where a block of coded text may arouse suspicion by being obviously secretive.
In the digital era, it's easy to disguise data very thoroughly, as the human eye is incapable of distinguishing tiny variations in the colours of 32-bit pixels. Tools for doing this are freely available. Here, for example, is an online demo tool
that will encrypt and decrypt messages in pictures.
Below is a before-and-after picture of a stegosaurus (see what I did there?) containing the opening scene from a well-known movie script encoded using the mobilefish demo. The difference is imperceptible. Try saving the second image and decoding it
yourself: the password is "clevergirl". (No prizes for guessing the movie!)
Of course, we are not trying to do anything secretive in TerraTech - we're just using a picture as a carrier for a payload of non-secret data. This means that for our vehicle sharing system a very rudimentary form of steganography will do the job.
We already have tech in the game to encode a vehicle design in a reasonably economical manner: a list of piece names, each with a position and a rotation. So, having saved the current player vehicle into one of these, we just need to serialise it into a byte stream, which is easy with standard .NET classes, and then encode the bytes into pixels of a screenshot.
Then we encode the result into a PNG file ready to save, upload or otherwise share. This last step again is easy with builtin Unity APIs. So, our outer logic calls the EncodeInPixels() function, which takes an array of bytes and the pixels to encode them into, returning the number of pixels it modified. It can also start from an offset position - so that we can encode several streams of data in sequence.
The encoding logic uses the exact, very basic, algorithm described on Wikipedia's page on steganography
: store one bit of information in the least significant bit of each colour value of each pixel. That's 3 bits per pixel: we'll ignore alpha, because we don't want any partial transparency causing unexpected effects.
The reverse process is equally straightforward. Load an image, extract pixel data and reconstruct a stream of data by concatenating a single bit from each R, G and B value. Finally, deserialise the resulting stream into the structure that represents a vehicle design, which can then be spawned as a brand new vehicle.
Making it better
We now have the ability to save a vehicle design embedded in a screenshot. This is great, but what happens if we decide to add more information into the tank design, like a callsign, or custom livery? All our old saves will break if we change the format. To guard against that, it's important to build in a versioning system. It doesn't take a lot of work, I just prepend the stream with a version identifier that we'll update if we change the implementation. I'm using the letter "A". Here are the relevant changes:
If I decide to compress the saved data scream in future, for example, I'll update formatVersion to 'B'. Then in LoadVehicleDesign, I'll add a new case to the switch statement to read the new format, while keeping the 'A' case unchanged so I can still load older saves.
It's all very well having some code that works, but we need to present the feature clearly so it feels nice to use. This means adding a button on the GUI, firstly, and we'll also crop the screen capture to a central region, framing the vehicle, rather than grabbing the whole screen. To emphasise this, we'll fade the non-captured screen area and add a camera flash effect and shutter sound.
Grab the free demo
if you want to see this in action! Of course, saving vehicles isn't much use without being able to browse and load them too, so we need a scrolling menu to select an image to load from the contents of a folder.
Wrapping it up
The final piece of the puzzle is to share the encoded designs on Twitter. After saving a captured design, we display a "Tweet This?" button at the side of the screen, which prompts the user to tweet, after first authenticating with their Twitter account. For loading shared designs, we provide two alternative Load menus, one of which searches your own tweets and the other searches all tweets with the #myTerraTech hashtag, which we automatically include in the tweets we generate.
There are plugins available on the Unity Asset Store for Twitter integration, and we looked at some of them, but they tend to be platform specific, and we weren't keen on licensing separate packages for Windows, Mac etc. We wanted one solution to cover all platforms, that would handle all our search parameters.
Eventually we hit upon a combination of Spring.NET
, to provide an API wrapper for stuff like hashtag searches and picture uploads and this test project
to handle authentication. The full details of the implementation are beyond the scope of this article, but if you want to know more, please leave a message on our website
. If we get enough interest we'll look at tidying up the code and making it available to others.
There's one more piece to the puzzle. Those APIs work, but since the Twitter API 1.1 oAuth update, it's not straightforward to get the initial authentication tokens that you receive when you log in for the first time. The system is designed to work in a browser. We were easily able to launch an external browser for login, but this required the user to copy and paste a passcode back into the game - a horrible user experience.
So, we bit the bullet and decided to integrate a browser directly into the game. We used the cross-platform uWebKit plugin
, which is perhaps a little heavyweight for what we need, but works. We display the login dialog in game by actually displaying the Twitter website, and automatically parsing the passcode after successful login.
It's not an ideal solution - as well as bloating our game binary, we have some tricky edge-case bugs that can occur when users don't login successfully and then click around some of the links that come up. We'll probably need to strip this down and use a more limited browser implementation for the login step in future, but for now it gets us where we need to go!
Out steganography-powered content sharing system has been a big win for us so far. We've stimulated a huge amount of player-generated content sharing (check out the #myTerraTech hashtag
!), and created a cool way for our fans to engage with the dev team.
Every weekday, on our 5pm livestream
(UK time), we load up the best fan-created designs that have caught our eye, and play around with them. We also run weekly design competitions where players use Twitter to send us designs that we run through pre-defined trials on the stream.
In our latest demo build
, we've added a head-to-head challenge mode called Sumo Showdown, where players can test their designs against each other too, either in an automated AI-driven stand off, or in local multiplayer with up to 4 competitors - the last one standing wins.
It's a great example of how a flexible solution can go way beyond the problem it was originally designed to solve. We originally came up with this as a way to allow players to share designs, and because the technique was not bound heavily to one specific use case, we've been able to take it much further, and are now building new gameplay on top of it.
I hope this walkthrough will prove useful to other developers looking for creative ways to boost their community engagement. If you would like to learn more about TerraTech and get involved with our community, please follow us on Twitter @TerraTechGame or take a moment to look at our Kickstarter page
, and consider backing us.