Showing posts with label targeting Android. Show all posts
Showing posts with label targeting Android. Show all posts

Saturday, July 9, 2011

Want to Change the Game Industry? Support the Xperia PLAY.

The problems with the console game industry are well documented.  The industry is fairly homogeneous (at least in the US), the cost of development is high (tens of millions of dollars has been the norm for a few years now), the hardware cycle is slow.  The game industry does a poor job at reaching people outside of the "core" gamer group (which is mostly men between 15 and 25), and generally tends to make the same sorts of games over and over again (see if you can count how many first person war games have been released in the last decade; I can't).  The big companies making games are too risk-averse to actually make anything interesting, and the developers themselves are often subjected to grueling death march development cycles.  And after all that, 10% of developers make big bucks and everybody else loses their shirts.  It's not a pretty picture.

Depending on which school of thought you come from, this is the point in the lecture at which you stand and declare that consoles are doomed and the future of gaming is ______ (pick your poison: iOS / mobile, tablets, Facebook, etc).  The argument here is that these devices are more widely accessible, development and distribution is very cheap, and even at a lower price point the potential for revenue is a better bet than a long-winded space opera designed for guys in their last year of high school.  I mean, Angry Birds made about 10 zillion dollars, who needs Call of Duty anyway?

Then, from the other side of the auditorium, the console game developer stands up and points out that Mario would be unplayable on an iPhone.  You'll never beat consoles, he argues, because a touch screen interface just isn't good enough for a lot of console genres.  Lack of physical buttons dooms mobile devices to "casual" (and he says it like it's a dirty word) games: Tetris and color matching and launching fowl.  No depth, valuable only as a time waster.  The market for more complex and meaningful games ensures a future for consoles, he argues.

Here's where I stand on the future of gaming: I think traditional game consoles are going away, but traditional console games are here to stay.  My rational is thus:

Mobile platforms are ubiquitous--everybody has a phone.  Software delivery to these platforms is extremely easy, and people download lots of apps (actually, mostly games).  Therefore, the installed base of potential customers is much, much larger than all the consoles combined.  Better yet, the hardware cycle for phones is much faster than consoles.  Phones will surpass current gen consoles very soon.  Heck, even Carmack thinks so.  And the cost to the consumer is lowered because carriers subsidize hardware in exchange for contracts.

I think simple mechanics and touch screen controls act as a gateway drug for new gamers.  The number one thing that the Nintendo Wii proved is that all kinds of people are willing to play video games if the interface is designed in a way that doesn't turn them off.  The success of mobile games is proof of this as well; the user base of iPhones is much wider than that of an Xbox360, and yet we know that iPhone users download games en masse.  Users who get hooked on playing games on their phone are more likely to try games on other devices; the phone has made it ok for them to experiment with gaming.

I also think that we've only just begun to experiment with touch screen interfaces.  Many other interface transitions have occurred in the past; people thought that Adventure games and FPSs could not work on consoles until Resident Evil and Halo came along and showed them how it was done.  Touch interfaces will certainly continue to improve and thereby widen the range of game styles that can be played on a mobile device.

That said, there is truth to the points my fictional console developer argued above: there are still a great many game genres that are simply not playable with out sticks or buttons.  And more importantly, there are a great many core gamers who are simply not interested in playing games without physical controls.  Or even on a small screen.

But consider this: if you bought an Android phone in the last year, you might have gotten one that supports HDMI out.  Better yet, you might have one that comes with a dock that has HDMI out on it.  The phone screen itself is probably not far off from the native resolution of your HD TV.  Plus your phone has Bluetooth support, and as Google demo'd at Google IO this year, support for USB devices is in the most recent versions of Android.

What if you could come home, drop your phone in its dock, pick up the wireless controller sitting on your desk, turn on your TV, and suddenly be playing a high-end game at full resolution from your couch, powered by your phone?  Part way through the game you get up to leave, grab the phone on the way out, and continue playing on the small screen in the elevator.  Sounds pretty slick, huh?

All the necessary technology for this type of device is already in place.  You've got enough power in the phones to drive a TV, support for traditional game interfaces via HDMI and Bluetooth, and a target audience of people who want a cool smartphone that can double as their game console.  If this was the norm, what would be the point of spending another couple hundred dollars on a dedicated game device? This would be fantastic for game developers; there's space for big-budget, high-end titles as well as low-cost casual games, all running on the same device and delivered through the same point of sale systems.  We could have our cake and eat it too, accomodate both the core gamer and everybody else with the same platform.

There are two major problems with this vision of the future.

The first is the problem of content delivery; console games are pretty gigantic (we're counting data in gigabytes here), and getting lots of heavy data to a mobile device is still arduous.  Nobody is about to download a 24 GB PS3 game to their phone over 3G.  The solution to this one is probably just time.  Better network infrastructure will come along and solve it.  Until then, streaming and compression technologies must pick up the slack.

The second problem is more immediate: in order for controller-based gaming to come to phones, phone games must support controllers.  The barrier to a hybrid game console / smartphone is not technology or even development cost, it's lack of applicable content.  Who cares if you can use a controller if all the games are expecting a touch interface?

This latter problem is one us mobile game developers can solve.  And the best way do start, I think, is by supporting Sony Ericsson's Xperia PLAY.

The gaming press has pretty much thumbed its nose at the PLAY.  It looks like the PSP Go (not a good association) but it can't play PSP games.  It has a few Sony logos on it but it's not really a "Playstation Phone."  Some have likened it to the N-Gage, which is a convenient conceit but not a very useful comparison; perhaps those folks have forgotten that the N-Gage had a terrible portrait-only display and required that the battery be removed before game cartridges could be inserted.  The best way to describe the PLAY is that it's a regular Android smartphone with a slide out game pad and game buttons.  That's it.  Oh, and it's also really fast (it's the fastest device I own, and I have a bunch).

Whatever you think of the PLAY, supporting its game controls in your game is a step towards a hybrid game console / mobile device future.  Consoles may die off but physical buttons will not.  By adding physical button support to your mobile game, you are increasing the business viability of a mobile console.  If every game supported physical buttons we could have such a device today.

Secondly, if the PLAY does well in the market then it is safe to assume that other manufactures will produce knock-off "gaming phones."  If these catch on, it could create a new subset of smartphone, much the way phones with physical keyboards have come to define smartphones for business people.  It would be pretty cool to have a whole array of phones with gaming controls to choose from; that would make button-based genres viable on mobile devices very quickly.  Of course, there'd need to be some games that support that interface before the manufactures are likely to really get on board.

So, if you want to promote a future where we can enjoy both console-style games and the latest tower defense color match physics playground social gold farming title on the same mobile device, support physical buttons.  Support customization of controls.  Support the Xperia PLAY pads, and hope that the device is successful enough to spawn more like it.  The game industry is in the midst of a major transition, and it's one that we, the console and mobile developers, can control.  It's an opportunity to create an environment where development doesn't suck and costs are not insane.  It's too good to pass up.

Sunday, November 7, 2010

Leveraging Java and C++ for Hybrid Games

I've been thinking a lot lately about how best to use the resources that Android provides for game development.  A lot of the game developers I know (and I know a lot!) are quick to treat any new platform as a dumb host to their game engines.  Usually developers have a bunch of code, or even entire games, that are written to be aggressively cross-platform, so all they need is a way to compile the source, attach it to input events, and draw to screen.  Any platform that can provide those basics can host their tech, so when evaluating a new platform to support, these developers only look at the most basic level of functionality.

This is certainly true on Android as well.  Lots of developers look at the NDK and see a C++ environment that they can run their code in and decide that supporting the platform only requires gluing their existing code to the hooks that Android exposes.  And that's true--if your only goal is to port an existing game from one platform to another, only the minimal set of common functionality is necessary to get something up and running.

But since I am in a position to write games exclusively for Android, I've been thinking about how to leverage parts of the platform that most game developers ignore: the OS and Java runtime itself.  There's a lot of functionality there, and maybe there are ways that I could leverage it to make better games.

One project I've been working on recently is a little game framework using the NDK.  My friend Gregg and I ported Google's open source browser-based 3D framework, O3D, to Android a while back, and I've been using that to get some dudes running around on the screen.  O3D has a big Javascript component which we've ignored; the rest of it is a C++-based, shader-centric rendering backend.  Gregg did the heavy lifting of getting the thing to run on OpenGL ES 2.0 and I've been hacking in bits and pieces of old game engines on top.  The result is that we have a pretty complete rendering engine running on Android without a whole lot of effort.

It's a lot of code considering that it doesn't really do anything yet--almost 500k lines of C/C++.  But it wasn't hard to port because in the end, Android is really just another Linux OS with hooks into things like OpenGL ES 2.0.  So for this work, we basically did what lots of other game developers do: we ported the code using as little Android-specific stuff as possible and got something up pretty fast.

I've been slowly adding game code to this project, and as of this writing I have an early prototype of a shooting game up and running: you can run a little test character around and shoot placeholder art zombies with dual thumbsticks.  It's not a game, yet, but it's enough to prove out the code.

Not a game, yet.  Place holder art courtesy of 3drt.com.
If this thing ever gets off the ground, it'll be a game written almost entirely in C++, with just a few hooks back to Java for input, sound, and application life cycle events.  Just like most games that are built to be cross platform, or brought over from other platforms.

But I think there's an opportunity to use Android's unique hybrid application structure to do things that might be difficult or impossible on other platforms.  There are areas where I can get a lot of value out of Java while leaving the game engine and performance-critical code all in C++.

For example, I've hooked up a web server to this game.  It's a very, very simple web server; I found some code on the web that implemented a basic HTTP server in Java, copied and pasted it, and then hacked it up until it did what I needed.  It runs in a separate thread within the main game process, and allows us to connect to the device from a desktop browser while the game is running.  Here's a graphic to illustrate the structure of the code.

The high-level structure of this engine.  Red bits are Android Framework, blue are separate threads, and green is native code.

I'm sure you're reading this and are thinking, why the heck would you want to run a web server inside a game?!  Well, sir, I'll tell you.  With the web server in place, I've opened the door to real-time game editing.  This web server doesn't serve static pages, it reads and writes data directly to and from the native engine.  I can, for example, pipe O3D's scene graph up to the web server and let the user browse its structure from their browser.  I can do that with my game objects too (thanks to the meta system I referenced in the last post, which lets me query the structure of a given object by string).  And perhaps most useful, I implemented a simple interface for editing shader code on the fly; I can write vertex and fragment shaders right in the browser, click a button, and immediately see the rendering change in the running game.

This obviously isn't a full runtime editor, but with just a little bit of effort it's already proved to be pretty powerful.  The whole thing is exceedingly simple: my copy-pasted web browser calls down into the native code via JNI and just passes a string payload, which a few hundred lines of runtime code process and then return to the server and thus to the browser.  I'll extend this interface as necessary to other aspects of the game; building a way to do very fast iteration for things like game play physics and shaders is the way to turn a mediocre game into a good one.

Despite the simplicity of the web server system, I'm not sure it would have been as successful on other platforms.  C++ is great for rendering a 3D shader-based game, but it's actually a bit arduous to use for building a web server.  Java, on the other hand, is a great language to write a web server in--it's actually designed with that kind of application in mind.  Android hybrid apps let you leverage both native code and Java simultaneously, which can lead to some pretty neat combinations.  I think that, if this particular game engine ever becomes a full-fledged game, this kind of language diversity will make it a lot of fun to build.

Update: Oh, internet, you fickle beast.  Every potentially disputable line of text must be disputed!

OK, to be clear: of course it's not very difficult to write a web server in C or C++.  I did not mean to offend your sensitive language fanboyism by suggesting that maybe, perhaps, possibly, some languages are more predisposed to certain types of work than others.  Though I could write a GLES 2.0 game entirely in Java, I would not choose to do so: that language is not the best fit for that problem.  So yes, you may of course write a web server in C++, or in C, or in assembler or any other language.  And it's not that hard.  But in Java, it's so, so easy.  Heck, I even implemented a memory file cache just for the heck of it.  The code generates JSON on the fly based on results coming back from the engine runtime.  Sure, you could do this in C.  Be my guest.  Me, I'm looking for the simplest possible solution to each of my problems, so I can spend most of my time on the part that counts: making the game fun.

I also did not mean to suggest that I am the first to think of piping game data through a web server.  I just thought it was a neat and easy method for this project specifically on Android.  So there.

Monday, May 3, 2010

Control Configuration and Abstraction



The #1 thing that I've learned since shipping Replica Island is that users want configurable controls.  I mean, I might have guessed that some devices would have one sort of controller and not another, but I didn't anticipate the number of people who prefer a specific control configuration even when others are available.  Users with trackballs and directional pads asked for configurable keyboard settings, and when I added orientation sensor-based movement for devices without other controls (I'm looking at you, Xperia), many users who could already play the game chose to switch to tilt controls too.  I've made four updates so far and all of them have had to do with the input system; in the first three I added more and more configuration options, and in the most recent (v1.3) I rewrote the core input framework to improve non-standard control configurations.

When I started writing Replica Island, the only device available was the G1.  About half way through development I switched to an HTC Magic, and at the very end of development I switched to a Nexus One. The game was entirely designed around HTC's trackball-on-the-right design.  Fairly late in development, devices sporting directional pads (like the Motorola Cliq, and more importantly, the Droid) started to hit the market, so I added some support for d-pad controls.  I didn't really think anybody was going to use the keyboard to play, so I only added a few key-based controls to support the ODROID.

The input system started out like this:


MotionEvents from touch and trackball motion, as well as KeyEvents, were passed to the InputSystem (via the GameThread, for reasons I'd rather not discuss), which recorded them in some internal structures.  The goal here was to abstract the Android events from the game interface.  The game wants to be able to say things like "is the jump button pressed," or "was the jump button just pressed since the last frame," or "how long has it been since the last time the button was pressed."  It's a query-based interface, rather than the message-based interface that the Android framework provides.  So the initial role of the InputSystem was to record Android events so that they could be queried in the future.

The trackball was tricky to get right.  I want to allow the player to flick the trackball in a direction and have the character get an impulse in that direction scaled by the magnitude of the flick.  But the Android motion events come in at a fixed frequency and fixed magnitude, so in order to build a vector describing recent motion, I needed to maintain some history between motion events.  My first implementation, which survived for the entire course of development, was to cache a history of 10 motion events and calculate the average direction of motion across all of them to find the flick direction and magnitude.  After a specific timeout had passed with no new events, the cache was cleared and averaging would begin again with the next event.

This worked ok as a way to calculate a motion vector, but it had problems.  The biggest issue was that there was no way for a user to move slowly; even if the user rolled the ball slowly (thus causing motion events to come less frequently), as long as he rolled fast enough to make the internal event timeout, the events would get averaged together and would come out looking the same as a fast flick.  So users who tried to move with precision or in small steps often found themselves rocketing across the level.

When I went to add d-pad support, I just treated the pad as a different source of motion events.  I treated each keydown as a roll of a specific magnitude in a specific direction, and fed that into the same cache system I used for motion events.  This worked, sort of: it allowed me to pipe the directional pad through the trackball interface (which connected directly to the game) pretty easily, but it didn't feel good.  The problem with this approach was that directional pad events don't need any averaging; in fact, you want exactly the most recent state to be represented, as the player can release a key at any time (the trackball, unlike other kinds of input, never goes "up", and thus required a history).  So directional pad support in Replica Island, in the first few versions, sucked.

Add in configurable control options and very quickly my simple G1-centric input system grew into a mess that didn't work very well.  So, for the most recent version, I rewrote the whole thing.  Now the structure looks like this:


The main change here is to separate input recording (necessary for querying) from game-specific filtering and control configuration switching.  The InputSystem is now generic; it just records input events from the keyboard, touch panel, orientation sensor, and trackball, and provides an interface for the current state (as defined by the most recently received events) to be queried.  A new system, InputGameInterface, reads the hardware state from InputSystem, applies heuristics and filters, and presents fake buttons for the game to use.  This way the game can ask for the "directional pad" and get input from a trackball, orientation sensor, keyboard, directional pad, or whatever, already filtered and normalized.  I put all of the filtering code for the trackball into this class, and I can now pass directional pad input directly to the game without tying it to the trackball.

Speaking of the trackball, I changed my approach to filtering.  Now I accumulate trackball events that occur within a very short cutoff, and average them after a slightly longer cutoff.  Instead of turning the trackball input "off" after a fixed duration, I make it decay until it reaches zero.  This lets the user make small, precise movements, and still get a big motion from a large flick (as in the latter case, events occur in rapid succession and accumulate).  This method also gave me an obvious spot to stick a sensitivity factor for the trackball, which several users of devices with optical trackpads (HTC Desire, Samsung Moment, etc) had requested.

The new system probably needs a bit more tuning, but I played the game through with it and it feels pretty good.  The code is about 100x cleaner now, and InputSystem is something that others can easily reuse without any other dependencies.

Friday, April 9, 2010

Replica Island: One Month On

As of today, Replica Island has been available on Android Market for exactly one month.  I thought this would be a good time to see how it's been doing.

Turns out it's doing pretty well!  It's holding steady at 4.5 stars and it just passed 250,000 installs.  There have been a few bugs; I've made a few updates, and there are a few more fixes in the works.  But most users have been extremely positive about the game.

I've been diligently recording my install numbers from the Android Market Publisher site all month so that I can produce this graph.

Before I talk about the graph, let me tell you a little bit about my launch plan.

Replica Island is a series of experiments.  I'm trying to learn how games should be made for Android, and part of that process is learning how they should be marketed.  So as part of the experiment, I made the following launch plan:
  • First ten days: no PR, no announcements, nothing.  Just upload it and see what happens.
  • Day 10: send out press releases, upload YouTube video, post on blog.
  • When installs start to slow, prepare a second round of press releases, this time for a different audience.
My marketing budget for this project is $0.00.  I know basically nothing about marketing, and I sometimes think that Nicholai, my PR guy, was dropped on his head as a child.  This plan reflected my need to spend no money and have basically no method of marketing other than trying to get the word out to blogs and news sites.

The first week I made no announcements in order to track the quality of organic growth.  Turns out organic growth was steady and apparently fairly constant; Replica Island was downloaded about 18k times in that first week.  

On 3/18/10 I uploaded the first update.  This update fixed a few bugs and added tilt-based controls.

On 3/19/10 Nicholai sent out press releases to a bunch of Android blogs and a few non-Android gaming blogs.  The total number of blogs targeted was small, maybe five or six.  Of those, AndroidGuys.com was the first to respond (and their report remains one of the most detailed).  A bunch of other blogs copied and pasted the AndroidGuys report (I swear 99% of blogs nowadays are basically retweets of other people).  There was an immediate increase in daily downloads.

On 3/22/10 Gizmodo posted the YouTube video and wrote a nearly content free report (though they still managed to work in an anti-iPhone reference, as if part of their editorial goal is to promote fanboyism).  Apparently a lot of people read Gizmodo, as downloads spiked on that day and then continued at increased volume.  Also, the retweeting of the Gizmodo article guaranteed that the first several pages of search results for "Replica Island" were all different sites referring to the same two articles.

On 3/30/10 Replica Island was added to the list of Featured Apps in Android Market (full disclosure: I'm a Google employee but was not involved in the decision to feature this game).  You can see the effect of being featured in the graph; downloads per day shot way up, and have remained high.  Featuring makes apps really visible!

Since app downloads haven't slowed down yet, I haven't implemented the next part of the plan, which is a second round of press releases aimed at different blogs.  I hear that Nicholai has some crazy scheme up his sleeve, but as long as it costs $0.00, I'm fine with it.

So, here's my takeaway from this first month on Market:
  • Users want games in traditional genres.  Replica Island gets a lot of love from users just for being a recognizable game genre.
  • Updates don't seem to really affect downloads.  Some developers have complained that mixing uploads and new releases in "Just In" allows unscrupulous developers to ship superfluous updates just to increase their visibility, but my data doesn't show any particular advantage to being in Just In.  I think that list moves too quickly.
  • Organic growth can work, but even the tiniest bit of marketing goes a long way.  Getting the word out to blogs, even with a simple web site or press release, is huge.  Those people who are expecting direct-to-consumer digital distribution to be the end of marketing are sorely mistaken.
  • The YouTube video we made was almost an afterthought, but it's been reproduced in more blogs than any of our screenshots or promotional text.  YouTube will definitely be a big part of our next push.
  • Nicholai went to all the trouble to make a press kit, and write press releases, as described in the excellent Care and Feeding of the Press, but 99% of blogs just copied and pasted the summary text we put on the front page.  I think less than 10% of the blogs that posted about the game actually tried playing it.
  • Development and marketing on a budget of $0.00 totally works!
So that's all for now.  I'll report back when the data reveals some new pattern.  Thanks much to everybody who is playing, and to all of the blogs who covered the game, even those that just copied their text from somebody else.

Thursday, April 8, 2010

Monday, March 29, 2010

Replica Island User Comments Are Hilarious

Update: Blogger apparently isn't advanced enough to deal with images reliably. I moved them to a regular web site.


So Replica Island has been out for about three weeks now, and today it reached 85,000 installs, which is pretty cool.

Lots of users have been nice enough to leave feedback, too.  Most of the feedback is overwhelmingly positive, which is fantastic--there's nothing better than knowing that something you made is bringing other people pleasure.  And even the negative comments can be useful; I've identified several bugs and high-value features thanks to the suggestions of users posting on the Market page.

Here's a few of the comments that really made my day.

Flattery will get you everywhere.  I'm preparing a fix as we speak!



That's some high praise right there.

Thanks!

Then there are the useless comments.  These are comments that, typically, contain so little information or are so undecipherable that they don't tell me (or a perspective user) anything useful about the game.  These are mostly comments like, "doesn't work" or "I'm stuck."


First the shift key and now this!


Wait, which is it?  Man, how would you rate a game that you liked?


Thanks for the bug report!  I'll get right on that, uh, wait, what did you say happened again?


Perhaps you missed the text at the very beginning of the game that explained how to move?  It's pretty complicated, I know: "roll the trackball" or "press the d-pad."  I mean, come on, give me a break, right?


Harsh!  Wait, are you saying that the effort is only worth 2 stars, or that the game is so bad that it only warrants 2 stars because we put a lot of effort into it.  Wait, what are you saying again?


Your feedback has ensured a higher standard of quality for our next app!


Thanks, but maybe you meant to post on the Zenonia page?

Then there are the hilarious comments.  Sometimes they are sort of innocent, like this one.


Sorry to let you down Etan, but I'm not sure exactly where that expectation came from, as this is our first game and all.  Also, maybe you could have added "mediocre" or "run-of-the-mill" in there somewhere--I'm sure there's some way to fit in another few words meaning "average."


See, this is almost a useful comment!  There really aren't any cutscenes in the game (well, there's one, but I won't spoil it), but there is a lot of dialog--maybe that's what you meant?  I'm not sure how to make the game faster and slower at the same time, though.

There were a bunch of comments with a common theme that I couldn't figure out.


Uh-oh, that sounds like a bad bug!


How could this happen?  I tested the Droid extensively!


Oh no!  This sounds like a real problem!

I was so confused about what these posters were trying to tell me.  Is there some horrible bug in my game that prevents moving forward?  How can that be?  And if that's the case, how come only 4 people out of 1000 have reported it?  I've played the game on the Hero, I know that it works fine.

Finally, one final post from a user with this problem suddenly made it clear what was happening.  This post has since been removed by its author, but it lives on forever in the databases of services like AppBrain.


If you've played Replica Island, you might remember the intro sequence.  In it, a character (Wanda) runs through a few short credits, finds the broken Android robot, and says a few words.  Then the game changes to the first level, in which Dr. Kabochanomizu teaches you how to play.  That intro sequence takes, on average, 48 seconds (I know because I have user data from 85k users telling me so).  During that period, you can't control the game.  These users are people who booted the game up and closed it again in less than 48 seconds, and then went back to Android Market and wrote a review.

I actually figured this out before Patricia came along and made it clear, so in the 1.1 update I released about two weeks ago I added a little flashing "Please Wait" message to this part of the game.  Still a few folks (like our friend Patricia here) didn't figure it out and gave up in less than 48 seconds.

I guess I don't have anything to say to people who give an app less than one minute to be awesome.  It might be nice if Market displayed the amount of time each user had the app installed before writing a review.



Ah, the good old backhanded complement!  However, this poster is mistaken: I never claimed that the game would get 50 fps on the Droid.  I said it would get 50 fps on the G1, which it does during normal play (it can drop to about 30 in complex scenes).  No game draws faster than 30 fps on the Droid (or Nexus One) because those devices are fill limited.  Sorry about your luck, Mario, but your device is going to be 30 fps for all games forever.  It's still a pretty cool phone, though.



Do you see this!?  THIS is how you write useful feedback!  Both points of feedback are great, particularly the suggestion box.  I am totally going to add that in the next update.  Glad she liked the game, too.

The funniest comment so far, however, wasn't posted on Android Market.  The user was so incensed at the game that he visited the Replica Island web site and sent e-mail to Nicholai, my PR guy.
By the way, your game sucks big donkey balls. I have spent a Good amount if time playing only to find I am at a part I can't pass. I would tell you what part of this stupid game it is from but I can't go to a reference point. I have also ran into several game glitches and I just can't believe you would publish such a piece of shit. Fuck you.
This is so awesome.  Mr. Russell Hall, whoever you are, you totally made my day.  Hopefully one day you'll figure out wherever it is that you are stuck and continue putting a good amount of time into my donkey-ball-sucking-game.  Seriously, this was the first comment to really make me laugh out loud.  Thanks.

Friday, January 22, 2010

Fragmentation? More like Fragmentawesome.

I'm lucky enough to have occasional access to lots of different Android devices via my work. The whole point of the Android approach to apps is that you can write an app on one device (or even an emulator) and deploy it across everything. In my case, that's been pretty true. I've tried Replica Island on the following devices:
  • Google Nexus One
  • Verizon Droid by Motorola
  • HTC Magic (The myTouch in the US, HT-03A here in Japan)
  • HTC Dream (The G1)
  • Samsung Behold II
  • Samsung Galaxy
  • HTC Hero
  • HTC Tattoo
  • LG Eve
  • ODROID
  • Covia SmartQ5
  • Android for x86
The cool thing is, Replica Island ran on all of them without complaint. That's not to say it was playable on all of them--the Covia SmartQ5, for example, has no keyboard, trackball, or even orientation sensors, and you have to use a stylus on the screen (it also has no GPU so the game runs extremely slowly). And some devices (like the LG Eve) have directional pads that are really poor for games. I ran the game under Android for x86 via virtualization, and while it worked it was slow enough that I have new respect for the Android emulator. But the game runs, pretty much error free, on every single Android device I've tested it on.

I don't have regular access to all this hardware to test on, so when a phone comes my way I jump on it, install the game, and try it out.  Excepting basic support for multiple screen sizes and input systems, I don't have any device-specific code. I developed Replica Island almost entirely on Dream and Magic devices; it's built for a trackball and touch screen. I've added support for directional pads as well, which covers almost all of the phones on the market. The game runs at a nice frame rate on the Dream/Magic hardware, and it's very smooth on faster devices like the Nexus One and Droid. But that's it--no special case code for any particular device anywhere. Cool!

You might be interested in which of these devices plays Replica Island the best. The answer might surprise you. Wait for it... ok, it's the ODROID.

Yeah, seriously.

What the heck is the ODROID? Well, it's an Android device (not a phone) sold by a South Korean company called Hardkernel. Actually, the consumer version isn't even for sale yet, but you can buy test hardware for nebulous "development purposes" on their web site. The Wonderswan ODROID runs Android 1.5 (sounds like they will have a 2.0 update soon), has an HVGA screen, a Samsung CPU at 833mhz, a touch screen, orientation sensors, and all the other standard stuff. What sets it apart is the game-focused form factor, a real directional pad, and four face buttons. The thing is clearly designed for games.


My ODROID arrived in the mail yesterday, direct from South Korea. It's clearly prototype hardware; the thing is made out of light plastic and looks fairly cheap. There's a very strange power button that doubles as a hold switch and screen orientation switch, and I keep accidentally hitting the capacitive volume controls where I expect shoulder buttons to be. The directional pad is actually pretty bad compared to what you'd find on gaming hardware like the Nintendo DS or Playstation Portable, but it's better than your average phone. The thing can talk to adb, it came with an SD card already installed, and supporting the A/B/X/Y buttons is trivially easy (they just map to regular keyboard events).

But the reason that the ODROID is the best device for playing Replica Island isn't just because of the game-like form factor and controls. Unlike most other Android devices, the ODROID is a combination of fast CPU and medium resolution screen. The devices with larger screens tend to be fill-rate bound; though the Nexus One and Droid have extremely capable CPUs and GPUs, the high resolution screens on those devices work against them when it comes to games (it's almost impossible to break 30 fps on those devices via the GPU, though they can crunch really complex scenes at that speed without breaking a sweat). On the other hand, the Magic/Dream class of devices have the same HVGA resolution, but tend to be CPU bound--rendering is fast but I spend quite a lot of time running the game simulation. The ODROID has neither problem--its CPU is pretty fast and its GPU has no problem filling the HVGA display. As a result, Replica Island is silky smooth on the ODROD--a constant, reliable 60fps. Add that to the game-ready control scheme and you have a pretty great game experience.

That's part of what's so awesome about the run-everywhere Android approach. Replica Island works on all Android devices, pretty much by default. It's fun to play (well, I think it's pretty cool) on most average phones. But when some crazy company wants to make some crazy device that's good at one thing, they can do so without requiring any changes to the applications themselves. In this case, the ODROID is a surprisingly solid game device, at least for games like mine (though other games, particularly 3D games with complex scenes, are probably faster on devices like the Nexus One). And supporting it costs me literally nothing; I just loaded it up and it worked. That's pretty neat.

Wednesday, November 11, 2009

It's Not the Size That Counts

One of the concerns that I occasionally run across when working with Android game developers is that Android handsets don't have enough storage space for applications.  Some folks, such as John Biggs over at MobileCrunch, see this as an obstacle to "real" game development.  In his article on the subject, Biggs notes that Myst for iPhone takes up 727 mb, making it too large for any of the existing Android handsets. His conclusion is that the lack of space on Android devices is preventing game developers from bringing "real" games to Android.


"The real culprit behind the lack of Android apps isn't lack of developer adoption or a difficult SDK – it's the ludicrous 256MB limit on app storage for most current Android phones and Android 2.0 itself. The OS also does not support the installation of apps on removable storage like SD cards, further ruining chances for more effusive and expansive titles. "


Actually, Android imposes no size limit on application space; each device maker may choose what kind of storage and how much they want to put in their devices, and there is already a bit of variation across the handsets currently on the market. The current partition space is the result of manufacturer preference, not some characteristic intrinsic to the Android OS.

While it's true that apps can't be installed on the SD card, and that the amount of available application space on existing Android handsets is smaller than some other devices, I think that this argument is based on the assumption that "better" games must take up more space.  I'm here to tell you that there's no strong correlation between game quality, or even game length, and application size.

Level of Detail
If we take a look back at video games over the last thirty years, we can see that, with each new generation, games have required more space than before. Take the Super Mario series. Super Mario Bros. (1985) for the Nintendo Entertainment System shipped on cartridges that could only hold around 40k of data. Super Mario World (1990) for the Super Nintendo shipped on a 512k cart. Super Mario 64 (1996) for the Nintendo 64 ran in 8 mb, and Super Mario Sunshine (2002) for the GameCube came on a single 1.5 gb mini disc.

The reason that this increase in space is necessary is that the target resolution of the host device has increased over time. The original Super Mario Bros. was designed for a 256 x 240 pixel display, while Super Mario Sunshine was designed for 640 x 480, the standard SDTV resolution. This increase in resolution required that art assets also grow in size; extra pixel density isn't useful if you don't actually have content to fill it with.

This is true whether you're talking about 2D or 3D. In a modern 3D game, resolution is a function of texture detail and model complexity. Texture data includes normal maps, height maps, bump maps, reflection maps, and all kinds of other image data that has increased in resolution (or only recently become viable due to increases in storage space) since previous generations. If you are a gamer with a good memory, you might remember Hideo Kojima talking about how Solid Snake's mustache in Metal Gear Solid 4 contains the same number of polygons as an entire enemy character in Metal Gear Solid 3; presumably, the increase in complexity was necessitated by the move to HD televisions.

So there is a correlation between application size and target screen size. Just not one between application size and game quality.

Running the Numbers
To drive this point home, I took a look at the top games on three different digital distribution networks: Microsoft's Xbox Live Arcade, Apple's iTunes Store, and Android Market. Xbox Live Arcade games are written to be run on HD television sets with 1080p resolution. That's 1920 x 1080, or 2,073,600 pixels. iPhone apps and most existing Android apps are written to run at HVGA resolution, which is 320 x 480, or 153,600 individual pixels. So the XBLA games are running at a resolution roughly 13 times greater than that of the iPhone or Android devices like the T-Mobile G1 or myTouch 3G. So, if we assume that all things are equal and that cost of detail increases at a linear rate (neither of which are very true, but bear with me here), we can reasonably expect about a 13x difference in the physical size of the same content on an HD device compared to HVGA device.

Below is a graph comparing the average application size for these three networks. To calculate this average I used the sizes of the top 20 games (as of Nov. 3, 2009) from each network.




The average top Xbox Live Arcade game is 277 mb. Interestingly, paid games on both iTunes Store and Android Market tend to be a little larger than free games, perhaps because the cost of generating art assets requires the developer to sell the app rather than give it away. In any case, the average iPhone game is 21.5 mb, which is about 12.8x times smaller than the XBLA average--pretty dead on with our resolution-based expectation. The average Android game is even smaller--around 1 mb--though as on the iPhone, paid games tend to be larger than free games.

Though the Android games are smaller in aggregate, there certainly are a number of titles at or above the 10 mb mark on Android Market. This is within the same range as the top 20 iPhone games; Myst at 727 mb is clearly an outlier (and, as an aside, it's larger than all but two of the top XBLA games). You can fit a bunch of top-tier iPhone games in a G1, and even more in a myTouch or Droid.

It's interesting that the Android games are so much smaller. The most popular free apps are tiny--the average of the top 20 free games is only around 300k. This might have to do with how popular games are ranked, or the fact that paid apps have been available on Market for a much shorter amount of time than on Apple's platform. Or it might be something else; Labyrinth Lite, which is available on both platforms, is less than half the size on Android compared to its iPhone version. At any rate, even if the Android games were larger, the average user would still be able to fit a bunch of them on their phone.

So, Size Doesn't Matter?
I don't mean to suggest that size has absolutely nothing to do with game content. There are some types of games, like Myst, that are unusually data-heavy. But content quality isn't a function of size; Super Mario World's tiny 512k footprint is evidence of that. And Android should support installing apps to the SD card (though I suspect that some game developers would be uncomfortable with that option). In the mean time, apps are free to stream data over the network or cache resources to the SD card (as the Android Quake port does), though admittedly this isn't as elegant a solution as true SD card support.  Still, it's an easy solution for big games like Myst.

While we're on the topic, 727 mb for Myst is a fairly surprising number. The original version of Myst targeted 640 x 480 displays at 256 colors and filled a single CD-ROM; even assuming that the iPhone version is using 24-bit color versions of the original graphics, the reduced screen resolution of the iPhone combined with advances in CPU speed and image compression technology should make it fairly easy to cram the game into less space than it originally required. After all, they fit Resident Evil 2, a 2-disc CD-ROM game for the Sony Playstation, into a single 64 mb N64 cartridge!

Plus, a game like Myst should be trivial to stream over the network; the spatial layout of each room is known and so room images close to the player's current location can be streamed in the background. Even if the developer elected not to cache those images to the SD card, 16 mb of application heap is a lot of room for 80k images, so it should be easy to stream far enough ahead into runtime memory that the player never experiences a loading pause.

The point I am trying to make is not that the Myst iPhone developers did something wrong, just that there are many ways to implement this sort of game and not all of them come with huge space requirements. I suspect that Myst on iPhone is as large as it is because that was the simplest way to port the game, not because the game itself cannot be made any smaller. And there's value in that--giving developers as many options as possible to make applications is the number #1 reason that Android should support installation of apps to the SD card. But the claim that this sort of game is impossible on Android platforms is, I think, wrong.

Wrap Up
Game quality has almost nothing to do with application size. For most games, physical size is most directly linked to the size of the screen and the resolution that the host device is running at. By looking at a selection of popular titles, we can see that on HVGA devices (such as the iPhone, or myTouch 3G) there is a fairly small range within which most games of significant scope reside. Looking at the top iPhone games, that range is well within the capabilities of existing Android devices. And while there are exceptions, they are few and far between; the existence of outliers, especially those that are large because of implementation decisions rather than necessity, is not sufficient to damn an entire platform.

Should Android support installing applications to the SD card? Yeah, sure, that'd be great. Is the lack of that functionality blocking games from working on existing Android devices? Not in the slightest.

And for the record, Replica Island is about 4.8 mb, which is a little heavier than I'd like, but not heavy enough that I'm going to spend time doing something about it. It has over 40 levels.

Friday, October 2, 2009

Rendering With Two Threads

The Replica Island renderer is based heavily on the GLSurfaceView class that ships with the Android SDK. I've made a couple of modifications but the code is pretty similar to the regular version: a derivation of GLSurfaceView.Renderer that draws the frame gets called every frame, followed by a call to eglSwapBuffers() to actually display the rendered frame.

GLSurfaceView provides a way to run user code in the same thread as the renderer. This makes writing games pretty easy; you can just implement a Runnable, implement a Renderer, stick them both into a GLSurfaceView and get stuff moving around on the screen. Indeed, it's more than sufficient for many applications; my SpriteMethodTest demo works this way just fine.

But for Replica Island I took a different approach. The problem with the single GLSurfaceView thread is that eglSwapBuffers() must block on the hardware until the previous frame finishes drawing. That means that even if you have nothing to draw, a call to eglSwapBuffers() takes 16.67ms to complete. (And of course, if you have a lot to draw, it could take a lot longer).

Now, just in case you are not used to thinking in terms of milliseconds, here's a quick primer. To achieve the magical "60 frames per second" that many games strive for, you need to have a new frame displayed to the user every 16.67 ms. If you go for 30 fps, you have ~32 ms to complete a frame. All your game code, plus all your OpenGL code, plus the actual time it takes to draw the frame must fit within 16.67 ms to achieve 60fps.

In Replica Island, the game code is fairly heavy-weight. I have all that collision to run, plus updates of all the active entities on the screen, plus sound playback and all that jazz. Turns out that it's usually more work to calculate a single simulation step than it is to actually draw the frame. Since this code takes time to execute, the 16 ms block that eglSwapBuffers() incurs makes it really hard to hit 60 fps. What I really want to be able to do is run game code while eglSwapBuffers() is blocking; that way I can pipeline the game updates while the hardware is busy drawing the frame.

So I split the game code off into a separate thread. This makes three threads, by the way: the main UI thread that all Activities have by default, the GLSurfaceView render thread, and this new game thread (actually, there are a few more that are generated by the system for things like orientation sensor updates, but they don't affect the equation much). Now my game code and my renderer can run asynchronously, and I win back some of that time spent in eglSwapBuffers().

Now comes the tricky part. I have two threads running in parallel that need to sync up once a frame so that the game thread can tell the render thread what to do. There's a lot of ways to go about synchronizing these two threads, but I went with a double buffer solution. The game thread fills up a buffer of commands to draw the next frame, and when it is ready it waits for the render thread to begin the next frame. At that point, the buffer is passed to to the render, which can then go off and draw the next frame asynchronously. The buffer that was used to draw the last frame is passed back to the game thread, which fills it up again the next frame. So drawing is the process of swapping these two buffers back and forth during a (hopefully short) choke point at which both threads stop and communicate.

This solution was attractive to me because it was simple, and so far it seems to be plenty fast. However, another solution might be to have a queue that is shared by both threads, with the game thread pushing commands in one end and the renderer executing commands out of the other. In theory such a solution wouldn't need both threads to ever perfectly align--blocking would only occur when one thread or the other was starved. But I haven't done this yet because it is going to be significantly more complex than the double buffer.

My render commands are objects that are allocated out of pools that the game thread owns, and must be returned to those pools when they have been drawn. In the double buffer system, the queue that is returned from the render thread contains commands that can be safely returned to their pools, but in the shared queue system there's no obvious way for the game thread to know how much has been drawn. I suppose there could be two shared queues, one in each direction, but that would still be a lot more complicated than what I have now. Right now almost no code outside of the buffer swap system knows about other threads; the pool objects and the objects they contain are not thread safe and, as it stands, don't need to be.

Is my solution the best for Android apps? I don't know. It seems to work pretty well and it is uncomplicated, which are two points in its favor. Still, I'd like to give this shared queue idea a shot at some point; my gut tells me that it will be slightly faster than the double buffer (less blocking in the average case) but a lot more complex, which might make it not worth the effort. Programmer guts are, however, extremely unreliable, so I will probably give this method a shot after Replica Island ships.

Thursday, September 10, 2009

Why Android Flies

The main mode of movement in Replica Island is flying. The Android robot has thrusters in his feet, and while he can also slide upon the ground, most of the game is spent maneuvering through the air. Enemies are dispatched by dropping on them from above and the collision and physics systems make it easy to glide off of a ramp and into the air. I don't think this is a common approach for side scrolling platformers.

The reason that the Android flies is that many Android devices ship with a trackball. Some (like the Samsung Galaxy) have a d-pad, which works fine as well, but the devices from HTC (which include the G1, myTouch, and Hero) all sport a trackball. The great thing about a trackball is that it's an analog interface with a pretty high resolution. The bad thing about it is that you can't hold a single direction down like you can with a d-pad; to keep sending input events in a specific direction, you have to keep rolling in that direction.

When I started working on Replica Island, I knew that I'd have to do something different with the player controls to afford trackball use. Letting the Android robot fly seemed like a good solution: the player gets going in a certain direction and then only has to make minor adjustments in heading to steer rather than constantly depressing a button indicating the direction that they wish to travel. This sort control scheme is a bit like a car steering wheel--given velocity that you already have you just need to worry about turning left and right. Indeed, in early prototypes it was clear that the trackball would work very well for this sort of analog maneuvering, but I also quickly learned that it's hard to make precise movements with a trackball.

My initial implementation let the player move left, right, and up by rolling the ball, and while it worked and was playable, people had a really hard time moving in only one direction. It was too easy to accidentally roll up a little when trying to go left or right, which made the controls feel unwieldy and arbitrary. After experimenting with dead zones and other input filters, I finally reduced the trackball to horizontal movement and put a jump/fly button at the lower-left hand corner of the screen. This is a much better solution because it allows players to manage their horizontal and vertical velocity independently, much like they can with a d-pad or other traditional game input device. Furthermore, by ignoring vertical movement on the trackball the control scheme became a lot more forgiving to minor input mistakes.

Replica Island is playable with three inputs: the jump/fly button, left and right controls, and a drop/attack button. These three inputs were decided upon to allow the trackball to feel good, but they map well to other input systems (like a hardware keyboard or d-pad) too, so Replica Island is playable on a wide range of hardware.

Once I settled on the trackball-based steering approach for movement, many other aspects of the core game design fell out. I posted earlier about the collision detection system I wrote to support slopes and angles; this system was necessary to allow for ramp and bounce physics. The Android robot can slide across the ground but it's a lot more fun when he's in the air, so I needed to have a collision and physics system that allows him to take flight easily. Sliding down hills or going off ramps feels good and works well with the control scheme.

This approach also simplified animation: if the Android robot is going to fly with thrusters in his feet, he doesn't need a walk cycle, a run cycle, a turn animation, a skid to stop animation, a jump windup or a jump peak or a jump fall animation. His motion system is more complicated than most of the side scrollers I've made in the past but his animation system is extremely simple; the control scheme afforded this simplicity.

As awesome as Android is for games, the devices it runs on are not generally designed explicitly for gaming. To make a fun game, especially one that is part of an established console-oriented genre, you need to come up with a control scheme that works well for the hardware, even if there's not a lot of precedent for it. In the case of Replica Island, I started with the control scheme and the rest of the game design flowed out from there; as a result, I think that it's a quite playable platformer despite its rather unconventional controls.

When making games for this type of system, it's important to consider exactly how the available inputs are going to make the game fun; if you try to just glue controls from some other hardware paradigm onto a game running on a phone the results are almost guaranteed to suck. Getting the controls right is probably the single most important task you have as a game developer, and if you can nail them down early enough, a huge part of your game design will pretty much write itself.