Kotan Code 枯淡コード

In search of simple, elegant code

Menu Close

Tag: gaming

Creating a Multiplayer Chat System with the Akka Event Bus

In my previous blog post, I talked about how to use the subchannel classification system with the Akka Event Bus. In that post, I showed a really simplistic way of determining if a channel is a subclass of another – using startswith(). That’s a really primitive way of doing things and doesn’t really show you the true power of the event bus.

In this blog post, I want to walk you through a slightly more realistic example. Let’s assume that we’re using Akka to build the back-end for a multiplayer game. We know that this game needs to support chatting between players, so we want to create an event bus to handle all of the chat traffic for the game. This should, in theory, give the system some nice flexibility in allowing individual players and player-actor components to subscribe and unsubscribe from different segments of the chat traffic.

We have three different segments that we want to divide traffic up into:

  1. Players – Individual players can receive private chat messages, or tells.
  2. Sectors – The players’ space ships are floating in 3D space in large areas called sectors. It is possible for those players to transmit messages to an entire sector.
  3. Groups – Players can form small groups where from 1 to 8 players band together to share experience as well as their own chat channel.

One of the interesting things to keep in mind is that our chat bus cannot read player state. In order for the chat bus to be really useful, general purpose, and, most importantly, testable, it can’t go reaching into the inside of some player object to figure out which sector object they are in or to which group they belong.

So we’re going to revise our previous sub-classification event bus sample with a new case class called ChatCoordinate that will be used as our classifier (remember in the previous blog post we used simple strings). Here’s the new code for the bus and its messages:

package chatbus

import akka.event.ActorEventBus
import akka.event.LookupClassification
import akka.event.SubchannelClassification
import akka.util.Subclassification
import akka.actor.ActorSystem
import akka.actor.Props
import akka.actor.Actor

/*
 * Chat Bus Coordinates
 * players/XXX - sends a private tell to a player
 * sectors/XXX - sends a tell to an entire sector
 * groups/XXX - sends a tell to members of a player group
 */
object ChatSegments {
	val Player = "players"
	val Sector = "sectors"
	val Group = "groups"
}

case class ChatCoordinate(segment: String, target: Option[String])

sealed trait Chat
case class ChatMessage(source: String, message: String) extends Chat
case class ChatEvent(coord:ChatCoordinate, msg: ChatMessage) extends Chat

class ChatEventBus extends ActorEventBus with SubchannelClassification {
  type Event = ChatEvent
  type Classifier = ChatCoordinate

  protected def classify(event: Event): Classifier = event.coord

  protected def subclassification = new Subclassification[Classifier] {
    def isEqual(x: Classifier, y: Classifier) = (x.segment == y.segment && x.target == y.target)

    /* Is X a subclass of Y? e.g. is Player/Bob a subclass of Player/None? YES. Is Player/None a subclass of Player/Bob? NO. */
    def isSubclass(x: Classifier, y: Classifier) = {
		val res = (x.segment == y.segment && x.target == None)
		//println(s"Subclass check: $x $y: $res")
		res
	}
  }

  protected def publish(event: Event, subscriber: Subscriber): Unit = {
    subscriber ! event.msg
  }
}

This new chat bus gives us some great flexibility. I can send a message to all players by sending a message to the Players segment with a target of None. I can send a message to all groups by sending a message to the Groups segment with a target of None, a specific group by sending to Groups/Some(“GroupId”) and a specific player by sending to Players/Some(“Player Id”).

One of the aspects of gameplay that this chat bus supports is a player moving from one sector to another. If a player leaves a sector, then ideally some actor (maybe a Player actor?) would unsubscribe from the chat bus @ Sectors/Some(“Foo”) and then subscribe to the chat bus @ Sectors/Some(“Bar”) if they moved from sector Foo to sector Bar, while always maintaining a persistent subscription to Players/Some(“Player ID”). Likewise, if a player joins a player group, they would subscribe to Groups/Some(“Group ID”) and unsubscribe from that same coordinate when they leave the group.

The system is inherently extensible and so whenever we want to add a new segment (e.g Race, Alliance, Guild, etc) we can just drop that in there and we’re good to go.

Finally, just so you believe me, here’s some Scala Test specs exercising the chat bus with some fake actors:

package tests

import akka.actor.ActorSystem
import akka.actor.Actor
import akka.actor.Props
import akka.testkit.TestKit
import akka.testkit.TestProbe
import org.scalatest.WordSpecLike
import org.scalatest.Matchers
import org.scalatest.BeforeAndAfterAll
import akka.testkit.ImplicitSender
import scala.concurrent.duration._

import chatbus._

object ChatBusSpec {
	
	val toKevin = ChatEvent(ChatCoordinate(ChatSegments.Player, Some("Kevin")), ChatMessage("system", "This goes just to Kevin"))
	val toBob = ChatEvent(ChatCoordinate(ChatSegments.Player, Some("Bob")), ChatMessage("system", "This goes just to Bob"))
	val toAllPlayers = ChatEvent(ChatCoordinate(ChatSegments.Player,None), ChatMessage("kevin", "This goes to all players"))
	
	val toSectorAlpha = ChatEvent(ChatCoordinate(ChatSegments.Sector,Some("Alpha")), ChatMessage("system", "Sector Alpha is about to explode."))
	val toSectorBeta = ChatEvent(ChatCoordinate(ChatSegments.Sector,Some("Beta")), ChatMessage("system", "Sector Beta is about to explode."))
}

class ChatBusSpec (_system: ActorSystem) extends TestKit(_system) with ImplicitSender
  with WordSpecLike with Matchers with BeforeAndAfterAll {
 
  import ChatBusSpec._

  val theProbe = TestProbe()

  def this() = this(ActorSystem("ChatBusSpec"))

  def getEchoSubscriber() = {
	system.actorOf(Props(new Actor {
	    def receive = {
	      case m:ChatMessage => theProbe.ref ! m
	    }
	}))	
  }
 
  override def afterAll {
    TestKit.shutdownActorSystem(system)
  }

  "A chat event bus" must {
     "send a private message to a player with no snoopers" in {
		val eventBus = new ChatEventBus
		val kevin = getEchoSubscriber()
		val bob = getEchoSubscriber()
		eventBus.subscribe(kevin, ChatCoordinate(ChatSegments.Player, Some("Kevin")))
		eventBus.subscribe(bob, ChatCoordinate(ChatSegments.Player, Some("Bob")))
		eventBus.publish(toKevin)
		theProbe.expectMsg(500 millis, toKevin.msg)
		theProbe.expectNoMsg(500 millis)
     }	

     "send a single message to all players" in {
		val eventBus = new ChatEventBus
		val kevin = getEchoSubscriber()
		val bob = getEchoSubscriber()
		eventBus.subscribe(kevin, ChatCoordinate(ChatSegments.Player, Some("Kevin")))
		eventBus.subscribe(bob, ChatCoordinate(ChatSegments.Player, Some("Bob")))
		eventBus.publish(toAllPlayers)
		// Each player should receive one of these, so the probe should bounce it back twice.
		theProbe.expectMsg(500 millis, toAllPlayers.msg)
		theProbe.expectMsg(500 millis, toAllPlayers.msg)
     }

     "send to all players in a sector should only deliver once per player" in {
		val eventBus = new ChatEventBus
		val kevin = getEchoSubscriber()
		val bob = getEchoSubscriber()
	
		eventBus.subscribe(kevin, ChatCoordinate(ChatSegments.Player, Some("Kevin")))
		eventBus.subscribe(kevin, ChatCoordinate(ChatSegments.Sector, Some("Alpha")))
		eventBus.publish(toSectorAlpha)
		theProbe.expectMsg(500 millis, toSectorAlpha.msg)
		theProbe.expectNoMsg(500 millis)
     }

     "support a player moving from one sector to another" in {
		val eventBus = new ChatEventBus
		val kevin = getEchoSubscriber()
		
		eventBus.subscribe(kevin, ChatCoordinate(ChatSegments.Player, Some("Kevin")))
		eventBus.subscribe(kevin, ChatCoordinate(ChatSegments.Sector, Some("Alpha")))
		eventBus.publish(toKevin)
		theProbe.expectMsg(500 millis, toKevin.msg)
		eventBus.publish(toSectorAlpha)
		theProbe.expectMsg(500 millis, toSectorAlpha.msg)
		eventBus.unsubscribe(kevin, ChatCoordinate(ChatSegments.Sector, Some("Alpha")))
		eventBus.subscribe(kevin, ChatCoordinate(ChatSegments.Sector, Some("Beta")))
		eventBus.publish(toSectorBeta)
		theProbe.expectMsg(500 millis, toSectorBeta.msg)
     }
  }
	
}

