Before we begin with an explanation of the implementation, it is important to know what our goals where for this game. We had three primary goals when building this game.

The game must scale to handle several hundred thousand concurrent users.*

The architecture must be cost effective.

The architecture must be flexible enough for different types of games.

* This is the goal, but there are still some known limitations in the current version that would prevent this. I will be writing more about that later.

Now, I want to write about the use and implementation of blob storage in Tankster.

Why to use blob storage? If you play Tankster in practice mode, the Javascript client doesn’t use the Azure backend. Javascript can access web role and blob storage via Ajax/JSON calls. But in multi-player game (there is one kind of game, named Skirmish), each player client code polls the blob storage to get the game status (tank shots, chat messages, other status). But again, why blob storage? There are money reasons (cost of each access to Web Role service API vs. cost of read a blob), but I don’t know about Azure prices (you know, MVPs don’t touch the money ;-). But there is another reason: to spread the workload, given some air to web role instances.

There is an AzureBlobContainer class in Tankster.Common library project:

The class use generics. Type T could be a Game, GameQueue or another .NET type. You can reuse this class in other projects: it’s “game agnostic” code. The many constructors add flexibility for testing purpose.

The object (type T) is serialized to JSON. AND not only JSON: note that a there is a Callback (you could remove this part if you don’t need this feature in your project). Then, a game object is saved as (I stolen …errr… borrowed 😉 this code from Nathan’s post):

JSONP or “JSON with padding” is a complement to the base JSON data format, a pattern of usage that allows a page to request data from a server in a different domain. As a solution to this problem, JSONP is an alternative to a more recent method called Cross-Origin Resource Sharing.

Under the same origin policy, a web page served from server1.example.com cannot normally connect to or communicate with a server other than server1.example.com. An exception is the HTML<script> element. Taking advantage of the open policy for <script> elements, some pages use them to retrieve Javascript code that operates on dynamically-generated JSON-formatted data from other origins. This usage pattern is known as JSONP. Requests for JSONP retrieve not JSON, but arbitrary JavaScript code. They are evaluated by the JavaScript interpreter, not parsed by a JSON parser.

If you are a newbie to JSON and JSONP, this is a short tutorial/example using JQuery (the same library used by Tankster client code):

One problem to point: note that the callback name is “hardcoded” in blob storage. The gamesCallback present in game status blob should be the name of a global function. But you can change the blob text to whatever valid Javascript code.

And the client code? You can study the gskinner code at Tankster.GamePlay web project, under src\ui\net\ServerDelegate.js:

See the ‘gameStatus’ polling: it uses ‘jsonp’ as format. My guess: the ‘gamesCallback’ parameter is not needed: you can use any other name, the function to call resides in the blob content.

I think there are alternatives to game status. The blob reflects the Game entity (see Tankster.Core\Entities\Game.cs). But it could be implemented in two blobs by game:

– One, having the initial status (players, positions,etc…) and the list of ALL the history of the game (think about to implement a chess or go game, you need to save the history).

– Another one, having the “news” (last 10 seconds of game actions). So, the data to poll should be shorter.

The price to pay: web role service should update both. But that update only occurs when a player sends a move (shot, chat…). The poll of game status occurs in every client, triggered by a repeated timeout. Actually, the game blob keeps the last 10 seconds actions AND initial status, weapons, etc…. Each client polls that info. In case a client disconnects and reconnects, it could poll the “complete game” blob to be in sync again.

The separation of that info in two blobs should improve the scalability of the solution. But you know: premature optimization is the root of all evil ;-). If you take that way of store and retrieve games, you should run some stress or/and load tests to have a really measure of such decision impact.

More Tankster code analysis, patterns, and social game dev in general: coming soon.

Git is a distributed revision control system with an emphasis on speed.[3] Git was initially designed and developed by Linus Torvalds for Linux kernel development. Every Git working directory is a full-fledged repository with complete history and full revision tracking capabilities, not dependent on network access or a central server. Git’s current software maintenance is overseen by Junio Hamano. Git is free software distributed under the terms of the GNU General Public License version 2.

Domain-driven design (DDD) is an approach to developing software for complex needs by deeply connecting the implementation to an evolving model of the core business concepts.[1] The premise of domain-driven design is the following:

Placing the project’s primary focus on the core domain and domain logic

Basing complex designs on a model

Initiating a creative collaboration between technical and domain experts to iteratively cut ever closer to the conceptual heart of the problem.

Domain-driven design is not a technology or a methodology. DDD provides a structure of practices and terminology for making design decisions that focus and accelerate software projects dealing with complicated domains.

Tankster.GamePlay is a Web Role. The only worker role is Tankster.WorkerRole. Tankster.Core is a class library. There are interesting code at Tankster.Common: Azure utilities to access repositories, a job engine; all its code is game-agnostic.

These are my first short comments about the code and implemented features (remember, is a beta! Some of these features/implementations could change in the next release):

– Client technology: HTML5, Javascript, EaselJs (for canvas programming).
– Server technology: ASP.NET MVC 3, some Razor test views (interesting topic: how to test the game without the REAL game), WCF Web API (another interesting topic to discuss: alternative technologies to received the game activity)
– There is a client game model and entities in Javascript. See src/model, src/game.

– There is a server game model (see Tankster.Core class library project)

– You can play in single player mode, but you can choose multi-player online. Then, the game uses ACS Portal to login using Federated Authentication:

There are a lot of points to comment and discuss, feed for upcoming posts. Surely, the solution will evolve and new versions will be published (this week? next week?). But it is interesting to have a published game online AND the code to analyzes it.

You know, I’m a big fan of Farmville. It pushed me to organize my days, using the rhythms of harvests. It’s a control of my daily agenda: if I seed in my farm, then I reserved the time to harvest. And it’s a game you can play alone, without bothering other players.

But I digress, the topic is game programming, not Farmville ;-): the problems and challenges of programming social games. Curiously, the most successful games in industry are online games and not the most sophisticated ones: instead of 3D real time games, Farmville is a one-player, with a simple 2D rendering. The social game challenges are not in graphics and user experiences.

In this series, I want to enumerate the patterns and solutions we can use in social/online games. I’m not an expert in the topic: game development is not in my expertise (yet ;-). But for me, it’s a way to gain understanding of the problems and possible ways to solve them in such kind of development. It pushes me to learn new technologies, libraries, tools, and concepts.

Maybe I could write two simple examples (one-player, turn-based), but I should review my schedule to have enough time for that activity. It would be a good excuse to exercise REST, Javascript, JQuery, PHP, Azure, artificial intelligence? 😉