Building an MMO Server in Akka : Using MongoDB as a Backing Store

The story so far: I’ve created an Akka application that is using non-blocking Akka IO over sockets to communicate via Google Protocol Buffers with iOS (or potentially others…) clients. In the last blog post, I created some Actors that allow objects that have a physical presence in space to respond to messages, namely radar pings. This allows objects to “appear” to players. Their client will get radar pong messages, which will allow the client GUI to create icons for the items in the radar pong like planets, star ports, ships (owned players or NPCs), harvestable asteroids, and so on.

That’s all well and good, but in the last blog post, I had to hard code things like the name, description, and location of the objects in the universe. The first thing I needed to do was to refactor the PhysicalObject trait … in the last iteration it had “magic knowledge” of the types of physical objects that might be using that trait. So here’s my new physical object:

package com.kotancode.ulysses.space

import com.kotancode.ulysses.space.Vector3D._
import akka.actor._

case class RadarPing(source: ActorRef, origin: Vector3D, scanDistance: Int)
case class RadarPong(source: ActorRef, origin: Vector3D, objectType: Int, name:String, description: String)

object RadarObjectTypes {
	val Planet = 1
	val Station = 2
	val Port = 3
	val Ship = 4

	val Unknown = 99
}

trait PhysicalObject extends Actor with ActorLogging {
	def replyPong(p:RadarPing): Option[RadarPong]

	def receiveSpatial: Receive = {
		case p:RadarPing => {
			replyPong(p).map { pongReply => p.source ! pongReply }
		}
	}
}

There’s a couple of new things happening here. First, this trait no longer has a member variable called location. Second, in the last iteration, this trait constructed the pong reply itself. This would have been really problematic because I would have ended up with one method with a pile of “switch” cases to determine how it should reply in different circumstances… and that would’ve been smelly. Now, it is up to the actor using this trait to define a method that creates pong replies. Also, note that the abstract method that the concrete actors will implement returns an Option so I can just run a map over that – if the method returns a None then the above code won’t deliver the pong message.

Now that I’ve cleaned up my physical objects (to make them easier to be instantiated dynamically based on data from a backing store like Mongo), I can create a Persistable trait:

package com.kotancode.ulysses.state

import akka.actor._
import com.mongodb.casbah.Imports._
import org.bson.types.ObjectId

case class LoadState(id:String)
case object PersistState

object BackingStoreKeys {
	val Name = "name"
	val Location = "location"
	val Description = "description"
	val ID = "_id"
}

trait Persistable extends Actor {
	var backingObject: MongoDBObject = null

	def receivePersistable: Receive = {
		case LoadState(id) => {
			loadFromMongo(id)
		}
		case PersistState => {
		  // Nothing here yet...
		}
	}

	def persistenceCollectionName:String

	def loadFromMongo(id:String) = {
		val mongoClient = MongoClient()
		val ulysses = mongoClient("ulysses")
		val collection = ulysses(persistenceCollectionName)
		val objectId = new ObjectId(id)
		backingObject = collection.findOne(MongoDBObject(BackingStoreKeys.ID -> objectId)).getOrElse { throw new IllegalArgumentException(s"id ${id} not found in ${collection}")}
		println(s"backing object ${backingObject}")
	}
}

Here I’m using the Casbah library for Scala to talk to MongoDB. What’s worth mentioning here is that the only way a persistable actor should load its state is after it has received a message to do so. This keeps the data-loading activity in the thread-safe message pattern already enforced by Akka, so I don’t have to worry about race conditions where I have to delay some activity until after my reference data has been loaded (this is a common problem I see regularly in message-based applications).

Let’s see what our new, cleaner Planet actor looks like now:

package com.kotancode.ulysses.space

import com.kotancode.ulysses.space.Vector3D._
import com.kotancode.ulysses.state.Persistable
import com.kotancode.ulysses.state.BackingStoreKeys
import com.mongodb.casbah.Imports._

import akka.actor._

object Planet {
	val BackingCollectionName = "planets"
}

class Planet extends Actor with PhysicalObject with Persistable {

	override def persistenceCollectionName = Planet.BackingCollectionName

	override def replyPong(ping:RadarPing): Option[RadarPong] = {
		val currentLocation = Vector3D.fromBackingObject(backingObject.as[BasicDBObject](BackingStoreKeys.Location))
		if ( (currentLocation distanceFrom ping.origin) < ping.scanDistance) {
			Some(RadarPong(self,
				currentLocation,
				RadarObjectTypes.Planet,
				backingObject.as[String](BackingStoreKeys.Name),
				backingObject.as[String](BackingStoreKeys.Description)
			))
		}
		else {
			None
		}
	}

	def receivePlanet: Receive = {
		case _ => log.debug("Received some message for a planet.")
	}

	def receive = {
		receivePersistable orElse receiveSpatial orElse receivePlanet
	}
}

In my Mongo database, the location field contains a nested object with the properties x, y, and z. The Vector3D class has a utility method on it (I will refactor this into a “pimp” or “augment” pattern later) that converts a Casbah BasicDBObject into a 3D vector by extracting these properties.

Finally, remember that Universe class? The one that hard-coded the instantiation of the “Utopia 1” planet? Here’s what it looks like now:

package com.kotancode.ulysses.space
import com.kotancode.ulysses.state.LoadState
import com.kotancode.ulysses.state.Repository

import akka.actor._

class Universe extends Actor with ActorLogging {

	def loadPlanets = {
		for (id <- Repository.allIds(Planet.BackingCollectionName)) {
			context.actorOf(Props(new Planet()), name=id) ! LoadState(id)
		}
	}
	override def preStart() = {
		loadPlanets
	}

	def receive = {
		case p:RadarPing => context.children foreach (_.forward(p))
		case _ => log.debug("Received a universe message")
	}
}

Here I’m just making use of a simple object I created called Repository that issues a Casbah query to Mongo – it’s an empty query on a collection so it returns all the objects and then converts the Object IDs into strings and yields them so they can be used in an enumerator, as shown in the above code.

Now, instead of having a hard coded planet, I can create multiple planets in my database and this code will instantiate an actor for each of those planets, each planet will be backed by its own unique Mongo DB document. Here’s some trace log output that shows a pong reply from each of the 3 planets I created in my MongoDB:

[DEBUG] [03/24/2013 08:31:12.998] [UlyssesAgenda-akka.actor.default-dispatcher-1] [akka://UlyssesAgenda/user/ServerCore/Clients/96e1e42b-5cda-4faa-aa89-019c2bde9794] I received a radar pong RadarPong(Actor[akka://UlyssesAgenda/user/ServerCore/Universe/514de823b485acb28e02bb91],(5.0,5.0,5.0),1,Utopia 1,This is a utopian planet, chock full of win.)

[DEBUG] [03/24/2013 08:31:12.999] [UlyssesAgenda-akka.actor.default-dispatcher-1] [akka://UlyssesAgenda/user/ServerCore/Clients/96e1e42b-5cda-4faa-aa89-019c2bde9794] I received a radar pong RadarPong(Actor[akka://UlyssesAgenda/user/ServerCore/Universe/514e194004538147414b4675],(6.0,6.0,6.0),1,Utopia 2,This is a little less utopian than the other one.)

[DEBUG] [03/24/2013 08:31:12.999] [UlyssesAgenda-akka.actor.default-dispatcher-1] [akka://UlyssesAgenda/user/ServerCore/Clients/96e1e42b-5cda-4faa-aa89-019c2bde9794] I received a radar pong RadarPong(Actor[akka://UlyssesAgenda/user/ServerCore/Universe/514e19b304538147414b4676],(7.0,7.0,7.0),1,Doom,Every game needs a planet doom.)

Now that I’ve got the core framework for persistence up and running, I can do some more useful things like giving players persistence so I can keep their names and locations separate. Once I have that, I can move on to creating the most basic of the actual gameplay functions.

Building an MMO Server in Akka: Objects in Space

I originally wanted to call this post Piiiiiiiggssss innnn Spaaaaace in homage to the Muppet Show, but I figured it would make it harder for people to actually find this content, so, we’re stuck with the boring title for now. In my previous blog post, I talked about enabling multiplayer and rigging up the essential infrastructure to support multiple players within an Akka-backed MMO universe.

So, we’ve got an iPad client (haven’t shown you this yet, mostly because it has no graphics) that connects to our Akka server. This iPad client sends a SignIn protobuf message and then, to keep the test going, sends itself a DirectMessage protobuf message. That’s all well and good if we’re building an MMO chat game, but this is a universe and, sooner or later, we’re going to have to put stuff in our universe.

So let’s take a look at some of the things that we think our stuff in this universe is going to need to do. Firstly, it’s going to need to exist at some point in space, e.g. a coordinate. All of the stuff that exists in space is only discovered by the player by virtue of appearing on their radar scan. I haven’t designed all this out yet, but I know that players who have invested more time and money in their ship’s navigational and scanning equipment will be able to see more stuff, see further out into space, and glean more information from what happens to be out there. Whether that stuff is visible may also have something to do with the thing itself. For example, I might have a cloaking device (though I’d probably have to call it something else, for fear of copyright infringement) which might make it so that cloaked stuff doesn’t appear on radar.

In other words, this is a very quantum style universe – you don’t actually know what’s in it until you inspect it, and the act of inspecting it can alter the results. I might, in the future, decide to code a sneaky NPC that waits to be radar scanned by nearby players and then automatically targets the source of that scan.

So what I’ve decided to do is create a sub-tree of my actor system hierarchy for physical things that exist in space, which includes planets, space ports, ships, star ports, and other stuff that might be harvestable for resources like asteroids and moons. For starters, these things can all be sent a RadarPing message which ultimately originates from a player. These things can then respond to that ping with a RadarPong. The iPad client can then collect radar pongs and use that to dynamically populate a star map of the “nearby universe”. Cool, huh?

So let’s start with the universe:

package com.kotancode.ulysses.space

import akka.actor._

class Universe extends Actor with ActorLogging {
	// create some child objects
	val testPlanet = context.actorOf(Props(new Planet()), name="Utopia1")

	def receive = {
		case p:RadarPing => context.children foreach (_.forward(p))
		case _ => log.debug("Received a universe message")
	}
}

So what we’re doing here is if I send the universeRadarPing message, that message then gets sent to all physical objects within that universe. If the object is out of range of the ping or is cloaked (or something else), then it won’t respond. Otherwise, it will comply and send back a RadarPong message. I know off the bat that I’m going to have many different types of actors that act as physical things in my universe, so this seems like the right time to bust out a trait that encapsulates this behavior:

package com.kotancode.ulysses.space

import com.kotancode.ulysses.space.Vector3D._
import akka.actor._

case class RadarPing(source: ActorRef, origin: Vector3D, scanDistance: Int)
case class RadarPong(source: ActorRef, origin: Vector3D, objectType: Int, name:String, description: String)

object RadarObjectTypes {
	val Planet = 1
	val Station = 2
	val Port = 3
	val Ship = 4

	val Unknown = 99
}

trait PhysicalObject extends Actor with ActorLogging {
	private var location = (6.5, 5.0, 7.2)
	var name = "Game Object"
	var description = "This is a game object"
	var objectType = RadarObjectTypes.Unknown

	def receiveSpatial: Receive = {
		case p:RadarPing => {
			log.debug(s"I received radar ping ${p}, it originated ${p.origin distanceFrom location} units from my location at ${location}.")
			if ( (p.origin distanceFrom location) < p.scanDistance) {
				p.source ! RadarPong(self, location, objectType, name, description)
			}
		}
	}
}

Since my game doesn’t currently have persistence, I’m making up hardcoded values for the planet but, in the future, the planet would ideally reach into some database, identify itself, and then pluck out a map of all of its data, such as its spatial coordinates. The Vector3D class I created back when I was writing a MUD in an earlier version of Akka, and it basically allows me to take a 3-tuple (e.g. (5.0, 1.5, 2.5)) and implicitly turn that into something that supports basic cartesian math. You can see this in the line of code that contains p.origin distanceFrom location, which utilizes the distanceFrom method that I added to my Vector3D class.

Now how about we create a planet that includes the PhysicalObject trait?

package com.kotancode.ulysses.space

import com.kotancode.ulysses.space.Vector3D._
import akka.actor._

class Planet extends Actor with PhysicalObject {

	objectType = RadarObjectTypes.Planet
	name = "Utopia 1"
	description = "This is a utopian planet, chock full of epic win."

	def receivePlanet: Receive = {
		case _ => log.debug("Received some message for a planet.")
	}

	def receive = {
		receiveSpatial orElse receivePlanet
	}
}

This is a pretty simple class and you can see that I’m doing some more hard-coding of values to serve as placeholders until I deal with the persistence deal (remember the YAGNI portion of the Agile Manifesto?). What I really like here is the receiveSpatial orElse receivePlanet partial function chaining. This lets me grab the receive function from the PhysicalObject trait and chain on the receive function from the Planet actor. I don’t have any planet-specific messages but you can imagine I might have messages like Land and TakeOff for when players bring their ships into orbit, etc.

Almost done. We’ve got a planet, which includes the physical object trait (and with it the associated message handling and state … I freaking love traits), and we’ve got a universe that contains the planet. Now we just need to send out radar pings. Rather than make the iPad client manually send radar ping packets, we can use an Akka scheduler on the server side to force the player’s proxy (GameClientProxy actor) to issue the RadarPing to the Universe object periodically.

Here’s the new code for my GameClientProxy class’ preStart() actor method:

lazy val universe = context.actorFor("../../Universe")

override def preStart() = {
	log.debug(s"GameClientProxy pre-start, socket uuid: ${socketHandle.uuid}")
	implicit val timeout = Timeout(1 second)
	import context.dispatcher
	SocketServer.system.scheduler.schedule(
		10 seconds,
		10 seconds,
		universe,
		RadarPing(self,  (5.0, 5.0, 5.0), 10)
	)
}

That’s pretty much it. We know from the code above that we’re going to be sending pongs directly back to the player proxy actor, so we need to respond to that. In the near future, this will involve creating a protobuf object and writing it back out to the client over the socket connection, but for now we’ll just log the fact that we got the pong back:

def receive = {
	case m:DirectMessage => {
		log.debug("I received a direct message.")
		writeRawMessage(m, MessageTypes.DirectMessage)
	}
	case pong:RadarPong => {
		log.debug(s"I received a radar pong ${pong}")
		// writeRawMessage(new raw pong protobuf ...)
	}
}

So that’s it… In just a few quick steps with a few small, lightweight actors, I’ve given my universe the ability to expose an infinitely expandable list of objects to players by virtue of modeling a message-based radar system. I’m nowhere near the point where I can add combat yet, but I’m adding building blocks slowly, which is always fun to do. I think next I’ll work on the “universe map” display for the iPad and possibly figure out a persistence method so I can load planets from my database.

Building an MMO Server in Akka : First Steps Toward Multiplayer

As you can imagine, building a Massively Multiplayer Online Game (MMOG, or MMORPG for “roleplaying” types, also you may have seen MMORTS for online real-time strategy games) is no small task. In fact, it’s pretty daunting. However, the technology we have now, including hardware, software, and virtualization, makes it possible to scale these games to incredible sizes.

To put it in perspective, EverQuest, what I consider the first truly huge, commercially successful MMO (yes, Ultima Online was first, but EQ quickly rose to eclipse UO’s volume), during one of the periods where I was playing, used to have a per-server capacity of around 1700-2000 players. Once our buddies started noticing that the number of players online in a particular server went up close to 2000, many of us started running like hell for the nearest safe spot, city, or useful campground.

Today, while still sharding out its content across a ridiculous number of servers, games like World of Warcraft not only have vastly more content and interaction than EQ did, but each shard can hold many more players. Being able to create a server that can handle that kind of scale and respond to messages from player clients in real-time is a daunting task. The sheer number of minutiae that you need to get absolutely perfect for things to work properly is mind-boggling.

The EverQuest servers, as well as similar servers for games that came shortly thereafter like Anarchy Online, were written in C++. To handle the volume of information from that large a number of simultaneous players, they had to manage their own threads, they had to do absurd low-level optimizations, and they had to make sure that every single line of code on that server was as fast and stable as possible. An entire shard (server process, or, later in EQ’s life, a cluster of server processes) simply could not crash. People paying $10-15/month for the privilege of playing the game (a concept which was brand new and controversial at the time) would not tolerate a server crash.

I am just one person, and giant game companies have entire armies of developers. How can I possibly hope to make an MMO server that players will actually use? Simple. Standing on the shoulders of giants. I don’t need to write all the low-level stuff, I don’t need to write the distributed grid-style asynchronous computing fabric that should underpin my game logic. It’s been done for me, and it’s called Akka.

You may have seen some of my previous blog posts where I talk about some of the low-level details like google protocol buffers and creating a non-blocking socket server using Akka IO. The next step toward being able to build an MMO is the core functionality required for a multiplayer game: asynchronous message routing and transmission.

The data flow for an MMO works something like this: A message comes into your server’s gateway (in my case, a non-blocking socket server). The gateway then does whatever it needs to do with the message and dispatches it accordingly. The message, or a version of it, then floats its way through the “business logic” (your game core) and as a result of it entering and executing your game logic, 0..n messages will be emitted as a result. Some of those messages will come back to the player (“your spell missed you blind moron”), some of those messages will arrive at another player’s client (“moronA failed to hit you with a magic missile”), and some messages will never leave the server environment (“persist this bit of information for me please, mr. database” or “hey NPC, player just missed you with a magic missile, your AI should respond.”). Whether you consider your NPC AI message-based or just part of your game logic is a minor semantic detail.

The point is this: we need to keep track of which players are connected, we need a way to identify those players so that messages can be targeted to them, and we need a way to be able to receive messages, funnel them into our game logic, and emit messages as a result. No matter what kind of game you’re building, no matter what your game logic may look like, this is the essential core nugget of functionality on which all of the rest of your MMO code must be built.

If you remember my dispatch map from this blog post, I can now add a new potential target for dispatch, the GameClientProxy, which is an actor that serves as a gateway between my game logic and the player. If I send the GCP a native scala case-class message, I can expect that as a result, the GCP will produce a protobuf message and put it on the wire, headed for the target player. In some cases I can send the GCP an already built protobuf message, which is the case when a player sends a DirectMessage, a protobuf message to send a “chat” from one player to another.

Here’s a look at my current dispatch map:

val dispatchMap: Map[Int, (Mergeable, String)] = Map(
   1 -> (ZombieSighting.defaultInstance.asInstanceOf[Mergeable], "akka://game/user/ServerCore/DispatchTarget"),
   MessageTypes.SignIn -> (SignIn.defaultInstance.asInstanceOf[Mergeable], "akka://game/user/ServerCore/Clients"),
   MessageTypes.DirectMessage -> (DirectMessage.defaultInstance.asInstanceOf[Mergeable], "akka://game/user/ServerCore/Clients")
  )

I’ve already got the code in place that dispatches these messages and does the protobuf de-serialization, so now I just need a “clients” actor, which is my GCP:

class ClientManager extends Actor with ActorLogging {

	var clientPlayerMap : scala.collection.mutable.Map[String, String] = scala.collection.mutable.Map.empty

	override def preStart() = {
		log.debug("Client manager pre-starting.")
	}

	def playerForUsername(username:String) : ActorRef = {
		context.actorFor(clientPlayerMap(username))
	}

	def removeUUIDFromPlayerMap(uuid:String) : Unit = {
		clientPlayerMap.foreach {  m => if (m._2 == uuid) clientPlayerMap.remove(m._1) }
	}

	def receive = {
		case ClientDisconnected(socketHandle) => {
			removeUUIDFromPlayerMap(socketHandle.uuid.toString())
			// Stop this actor
			context.stop(context.actorFor(socketHandle.uuid.toString()))
			log.debug(s"Player at socket ${socketHandle.uuid} disconnected.")
		}
		case ClientConnected(socketHandle) => {
			val newClient = context.actorOf(Props(new GameClientProxy(socketHandle)), name = socketHandle.uuid.toString())
		}
		case (uuid:String, signIn:SignIn) => {
			clientPlayerMap(signIn.username) = uuid
			log.debug(s"Player ${uuid} signed in ${signIn}")
		}
		case dm:DirectMessage => {
			log.debug(s"Player ${dm.sourcePlayer} sent dm to ${dm.targetPlayer}")
			playerForUsername(dm.targetPlayer) ! dm
		}

	}
}

This class maintains a mapping between socket UUIDs (what I use to identify the game client proxy/GCP actors) and player names. This mapping is the essential bit of state that allows messages to be targeted at players rather than UUIDs. Game clients will be unaware of the UUID of other players (because that could change if they disconnect and reconnect while messages are flowing toward them). Also note that the s”foo ${bar}” syntax is Scala 2.10 string interpolation syntax.

class GameClientProxy(socketHandle: IO.Handle) extends Actor with ActorLogging {

	override def preStart() = {
		log.debug(s"GameClientProxy pre-start, socket uuid: ${socketHandle.uuid}")
	}

	override def postStop() = {
		log.debug("GameClientProxy stopped.")
	}

	def writeRawMessage(msg:com.google.protobuf.GeneratedMessageLite, messageType: Int): Unit = {
		val bb: java.nio.ByteBuffer = ByteBuffer.allocate(4)
		bb.putInt(msg.getSerializedSize)
		bb.flip
		socketHandle.asSocket write ByteString(bb)

		val bb2 = ByteBuffer.allocate(4)
		bb2.putInt(messageType)
		bb2.flip
		socketHandle.asSocket write ByteString(bb2)
		socketHandle.asSocket write ByteString(msg.toByteArray)
	}

	def receive = {
		case m:DirectMessage => {
			log.debug("I received a direct message.")
			writeRawMessage(m, MessageTypes.DirectMessage)
		}
	}
}

This is also my attempt to delay side-effects as long as possiblewhich is a core functional programming mantra. A message being written on the wire to a particular socket is a side effect of the exchange of messages between Actors in my Actor System (the game grid). Note that I didn’t have a “player” class floating around anywhere that I used to represent a single player, instead that’s a GCP. In this blog post, I talked about the importance of modeling an actor system in a way that gets work done which may not be the same as creating an actor for every potential interactive thing visible to a player.

So, with this bit of infrastructure in place, I am now in a position where I can start building small multiplayer interaction. From there, you scale out, you test, and you build more interaction. The key point in a situation like mine where I’m just one person and not an army is that I make small bits work, I test as I go, and more importantly, the act of creating the game should be just as fun as playing it.

So far, with Akka, it’s been a blast.

Dispatching Messages in Scala Without Conditional Statements

So far I have been having a lot of fun tinkering with an Akka IO socket server sitting atop an Actor System that can send and receive protocol buffer messages, ideally when communicating with a mobile client like iOS.

Up to this point, the samples that I have been using all have a single message type and I’ve been dispatching inbound messages to a single fixed Actor. That’s not realistic. I could be getting combat messages, communication messages, navigation messages, commerce/trade messages, and any number of other types of messages. I need to know what class to de-serialize those bytes into (this is why I put the message type as a number on the wire) and I need to know which actor to send that message to once I’ve received it.

The first thing I want is to be able to create a dispatcher map, which maps a message type to a tuple that I’ll be using to store the prototype of the message (the defaultInstance , which can be used to create new instances via mergeFrom) as well as a string that contains the actor path for the actor to which I ultimately want to send the message.

Here’s how I’ve defined my dispatcher map:


type Mergeable = { def mergeFrom(data: Array[Byte]): com.google.protobuf.GeneratedMessageLite }
val dispatchMap = Map(
  1 -> (ZombieSighting.defaultInstance.asInstanceOf[Mergeable], "akka://MyGame/user/ServerCore/DispatchTarget")
)

There’s a couple of interesting things going on here. First, I’m using a structural type to indicate that anything that has a mergeFrom method on it that produces a protobuf message is called a Mergeable and I can then pass stuff around as though Mergeable was an interface, even though the protobuf implementation for Scala that I have doesn’t treat it as such.

Next, I’m mapping an int (which I’ll replace with constants later) to a tuple containing the default instance of the corresponding message and the actor path of the actor to whom I will be dispatching the message.

Next comes the part that I struggled with a litte. I want to be able to dispatch the appropriate message to the appropriate actor but I don’t want to use any statements like if (messageType == 1) { … } , because that’s very un-Scala looking and not as functional as I would like. I know that I have access to the map function in Scala which is pretty powerful, and my first attempt at using it worked, but it wasn’t quite as pretty.

After getting some more advice from the amazing people on Stack Overflow, I converted most of my map and “get” (Option handling) code into a for comprehension. Below is my completed dispatchMessage method, which is part of an Akka IO Iteratee stream:

def dispatchMessage: IO.Iteratee[Unit] =
  repeat {
	for {
		(messageType, byteString) <- readMessage
	} yield {
		for (
			(protoMessage, actorPath) <- dispatchMap.get(messageType);
			theMessage = protoMessage.mergeFrom(byteString.toArray);
			targetActor = SocketServer.system.actorFor(actorPath) )
		yield
			targetActor ! theMessage
  }
}

And now when I get to line 11, I can simply send theMessage to targetActor and the dispatching has taken place and now my facade on top of my business logic is really, really thin and the only thing I need to do is maintain the dispatch map object whenever I add new message support to my application server.

Designing Akka Actor Hierarchies for Online Games – Commerce

Lately I’ve been thinking a lot about the design of Actor systems and actor hierarchies, specifically as implemented by Akka. In a previous series of blog posts, I used Akka to build a telnet-gateway that went through to an Akka Actor System to support a MUD (Multi-User Dungeon/Dimension). Having learned a thing or two about high performance systems since then, I have changed my perspective on how some of these things should be designed.

User Space Modeling vs. Task Modeling

Let’s assume for a minute that we are building an MMO server that supports commerce. Players can walk into a shop and perform a number of tasks. Within the shop, players can sell goods from their inventory, buy goods from the shop keeper, or use the shop keeper as a means to engage in secure trade between players (assume for the sake of this example that players can’t exchange goods unless they’re standing in a shop – it helps illustrate my point later).

When modeling an Actor, especially in my MUD, it can be very easy to think of Actors with a clear correlation to objects within your virtual world. For example, we might create an Actor for the shop keeper and we might send him messages like:

shopKeep = context.ActorOf .... (find the shopkeeper standing in the same room as the player)
shopKeep ! SellStuff(player, 21, ItemPrototypes.JunkSword)
shopKeep ! SellStuff(player, 57, ItemPrototypes.Seashell)

In this scenario, every shop keeper in the game is a unique instance of the ShopKeeper actor. Each one can maintain their own state (their inventory or wares). Sounds good, right? My inner MUDder likes this because it maps pretty much to what the virtual world looks like on my game client. So let’s scale this out a bit. Let’s say the game has 5,000 shop keepers total. 5,000 instances of a shop keeper, each consuming roughly 300 bytes (Akka actor overhead is 300 bytes) plus whatever it takes for their state, that’s an overhead of roughly 1.4MB to manage the overhead of my shop keepers. Meh, 1.MB is nothing in relative terms, so that’s no big deal. So far so good, right? Maybe, but my new perspective says no. This particular type of scale-out is only useful if there is an even distribution of players compared to shop keepers. This is hugely important to remember. What if my game currently has 10,000 concurrent users but instead of being spread out evenly across my virtual universe, someone posted a “FREE BEER AT SHOPKEEPER2921’s HOUSE! PAR-TAY!” sign at the Orc’s Crossing. Now, I’ve got 7,500 players crowded into Shopkeeper2921‘s shop. Graphical client problems aside, this means this one actor is now trying to handle messages from 7,500 players who are buying, selling, and trading with each other. In short, that actor is going to get backed up, the game will appear slow to 7,500 of it’s players, and the proverbial shit has hit the fan.

Creating an actor for every shop keeper, actors for the shop keeper’s shop, actors for each person’s weapon, etc is what I am going to call user space modeling. I have no idea if this is real term, but it is now. It means that the architect of the actor system has decided to map user perceived actors to real actors. This is what I was doing with my MUD. What I should be doing for better performance and certainly better (cloud-sized) scalability is task-based modeling.

Let’s take a look at this problem from a slightly different point of view, task-based modeling. Instead of creating actors to back virtual constructs like shop keepers, swords, and shops, we create actors that perform tasks. If we take a look at our game client, we see that we might be sending packet-messages like “sell stuff”, “buy stuff”, “trade offer”, “trade counter”, and “trade confirm”. Instead of sending these messages to whichever shop keeper happens to be standing near the player (user space modeling), we’ll simply send the messages to whichever Commerce Actor happens to be available based on Akka routing.

Let’s say now that we create an actor CommerceActor who accepts messages in case class form SellBuyTradeOfferTradeCounterTradeConfirm. Instead of sending those messages to a nearby virtual shopkeeper, let’s send them to the “least busy” commerce actor among the N instances of CommerceActor that we’ve created with the Router mix-in trait.

Now our commerce logic might look something like this (did a little DSL-style stuff with the items just for giggles):


val shopKeeper = system.actorOf(Props[Commerce].withRouter(
    RoundRobinRouter(nrOfInstances = 10)))
shopKeeper ! Buy(shopId, 21 VorpalSwordOfDooom)
shopKeeper ! Trade(playerOne, playerTwo, 15 Gold)

Here the code is using a “round robin” router, which means each instance will be given a message in round robin fashion. You can also use a “least full mailbox” router, which essentially load balances it so that the shop keeper currently having the smallest backlog of transactions to process will be given the message. This feels right, and will scale. Even better, the routing configuration for a particular type of actor can be configured in the application.conf file. This means that you can dynamically change the number of instances of certain types of actors. This way, if players are suddenly doing a crapload of commerce and bogging your system down, you can beef up the number of instances of your commerce actor.

In task-based modeling for an actor system, actors are as the Akka documentation recommends as a best practice, encapsulations for behavior and state that perform discrete tasks and either complete the task or delegate sub-tasks to other actors. The supervisor/actor hierarchy is created based on the work that needs to be done, which doesn’t necessarily have a 1:1 mapping with the virtual world in which players inhabit.

Building a MUD in Scala – Revisited

In my previous blog posts where I tried learning the Scala language through an interesting project, that of building a text-based multiplayer game (a MUD), I made lot of mistakes. Thankfully, that is the real purpose behind that kind of experimentation. We learn from our mistakes and we never really grow until we take risks and deliberately step outside our comfort zone.

Some time has passed and I’ve learned a little bit more of Scala so this time I’m going to take another stab at building a MUD in Scala. This time, however, I’m going about it in a slightly different way. Here’s a list of some of my new goals:

  • All of the code for the MUD will be written in Scala 2.9.1
  • Instead of using regular Scala Actors, I will be using Akka 1.3 Actors
  • Rather than manually executing Scala every time at the command line, I will be using Maven to build AND execute my MUD.
  • I will not tolerate ANY ugliness. Everything I consider done must be clean, concise, easy to read, and as Scala-ish as possible.
First, let’s take a look at the POM file I’m using in order to allow Maven to build, test, and execute my MUD:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.kotancode</groupId>
    <artifactId>scalamud</artifactId>
    <packaging>jar</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>ScalaMUD</name>
    <url>http://kotancode.com/tag/mud</url>
    <repositories>
        <repository>
            <id>scala-tools.org</id>
            <name>Scala-tools Maven2 Repository</name>
            <url>http://scala-tools.org/repo-releases</url>
        </repository>
		<repository>
		  <id>akka.repository</id>
		  <name>Akka Maven Repository</name>
		  <url>http://akka.io/repository</url>
		</repository>
    </repositories>
    <pluginRepositories>
        <pluginRepository>
            <id>scala-tools.org</id>
            <name>Scala-tools Maven2 Repository</name>
            <url>http://scala-tools.org/repo-releases</url>
        </pluginRepository>
    </pluginRepositories>
    <dependencies>
        <dependency>
            <groupId>org.scala-lang</groupId>
            <artifactId>scala-library</artifactId>
            <version>2.9.1</version>
        </dependency>
		<dependency>
		  <groupId>se.scalablesolutions.akka</groupId>
		  <artifactId>akka-actor</artifactId>
		  <version>1.3</version>
		</dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.scala-tools</groupId>
                <artifactId>maven-scala-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                            <goal>testCompile</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <sourceDir>src/main/scala</sourceDir>
                    <jvmArgs>
                        <jvmArg>-Xms64m</jvmArg>
                        <jvmArg>-Xmx1024m</jvmArg>
                    </jvmArgs>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
If I were to drop a simple Scala hello world object in src/main/scala then running mvn clean install would compile that Scala object and I could then execute my Scala application with mvn scala:run -DmainClass=Hello (assuming I created an unpackaged Scala class named hello).
To start with, I created a root/bootstrapper object called Game:
package com.kotancode.scalamud

import akka.actor.{Actor, PoisonPill}
import Actor._

object Game extends App {
	val server = actorOf(new GameServer).start()
	server ! ServerStart
}
At first I thought I would just create a singleton actor GameServer, but because of the way you have to use the actorOf method to get an ActorRef instance for Akka Actors, you can’t just create self-starting singleton actors (well you can, but it looks like a hack). Note that because I didn’t declare server as private, that member variable is now visible to the rest of my application, giving all of my game objects access to the game server Actor.
The first task of the game server, once it receives the ServerStart message, is to fire up a telnet server and spin off a background thread that accepts inbound connections.
package com.kotancode.scalamud

import akka.actor.{Actor, PoisonPill,ActorRef}
import Actor._

import java.net._
import java.io._

import com.kotancode.scalamud.core.Player
import com.kotancode.scalamud.core.NewSocket
import com.kotancode.scalamud.core.TextMessage

case object ServerStart
case class PlayerLoggedIn(player:Player)

class GameServer extends Actor {
	private var allPlayers = List[Player]()

	def receive = {
		case ServerStart => {
			startSocketListener
		}
		case PlayerLoggedIn(player) => {
			handlePlayerLogin(player)
		}
	}

	private def handlePlayerLogin(player:Player) = {
		println("Player logged in: " + player)
		allPlayers ::= player
		allPlayers.foreach( p=> {
			if (p.name != player.name) {
				p.self ! TextMessage(player.name + " logged in.")
			}
		})
	}

	private def startSocketListener = {
		spawn {
			val serverSocket = new ServerSocket(8888)

	  		while(true) {
	   				println("Awaiting connection...")
   					val clientSocket = serverSocket.accept()
	   				val player = actorOf(new Player()).start()
	   				player ! NewSocket(clientSocket)
	   				println("Spun off echo handler for player")
	  			}
		}
	 }
}

At this point, I’m now using Akka actors (whose receive method syntax I like much better than standard Scala actors) and a Maven build with automatic dependency management to build and launch my MUD. With just a few minor changes from my previous Scala MUD, I’m in a much better position to grow this into a real application.

Also note the use of the spawn class here. This executes whatever code is inside the code block as an asynchronous background thread, much like the standard Scala actor actor { } syntax. So, for Akka we use spawn { } and for standard Scala Actors we use actor { }.

Another thing worth noting is the use of the .self member before sending a message to an Akka actor. Unlike regular Scala actors, you can’t use !, ?, !!, etc to send messages directly to instances of objects that derive from akka.Actor. Instead, you need an ActorRef instance, which you get from the actor’s self member. In this way, there’s a much clearer distinction between the class’ message-handling behavior (accessed from it’s ActorRef) and it’s regular java-like behavior accessed from standard class members.

In my next blog post, I will get some more features implemented in the MUD. Eventually, if I like the way things turn out I’ll start pushing my code to a Git repo so that you can read/download it there instead of just copy/pasting it from this blog.

Gamification or Dumbification

First, let’s talk about what Gamification actually is. By most standards, it is the use of game design theory and techniques in order to solve problems, engage audiences, or otherwise increase the “stickiness” or popularity of a brand, a technology, a person (who could be a brand in their own right), and so on.

In short, Gamification is the idea that if you want people to participate in something or to otherwise increase their satisfaction (or addiction) with something, then turn it into a game.

Gamification is nothing new, but the way in which it is currently being used in society today is very different than the way it used to. This is due in large part to the Pavlovian conditioning (see my previous post about dopamine squirting) brought about by today’s casual gaming obsession with Facebook and mobile apps. These games are typified by things like:

  • Badges or Achievements, many using phrases like “Achievement Unlocked”, etc.
  • Levels, Points, or otherwise assigning a numeric value to someone’s progress
  • Progress bars so you can watch your overall progress as well as individual progress of sub-tasks
  • Assigning some value to points, which can then be used in virtual commerce
  • Micropayments – this is huge. Many, many games make giant, heaping piles of cash simply by charging people $.99 to buy more virtual currency, increase virtual points, unlock achievements, or otherwise progress in the game.
  • Comparison – These games facilitate the ability to compare your numeric scores, points, levels, badges, etc. with other players. If it seems superfluous to you, think again. The ability to provide a context of comparison to gamers is a psychological necessity for giving meaning and value to all the other aspects of the game.
  • Competition – Games that let you compete against your buddies, enemies, family members, etc.
  • Cooperation – Games that let you team up with these same types of people against computer opponents or human teams, etc.

Anyone who has played an iPhone game lately (or has children who play them) is very, very familiar with the above model. It’s the “recipe” by which these games are created and what makes them so popular on the mobile form factor for casual gamers. Casual gamers are enticed more by the preceding features than they are by graphics, audio, smooth animation, or other yardsticks by which hard-core gamers measure their console games.

So what does this have to do with reality? This is where Gamification comes in. It is the application of the aforementioned techniques to real world problems to encourage people to solve them, to encourage people to participate and engage with your branding effort, to increase the stickiness of a message, or otherwise get a massive number of people to do what you want them to do (including pay you money).

You see this start to creep out from mobile applications with software like FourSquare that lets you earn badges, unlock achievements, gain score, and compare your stats against those of your friends all by “checking in” at real-world locations with your mobile device and GPS. Another one that I’ve seen quite a bit of recently is using software that gives you badges, points, leaderboards, and so on for participating in fitness activities. Even scientific endeavors like SETI use some form of gamification by giving you statistics about the number of blobs of information your computer has chugged through in the search for alien life.

Gamification, at its core, is a motivational tool. It provides incentive for people to do something you want them to do. This can be really, really useful or really, really detrimental. You could gamify the decryption of puzzles (as was recently done in deciphering a German code from an ancient eye-worshipping cult), you could gamify the search for cures for cancer or charitable organization donation distribution algorithms to maximize the benefits of donations… These mad scientist powers of human motivation can be used for good or for ill. Largely the examples I’ve seen have been relatively harmless, but is there a side effect caused by all this gamified motivation? What is happening to us, as a society, as a result?

Consider this: When a child is misbehaving and a mother gets frustrated and she starts counting.. “1 …. 2…. don’t make me come up there, Timmy! 3… ” Now, you ask the mother the question, “Why did Timmy wait until 3?” The mother then responds, “Because he’s  stubborn!!” But the real answer is more interesting. The real answer isn’t because Timmy is stubborn, the real answer is because the mother taught Timmy that he can wait until the count of 3 before behaving.

Gamification is everywhere and the thing that bothers me is how blissfully unaware we, the general public, remain to the fact that we are being gamed.  Take NaNoWriMo, the National Novel Writing Month. They’ve gamified the act of writing in order to motivate budding and published writers to produce 50,000 words in a single month. They use a website where you can record your progress (remember progress bars, assigning point values, and most importantly, comparison?). Note: I am actually participating in NaNoWriMo, so despite knowing that it is artificial motivation via Gamification, and despite writing this blog, I’m still doing it because it’s still fun.

This all looks great – motivating people to do the things that they should be doing, charitable things, or even things that make you money. The flipside, however, is that, once conditioned that rewards and gamification is available for all sorts of things, people may stop doing things unless motivated in this fashion.

The dark side to NaNoWriMo might be that writers will be horribly unproductive during months other than November. The dark side of too much gamification is that its ubiquity is conditioning people to expect gamification, to expect rewards and badges and achievements and comparison and competition for everything. While giving people all these things that their brains love is not necessarily a bad thing, I wonder what will happen to our ability to motivate ourselves to do things because they should be done or we want them done without badges, leaderboards, achievements, or bragging rights.

What do you think?

Slide Deck from my NYC Code Camp Presentation

For those of you who attended my Code Camp NYC presentation on casual and indie gaming with Windows Phone 7 and “the cloud”, I have finally managed to find and upload the PPT slide deck. Ironically enough, the reason it took me so long is because I had trouble with the cloud drive on which the deck was stored 😉

I will be posting code samples that go along with this presentation in one form or another soon… so stay tuned!

Indie and Casual Game Development with Windows Phone 7

Apple’s GameCenter vs. Windows Phone 7 and Xbox Live

As many of you know, I’m currently writing a book to help iPhone developers (as well as non-iPhone developers) adopt the Windows Phone 7 platform called Windows Phone 7 for iPhone Developers. In the course of writing this book, I’ve discovered a lot about the Windows Phone 7 development platform and SDK that I truly love. It really is an awesome platform on which to develop mobile applications and even mobile games.

It’s mobile gaming that is at the heart of this blog post. After version 4.0 of the iOS SDK was released, Apple’s GameCenter was made available. This is an area in which iPhone users can go to see a list of GC-enabled games, find friends, see the status of their friends, and even take part in multi-player games with those friends. Additionally, GameCenter games sport global leaderboards and an unlockable achievement system. I have a few GameCenter games on my phone and, with the release of iOS 4.2, I even have a few GameCenter games on my iPad. The user’s view is that GameCenter’s feature list is incredibly similar to that of Xbox Live as implemented on WP7. However, the similarities disappear altogether when you examine the developer experience.

GameKit is the portion of the iOS SDK that revolves around gaming. Through this API, developers can access a user’s GameCenter profile. They can read to and write from global leaderboards stored somewhere within Apple. For a developer, this is as simple as configuring a leaderboard from within iTunes Connect and then setting some numeric value on the gamer’s profile. This value is compared globally and the leaderboard is computed automatically. For example, if I wanted a leaderboard for “Monster Kill Count”, I would just set the monster kill count for the current player and the leaderboard takes care of itself thanks to Apple’s infrastructure and the GameKit API.

Further, GameKit provides APIs for establishing multi-player gaming sessions with either nearby players (Bluetooth, ad hoc via the Bonjour protocol) or players scattered across the globe. The GameKit API is so easy to use, there are simple method calls for sending data to individual players or broadcasting to all of them. And if you thought that was plenty, add to this the fact that GameKit gives you the ability to, in just a few lines of code, add an overlay channel for in-game voice chat between all connected players. Now if you’re starting to get impressed, think about the fact that NONE of this requires you to stand up a back-end server to support any of this. All of this can be done for ZERO up-front cost, making this an absolute goldrush ripe for the picking for Independent developers as well as prime target for commercial games that support GameCenter features. Oh, and don’t forget the fact that the GameKit API lets you unlock achievements on a player’s profile and those achievements are defined quickly and easily by a developer through the iTunes connect portal.

So how does Xbox Live on Windows Phone 7 fare? Well, this is where the waters get muddy. Xbox Live games have at their disposal leaderboards, lobbies for finding and grouping players, APIs for multiplayer gaming, and APIs for unlockable achievements. So what’s the problem? The first problem is that right in the Marketplace list of conditions for acceptance into the application marketplace is a rule that says your Silverlight application may NEVER make any API calls to any of the core gamer libraries provided for Xbox Live. This immediately rules out casual games written using Silverlight that have multi-player, social aspects.

That’s OK you might be thinking, you’ll just use XNA to build an Xbox game using DirectX9 / Direct3D. You don’t need Silverlight and you do get a flaming truckload of high-end graphics features by going the XNA route. Here’s the rub: You can’t access the Xbox Live APIs unless you’re an approved Xbox Live partner. This means that you must e-mail Microsoft and ask to be admitted into the elite group of Xbox Live partners. Conditions for entry to this club aren’t simple, either. You must already have published an Xbox game to be considered for Xbox Live partnership. I think there are also company size requirements and possibly even a “commercial revenue” requirement. In short, if you’re an indie developer looking to use Xbox Live features, you’re hosed.

With all that said, I wouldn’t be telling the whole story if I didn’t at least explain a bit about why you’re hosed if you want XBL features in your WP7 game as an Indie developer. Xbox Live isn’t just a suite of APIs, it’s an ecosystem. This ecosystem has a currency: gamerscore. This is a point value that every single Xbox Live gamer has on their gamertag. Every Xbox Live game a gamer plays will earn them both points and unlockable achievements. These are global. This means that every XBL gamer can see which achievements you have unlocked and what your total gamer score is – it’s part of your public profile. This is the currency by which relative wealth in the Xbox Live world is measured. Those with higher game score and rarer achievements are this ecosystem’s elite… the upper class.

If an independent developer were to be given unfettered access to the ability to unlock achievements and add points to a gamer’s score, it is entirely likely (if not simply inevitable) that a well-meaning Indie developer would make a game that was too easy, with too many achievements, that awarded too many points. The simple act of a single gamer playing this game and easily racking up its thousands of points and hundreds of achievements would immediately devalue the currency of the entire ecosystem. The hard work, time, effort, and (hopefully) fun players invested in earning their gamer score and unlocking their achievements would mean little in the face of the onslaught of indie developers able to create unbalanced games that respect neither the relative difficulty in unlocking achievements nor their relative worth ecosystem-wide.

GameCenter, despite having the ability to put together players from across the globe, has no global currency. There is no continent-wide Euro with a relative worth standard like the Xbox Live gamerscore. Every game has private leaderboards. The points required to rise up on those leaderboards are not scaled relative to the time or effort required to ascend the ranks of any other game. It might take me 10,000 points to reach the top of a leaderboard in GameCenter Game “A” and only take me 1,000 points in Game “B” but Game “B” might take me 300 hours whereas Game “A” only took me 20 minutes. This type of scale disparity would ruin the value of Xbox Live gamer score but because each GameCenter game is isolated, it has no affect on global GameCenter economy. The same is true for unlockable achievements within GameCenter. GameCenter’s lack of a single, unified currency or score, gives it the ability to allow any developer unfettered access to points, leaderboards, achievements, and multi-player gaming without ruining the ecosystem.

So, in conclusion, it is my belief that until Microsoft creates a mobile, “lite” Xbox Live in which they give developers access to points, leaderboards, achievements, and mobile-isolated multi-player APIs but without access to the global gamer score value, Indie developers will be out of luck.

If anyone from Microsoft is reading this, this is my formal request for such an isolated, “lite” Xbox Live. I realize that Windows Phone 7 is a v1 product, but at least letting your customers (developers, especially Indies) know that you have plans in the works to give us an equivalent of GameCenter and GameKit would go a long way toward platform adoption by Indie developers for casual, multi-player, social games.

BTW, in case you’re curious… the top selling games on the iTunes app store, after you remove the blockbusters by companies like EA, etc, are… drumroll…. casual, multi-player, social games. Here’s to hoping that Microsoft throws us a bone in the near future, or at least something to chew on while we wait for WP7’s sandboxed Xbox Live, if such a thing will ever exist.