Sep 23

Oh, It’ll Be Out By….

Hmm, even now as I look back on what’s been done on Outwitters, I’ve learned a *ton* of new things in regards to game development. I’m not too excited about having only 1 game to release this year (if we even make *that*). Hell, we even planned on having 2 games a year. The take-away from that is game development is not an assembly line process. Going into Outwitters I:

  1. Never coded a turn-based strategy game before
  2. Never worked on an asynchronous game before
  3. Never worked with Google App Engine
  4. Didn’t use unit testing prior to this game
  5. Never worked with push notifications
  6. Never worked fully in C++ in a commercial project before
  7. Knew little of JSON and it’s benefits
  8. Hadn’t used Actionscript to the capacity that I am now
  9. Haven’t touched Python since freshmen year of college (omg I love python again)
  10. …and several others

Looking at just that list above, which isn’t even scratching the surface, it was dumb to think I could predict *any* sort of release date prior to starting this project. Unless you’re phoning it in game after game, or the game has a very small scope, or you just have many years of broad experience working on several different kinds of games, platforms, and genres, scheduling is almost silly to think about. Having only been doing this for a couple years, I’m far from the “broad experience” category. There are a few constants in game dev, such as getting your boiler plate code, foundation, or engine ready to go, or a super basic prototype up and running, but beyond that it’s just a hazy mess for me at the moment.

The great thing is now I know a decent amount of everything on that list. If we were to do another asynchronous TBS game for iOS, scheduling would be far less hazy. But that’s the dilemma. I sure as hell won’t want to dive into another “Outwitters”-like project after this for a while. I get excited about new games and new ideas (most involving multiplayer to boot). I’m interested in things I haven’t tried before, and as a result, they’ll always be difficult to estimate length of development, but the challenge is what makes it fun for me. Even if we were to revisit a previous game and make a follow-up, I would want to add or change something about it that would make it unique, because that game is already a “solved problem” and is pretty much just grunt work from start to finish with little thought involved.

Outwitters Battle Report

This week I finished up implementing custom games into Outwitters. Outwitters was designed to be played with friends, so it’s kind of weird having this feature come online so late in the game. Our Leagues and Ladders system works with 1v1, but we wanted to make sure to have 2 vs 2 in there as well so you can still take on the world with a buddy. Things are always more fun with a friend in tow :). Custom games are just a way for players to create their own games with their own settings. They can choose who is in the game, who is on what team, and the map. The league system tends to take over a lot of those choices to make things a bit more ‘standard’. Wins and losses don’t count in custom games, so it’s a nice place to try out strategies or just play with friends casually.

Speaking of leagues, the matchmaking and ranking system is finally online as well. It’s not too interesting to look at yet since the player numbers are still very low. At least not my profile, since i have zero points and can’t win a game to save my life. I’m apparently strategically challenged when it comes to these games. Probably explains my horrible performance in Starcraft 2. I tend to be impatient and like to throw my army away like lambs to the slaughter when the engagement heavily favors the opponent instead of me. Oh well, there’s always Battlefield :D.

Sep 9

This following post is probably going to be useful to an extremely niche audience: anyone developing a multi-user iOS app that has a GAE backend. I’m currently working on Outwitters and debugging turn-based games on the local dev server (dev_appserver.py) is really quick and painless. The problem arises from the nature the game. It’s a multiplayer game, and as such, requires multiple users to function. You can only go so far with creating ‘mock user’ accounts, and fake data populating your local server. With each build I always find some sort of issue that the alpha testers stumble across that may not be server-related but the gamestate that the “production” server is holding is something I want to grab and debug with locally. Wouldn’t that be nice?

So when you run a local dev server the command is pretty simple:

[code]

dev_appserver.py pathToCode

[/code]

Not bad. Now if you want to access it on your machine you simply do an http request to localhost:8080. The problem comes in when you’re developing for a mobile device. The dev server is no longer at localhost but on some local LAN IP. That’s a pretty easy fix too:

[code]

dev_appserver.py --address 192.168.1.x pathToCode
[/code]

Now in your iOS app you can send requests to a local server. We’re in business, awesome! So you want to download the data from your hosted application over at appengine.google.com? Pretty simple. Uploading it is pretty straightforward to if you use the –url option with “appcfg.py upload_data”.

Now this is where I ran into problems, and I couldn’t find a clear cut answer as to why uploading data to my local dev server was simply not working. It would ask for credentials, and no matter what I put, it would fail. Hopeless. I used all sorts of combinations of my local address and ports for the –url flag for appcfg.py and tried countless combinations of any of my known logins for both appengine and my local dev machine. I then decided to go back to basics, and follow their instructions exactly. I downloaded the production data as documented. Then I launched a clean dev server with no command line options. It worked as advertised! I had all the data frolicking about inside my dev server, but I couldn’t access it with any of my iOS devices. Without the address option, the dev server would launch with localhost as being it’s address, and no other device could connect to it.

So after banging my head on the keyboard for a couple hours, and not being able to find any answers as to why upload_data only works to a local dev server if you’re running on localhost, I found a round-about way of getting production data into my own iOS friendly dev server:

  1. Download the data as per the documentation
  2. Now launch  dev_appserver.py, but this time declare a datastore path as a command line argument. This is the –datastore_path= option. Also run it with a –default_partition of “” (empty string), to mirror production’s data.
  3. Now that you have a dev server running on localhost with a defined datastore file, upload your data to your dev server with appcfg.py (by using the –url option pointed to localhost).
  4. Once uploaded you can now shut down that server.
  5. Now run a dev_appserver with the commands that you usually run with (the –address flag), but add a –datastore_path pointing to the datastore file you used in step 2.
  6. W0ot!
A lot more cumbersome than just doing a simple download/upload routine to test stuff locally. Of course, I may be missing something entirely as I’m still relatively new to GAE, and there may be a way to do this with a local dev server that is running on an actual LAN ip instead of localhost, but I haven’t been able to find it. Hopefully this will prove useful to those using GAE for their iOS apps as well, or they’ve found a better way to do this and can leave a comment :).
Aug 15

My first week off the iDevBlogADay rotation and I miss my usual Friday post. Go me. We’ve kind of hit a period where a lot of work is getting done, but an ever growing mountain of work is coming up on the horizon. Polishing a game is hard. Polishing an online turn-based strategy game is really hard. The simplest things take 3-4 more extra steps to do whenever you incorporate a server into your game’s architecture. Noted. Turn around times are my biggest hurdle due to the larger scope of the game and Xcode’s stupid way of managing resources. Left to it’s own devices, it doesn’t copy new bits every time, so a work around is to essentially ‘touch’ the root folder to have every resource re-copied on every compile. The downside? Long deployment times due to a huge number of assets. To help mitigate this I wrote in some asset hotloading into the engine so  I can iterate on UI a lot faster. It was definitely worth the day of implementation.

And now, I’m starting to see the value of unit-tests even though I’m not doing them yet. In prior games, the code base was small enough, the turn-around time so quick, and the permutations of input so limited, that it was the same amount of time, if not quicker, to simply run the game, test the UI or mechanic, and fix it. But now, the actual game logic complexity is growing so much that whenever I’m met with a new thing to implement or test I get a sense of dread of how many turns it takes to setup a game board, execute the test, and when it inevitably fails, debug it and try again. I don’t think it’s too late for me to start doing unit-tests, so I think I’ll get that going. The game’s setup I think lends itself well to unit-testing since all the game logic happens separate from the visuals. I don’t think it’ll be completely necessary for me unit-test the visual stuff (due to the nature of the thing), but having just a few unit tests covering the game logic will really help test those obscure edge cases that would be a pain to test manually, as well as help stop regression (which is already happening)

Now I’ve tried doing unit-tests before in older game projects and hated it. Why? Because I didn’t get the sense that I was  getting much benefit from it versus my old way of just running the game. it just seemed like an exercise in typing more code.  It’s interesting to note, that a lot of the advice one hears from devs about the more mundane tasks of game development (hot loading, unit-tests, asset pipelines) become this ‘awesome thing’ that saves the day when you finally hit a point in your development cycle that would tangibly benefit from it. Academically, I was told repeatedly to write unit-tests. In the “real world”, I saw no explicit need for it, until now. So I guess the takeaway is don’t blindly follow other devs’ mantras unless you can see where it makes sense, but be knowledgeable and aware of them. In the case of unit-tests, it didn’t start making sense until last week when I was seeing how much time I was spending “playtesting” the game for bugs and such. Experience is the best teacher as they say.

May 6

So what’s new in the world of OML and Outwitters? Not much really. Just keeping our heads down and working through some of the boilerplate stuff. We iterated a bit on the prototype over the week for visual elements to help make the game more approachable. I got my feet wet in Google App Engine and threw together really basic asynchronous functionality into the prototype in about a day just so I have a clearer understanding of how those things are going to work. Best way to figure out how to do something is to just do it sometimes.

The next thing I’m focusing on is UI and UI tools. In Tilt to Live I had a lot of fun coding up a basic UI system that allowed for easily adding transitions on a per element basis. The problem? modifying the UI was extremely cumbersome as it required a code change and re-compile. Not to mention there was no visual aid in laying it out, so beyond just looking at jpeg mock ups in photoshop, there was a lot of trial and error in getting things lined up correctly. The “screens” are still organized as a stack. You can push new screens on top, remove then, etc. This setup makes it much easier in handling things like “going back”,  switching game state, or handling pop ups.

I’m using a similar system for Outwitters again with a few modifications. I’ve separated out the UI logic from the Screen class into a controller class for a more traditional MVC setup. So now layout data (even if it’s still c++ code) is separate from UI logic and I can edit it with reckless abandon.  This also opens the door for making the layouts data driven. I can put together a layout tool that allows me to visually layout elements on a screen and save them into some sort of format for the game to load up and attach a controller to. This by itself would really help speed up the process of creating the UI we need for the different elements in Outwitters, which is a bit more UI heavy than Tilt to Live.

Yet, I’m wanting to take it one step further and allow me to author transitions in the tool so the UI can be animated in a similar manner to how Tilt to Live’s UI worked. This would be a huge boon and allow us to create fancy-shmancy UI presentation without all the verbose function calls I previously used to achieve the same effect. I guess at this point it’s just a matter of deciding “how detailed” I want this tool to be in terms of animating the elements. There’s no way I’ll be able to achieve the fidelity of what a flash powered UI with an actual artist/animator can achieve, but hopefully it will still be better than the basic ‘powerpoint presentation’ feeling I get when I play some games.

I’ve been looking at “off-the-shelf” solutions of flash integration recently and I haven’t found anything that’s been satisfactory. Usually, there’s a huge gotcha in the free/cheap areas (incomplete implementations, or said to be buggy) and in the commercial market, it’s just too cost prohibitive for a small team to use (looking at you, ScaleForm). Yet, like many things, I won’t truly know the extent of what GameSWF can do until I give it a try. I suspect it’s using standard OpenGL, but looking around there seems to be an iphone compatible version floating around. Just briefly glancing around the net on discussions about this topic, the arguments seem to be wishy-washy. There’s mentions that it’s usable for UI, but actionscript support is spotty in a few places. Seeing that all I want is a way to animate bitmap transforms easily, and get callbacks for taps on menus, my requirements hopefully aren’t too strict. The few that have reported back on their success/failure of using gameswf seem to be stating that writing UI may require scripting, which isn’t friendly to artists. Since I’m handling a lot of the UI work, it doesn’t seem like a huge hurdle. Performance has been listed as an issue, but that was pre 3G.

In any case, I’ll be playing with gameSWF over the next couple of weeks and report back, while we continue work on game balance for Outwitters. If it doesn’t work out, I’ll continue on with my original plan of writing a custom tool for my specific UI needs. Next week is lots of playtesting, tweaking, and also fixing some Tilt to Live bugs!

Apr 22

As we’ve announced on the OML site, our new game has a name: Outwitters. It’s been quite busy for the last couple of weeks, but I’m loving it. Being able to tackle new problems and going outside my comfort zone in terms of game development has been pretty fun so far. I’ve never coded a turn-based strategy game from start to finish, so I’m having to learn a slew of new concepts and design patterns to help mitigate the complexity of the game’s rules. I’m usually coding physics-based dynamic gameplay where things are far less rigid and you are coding a vague system of rules the user can easily manipulate.

A hurdle I recently got over was managing the complexity of all the animations Adam is churning out. We have quite a few frames of animation that needed to be edited in bulk with all the color permutations and classes. With the help of Blitzmax, Photoshop scripting, and TexturePacker, I set out to write a simple character animation editor that allows us to edit one animation and apply it to all the different team colors and different resolutions (iphone,retina,ipad). Also when new units are done and ready to be animated, the editor automatically generates stock animations for each new character so we’re only going in and adding in a few frames and tweaking timings in some of the more elaborate animations.

The art pipeline  process for characters has become:

  1. Run a photoshop script to process all PSD files to convert layers into separate pngs in set folders.
  2. Run a command line script (written in blitzmax actually) that takes the pngs and automates TexturePacker to spit out spritesheets and json files for all the different resolutions into a designated folder
  3. Open Character editor, and if it’s a new character go to file->initialize character and all the stock animations and animation files will be generated based off the pngs and json files in the chosen folder
  4. do any manual edits to animations in the editor itself
  5. File->save and go celebrate since you’ve just processed a couple thousand files in about a minute.

I probably could have automated step 3 itself, but since one of us is usually going straight to the editor to edit the new character, it’s just an extra click so I took the lazy route there.

 

We hit another major milestone earlier this week with the fully playable ipad prototype finished with our first iteration of the UI/Interaction. So now we can get a decent number of games played. This’ll hopefully help us get a good amount of feedback on balance, game rules, and how usable the game UI is, while working in parallel on some of the ‘shiny stuff’ for the game. Lots of progress in the past week! Now I’m going to scurry back to my cave as there is still lots of science left to do…

 

Feb 14

Tilt to Live HD’s Viva la Turret mode is now live and people seem to be enjoying it. One of the bigger hurdles in this prior update was getting in app purchases to work the way we wanted them to without violating the standard user experience of IAP. I figured I’d share how I went about solving this for Tilt to Live HD specifically. We had a few business goals in mind:

  • We wanted to maintain parity with the upgrade model we went with on the iPhone, which was a simple in-app purchase to get the new mode.
  • We still wanted to maintain the ‘demo then upgrade to full version’ packaging of Tilt to Live HD for a single price, as we still believe it appeals to a certain type of gamer that wants a more traditional model for buying a game.

In a way, it seems our two goals were at odds with each other. We wanted players to have an optional upgrade, but at the same time we didn’t want the ‘full version’ to break down into “meh..it’s kind of the full version..but not really”. Our solution was to treat it as a paid upgrade for existing users, but bundle the new mode in with any new customers who bought the full version of Tilt to Live. The caveat being we did not want to break it down into some sort of ‘store’ list, where a user could inadvertently end up buying the wrong version and be double charged for overlapping content. We were pretty proud of the IAP integration in HD where it was a relatively seamless experience that didn’t involve any UI that required a “store” button. We simply showed you the gametype option and it was locked if you didn’t have it, and unlocked if you did.

With the additional new mode, we now had 3 basic states you could possible be in.

1. You have the demo version of Tilt to Live HD, so the gametype select screen is pretty standard and you see 1 in app purchase that includes everything:

2. You have the full version of Tilt to Live HD prior to February 8th. The gametype select screen should show you just the small IAP for the single Viva la Turret game mode:

3. You have the brand new full version of Tilt to Live HD, so everything is unlocked:

Now this sounds all well and good and pretty straight forward when I first considered it. Then came the technical details:

  • The behavior of IAP is such that it mirrors functionality like App Store purchases. If you’ve ever bought that IAP before, you can buy it again, but a pop up will notify you that you already own it and are downloading it again for free.
  • If a person has never restored, then simply checking what modes in the client are unlocked is sufficient and is the path of least resistance.
  • If a person has restored/re-installed, there is no API from Apple to determine if a person has already bought a piece of content before they try to buy it again, which could result in angry customers being double charged if they were in state #2 (pictured above) but have re-installed and ended up buying the full version again as if it was in state #1 (pictured above).

Essentially, when a prior customer re-installs our game for whatever reason, there was no way for me to determine whether they never bought the old full version and we should upsell the entire new full version, bought the old full verison and we should upsell just the game mode, or if they already have the entire thing unlocked (either by buying the old full version + the turret IAP or by buying the new full version that includes everything). Confused yet?

The riskiest thing was that I did not want to have a situation where a person could inadvertently buy the entire brand new ‘full version’ IAP when all they needed to buy was the small turret IAP. With the StoreKit API lacking any sort of method to determine a user’s purchase history, and with Tilt to Live HD not using any sort of server solution to track receipts,  I was running out of ideas. Then I got the idea of experimenting with a little “hack” to simulate the same IAP experience.

When a user taps on the ‘buy’ button for any IAP in the game I decided to instead force it to restore purchases all the time. Using a small collection of state variables when a restore was finished I would check to see if what they were purchasing was in line with what was restored:

  • If so, do nothing and give a standard dialog showing they restored successfully.
  • If it was in conflict, let them know nothing was purchased but their previous items restored. I would then refresh the upsell screen showing what they could really purchase.
  • If there was no conflict and they, in fact, don’t own any part of the IAP, then I would immediately push the purchase through. The great thing here is since it happens right after the restore, the user is never prompted for their password again since they already did so during the initial tap of the buy button to trigger the restore.

When going about implementing this I had a few false starts and dead ends, but after re-reading the documentation and a bit of experimentation I finally grokked most of the restoration API from StoreKit.

There are two methods involving the end of restoring tranactions. There is one that is called at the end of each IAP item restored:

[code]
-(void)restoreTransaction:(SKPaymentTransaction*)transaction
[/code]

And then there’s a method that is called when none, or all IAP items have been restored:
[code]
-(void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue
[/code]

The former I left alone to act as it normally would under any restoration of transactions. The latter method, I modified to behave as an ending point if the user really tapped on ‘restore purchases’ or a beginning point to analyze what was restored and to continue with the purchase if needed. Below is the method in full in case you’re curious:

[code]
-(void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue
{
if(iapTransactionState == kIAPTransStateRestoring) // restore as is.
{
[[NSNotificationCenter defaultCenter] postNotificationName:kInAppPurchaseRestoreSucceededNotification object:self userInfo:nil];
}
else if(iapTransactionState == kIAPTransStatePurchasing)
{
if([self isContentUnlocked:purchaseItemID])
{
// if it's been restored or unlocked already then no need to do it again.
[[NSNotificationCenter defaultCenter] postNotificationName:kInAppPurchaseTransactionAlreadyHaveItemNotification object:self userInfo:nil];
} else {
//...unless we're already in some half-bought state (full -> full+turret)
bool makePurchase = true;
if([purchaseItemID isEqualToString:kIAPFullAndVivaLaTurretID])
{
// if after restoring we found the player purchased the full and viva separately
// don't go forward with payment for the bundle.
if([self isContentUnlocked:kIAPVivaLaTurretID] || [self isContentUnlocked:kIAPFullVersionID])
{
makePurchase = false;
#ifdef DEBUG
NSLog(@"bundling purchase error");
#endif
}
}

if(makePurchase)
{
// continue with the purchase
SKPayment *payment = [SKPayment paymentWithProductIdentifier:purchaseItemID];
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
else {
// send a bundling error message
// or a restore complete if they have entire bundle
// because they purchased it separately (upgraders)
bool hasBundle = [self isContentUnlocked:kIAPVivaLaTurretID] && [self isContentUnlocked:kIAPFullVersionID];
if(hasBundle)
{
#ifdef DEBUG
NSLog(@"has complete bundle, no purchase made");
#endif
[[NSNotificationCenter defaultCenter] postNotificationName:kInAppPurchaseTransactionAlreadyHaveItemNotification object:self userInfo:nil];
}
else
{
[[NSNotificationCenter defaultCenter] postNotificationName:kInAppPurchaseTransactionAlreadyHavePartialBundleNotification object:self userInfo:nil];
}

}

}
}
#ifdef DEBUG
NSLog(@"restore done");
#endif
// [[NSNotificationCenter defaultCenter] postNotificationName:kInAppPurchaseRestoreSucceededNotification object:self userInfo:nil];
}
[/code]

I can’t say this is the most ideal solution since I feel it’s using the StoreKit API in a slightly unorthodox way, but it works well. So this is one way of implementing a ‘paid upgrade’ for IAP items. If we were selling more items in a more ‘freemium’ type model it might’ve been a good idea to generalize the above code to handle upgrades for any item, but since Tilt to Live HD’s model is a one-off IAP I didn’t bother generalizing.

Feb 2

I’m still in the middle of finishing up our Co-op mode for Tilt to Live and coding in the last odds and ends to polish up the UI. The gameplay rules have be finalized and it’s been a hoot to play. Yes, I said hoot. We’ll be playtesting the mode in the coming weeks to do any minor tweaking to the physics and balance.

The wireless P2P GameKit API has been pretty cool to work with. It certainly takes a bit longer to get something tangible out of it because it’s a relatively ‘invisible’ piece of the iOS SDK  (as opposed to Core Animation, UIKit, and the like). Yet there’s always something inside me that goes “that is so damn cool” when I finally see a game running on two separate devices and are interacting with each other.

I’d like to write up a mini post-mortem after the co-op update is done looking back at adding real-time networked play to an iphone game. But for now, the biggest hurdle was realizing that running with the GKPeerPickerController  limited you to only bluetooth. The docs weren’t 100% clear on this and I was beating my head on my desk seeing people claiming GameKit worked over Wi-fi with no issues and I couldn’t get any device to talk to each other without bluetooth. Couple that with a faulty router setting keeping my iDevices from connecting to each other and it was a painful couple of days. In any case, let it be known, that if you wish to support local Wi-Fi and Bluetooth transparently you’ll need your own custom UI outside of GKPeerPickerController for clients connecting a host.

Oh, and the utter joy I experienced when I realized I had to change zero networking code to have it work over w-fi was indescribable. I think I fell in love with GameKit at that point since I was anticipating  a day of refactoring, integrating bonjour directly, and whatever else I had in mind to keep the game-level networking code intact.

For anyone thinking about doing some real-time multiplayer game on the iPhone, the biggest problem you’ll probably face is interference, followed by throughput (when dealing with bluetooth anyway). iPhones are jam packed with so much wireless technology that it seems if the wifi or 3G antenna so much as thinks about sending or receiving data, bluetooth communication suffers horribly.  I’ve had many a game end in death when I received an e-mail or text during gameplay. We originally intended on supporting nothing but bluetooth, but given this type of wildly varying performance we needed to have a fall back solution that was a bit more reliable. Thankfully, GameKit made it easy. While I was hoping I wouldn’t have to code up a custom UI (pictured above) because of GKPeerPickerController’s magic, in the end it added more robust functionality, as well as felt a lot more integrated into the game.

Jan 14

January started off with quite the busy schedule and it hasn’t let up yet. So much to do so little time! Viva la Turret has turned out to be a critical success and people are enjoying it so that’s great. Coming right off the heels of that I wanted to update Tilt to Live HD with Game Center support. It came, and we screwed up (again) :[. There’s a bug with the scoring that cropped up after I added a last minute fix to a less serious bug involving double vortexes. We do have a thorough test plan for our releases, but given the small amount of features/fixes in this one we didn’t exercise all of them. Hah, the code goblins struck again.

What’s funny is there have been moments throughout the year when I look around and realize how freaking awesome things are going. I feel like we’re on a roll and it’s like racking up a crazy combo in some shooting game. Release done and shipped. BAM. Release done and shipped. BAM. ANOTHER Release done and shipped. BAM! That is usually the very moment a dreadful thing occurs. Usually involving HD. And it’s already live and tanking our reviews. It certainly takes the wind out of my sails.

No developer wants to be seen as someone who writes ‘buggy software’, so it’s something I’m striving to improve. So what am I working on as of late?

One Man Left

We’ve got an update in for Tilt to Live HD submitted this past Friday to fix the scoring bugs. We’re also wrapping up testing on Viva la Turret HD and it’s proven to be pretty fun, yet still feel slightly different compare to the iPhone counterpart. Also got some other stuff in the pipeline for Tilt to Live that may or may not come to fruition.

Blitzmax

So I decided this year to make more time to code outside the daily projects of OML. Every few nights I’ll get back into the swing of Blitzmax and started poking around with a game framework I had written for it years ago. It was written when I was in college and it shows. It’s very ‘academic’ feeling when using it. I was pleasantly surprised at how flexible it was, but there’s a lot of tedious code to write to get a ‘blank project’ up and running. I guess back then I had oodles of time, haha (not). I also got it compiling on OS X, so having two clients on different OSes talk to a windows server with minimal fuss was a neat thing to see :).

I think my next steps will be to rip out the WxWidgets integration I did back then, using Brucey’s module. I had originally intended to code in an integrated editor with the game Unreal Engine-style, but recently decided against it for simplicity’s sake. I’m just going to fork the current codebase and create a dedicated editor out of it while having a ‘game’ branch that is hopefully more lean and mean.

Misc Dev

I haven’t begun any actually coding yet, but I’ve been toying with the idea of creating a 2D editor using Cocoa/Objective-C and OpenGL. I’m currently working on some preliminary stuff for “Game 2″, and intend on trying to keep it mostly C++. With that said, writing an editor on the Mac using Objective-C would give me the bonus of re-using a lot of the game code in it for handling things like rendering, input, etc. It wouldn’t be difficult but I guess it comes down to time. Cocoa seems like a really nice UI library, but I’ll admit I’ve never done much of anything in UIKit beyond hooking up an OpenGL view to the window and going back to XCode, haha.

Where as, if I were to just leverage the code I had written in Blitzmax with WxWidgets I can kind of hit the ground running in creating editing tools for Game 2, as well as making the tools cross platform. The drawback being I’m using 2 separate code bases and 2 separate languages. Although, I think I’m just blowing that out of proportion since a Cocoa editor would most likely be a fork anyway. It would certainly provide me the freedom of just messing with the internal model of how objects are structured since I wouldn’t be concerned about game code. When doing editors in the past I found trying to get relevant data out of game objects to manipulate in an editor went against a lot of the encapsulation and designs in place for the actual game. So this may be the better long term route.

Cocoa? Blitzmax? Jury is still out on that one. I also don’t think I can make a fair judgement until I actually try coding some basic tool using Cocoa UI on the Mac. And why Blitzmax? Well, it’s just that I happened to code in it for years so I’m using what I know. And it’s nice. Too bad there isn’t a good native mac editor for it. I use Blide (running in a Windows XP VM) for Blitzmax coding.

Oct 18

Ok, that title is kind of misleading. But for those who caught the reference, *high five*. I actually pulled gyroscope support from our latest Tilt to Live update. I had it implemented into the game at one point but through beta testing eventually killed the feature. I just wanted to go over the details as to why it went the way of the dodo bird.

Gyroscope != Accelerometer

Alright this a biggie. With the gyroscope on iPhone you can detect the orientation of the device in any position. This is great and actually not a limiting feature. You can calibrate the device in any position. Hell, you can calibrate the device while hanging upside from a jungle gym on a pre-school playground and it will work without a hitch. But there is a subtle difference as to how your tilt offset is calculated. The gyroscope offsets are calculated off of absolute orientations, where as using the accelerometer offsets are calculated off of relative orientations to a gravity vector.

Before I go any further, let me explain why I went down this dead path for tilt controls. When you calibrate a device off of the accelerometer there is a ‘gymbal lock’-esque problem when the device is 100% vertical. Any horizontal tilt cannot be detected because you’ve lost this degree of freedom since one of your tilt axis is aligned with gravity (what the accelerometer works off of). When the gyroscope was announced I naively thought, “Hey we can probably make the perfect tilt controls now that work in any position!” I got the ‘any position’ part down, but it was far from perfect.

Complexity in the UI

Another ding against gyroscope was due to the nature of how it worked, I couldn’t find a way to automatically turn it on and off without a large chance of the user becoming confused. As a result, I needed to create some UI interface to enable gyroscope controls. And wow, it was a hard one. Trying to explain the nuance of how the gyroscope works, without getting technical so that the user can make an informed decision as to whether they want it or not was…a bit weird. How weird? When you have to write up text that says this:

You’re probably doing it wrong.

We found it pretty funny and in line with the rest of the humor of Tilt to Live. But it just wasn’t easy to explain. Complexity in the UI was actually one of the main reasons we decided to pull it. We didn’t want Tilt to Live’s calibration to become this screen of knobs and switches, even when you’re doing a custom setting.

We weren’t kidding. Cars = bad

Step 1. Calibrate using gyroscope

Step 2. Play the game. (You so happen to be in a moving vehicle)

Step 3. This vehicle takes a right hand turn

Step 4. Owned.

The handset, in “real world” space is actually rotating when the car turns, but in local space relative to the car it isn’t. Bad news for people who are now wondering why their little arrow turned suicidal after they got off that exit ramp from the highway.

This issue ultimately clinched it. Having to calibrate not only the orientation but the actually direction a player is facing was too much. There was too large of a margin for error.

Gyroscope is awesome, we just weren’t meant to be….

With all that said, playing around with the gyroscope was awesome. It allowed me to play Tilt to Live in one-handed portrait mode because of the freedom it provided with calibration. But that freedom is very short-lived as soon as I get up, turn in my chair, or any other minor movement.

In the end, if you’re making a tilt-based game mechanic gyroscope may be of a more limited use when you actually stop and think about it. Unlike me, who did very little thinking and went ahead and tried it :). I did have a period in there where I was completely convinced that there was an elegant solution to combining the accelerometer data and the gyroscope data to create a fully working “hybrid” of sorts. It never came to me, but I’m sure someone out there much smarter than me that could write a proof proving or disproving this problem and make my head explode.

Sep 27

Let me first start off by saying how great it feels to be genuinely “busy”. I’m talking about the “excited-and-can’t-wait-to-get-started-or-get-finished” type of busy. I’m slowly finding out that the days are flying by with me barely noticing. Each morning, I’m looking forward to getting to work (yes, even Mondays). So either I’m strange or have found something I truly love doing :). Anyway, I don’t have any technical insights for this week’s post, just more of a status update on something I’ve been tinkering with. Noel of SnappyTouch fame has a similar article about version control, so definitely got check it out to get another (and more experienced) perspective.

The Issues With SVN

As see in some of my previous posts, I use SVN for version control but I figured I’d give an update to my ‘branching’ method. It utterly failed. What’s my current workflow? Branches and merging are much more the exception than the rule right now in my current code base. After a full release of Tilt to Live I’ll branch again to start 1.n+1 but won’t branch for any other issues or experiments. I tried for a while getting SVN to merge things, but I found myself missing files, deleting things that didn’t need to be deleted, and sometimes accidentally working in the wrong branch. Doing an “svn switch” had weird issues where it would sometimes not switch the entire structure but only the root folder I switched from (grrr…).

In any case, branching and merging caused more problems than it solved using SVN. So I went to the ‘merge only on releases’ approach, but that was riddled with issues as well becomes the changes were so large it would cause all sorts of conflicts. I eventually gave up and just ‘branched’ the branches into tag folders to save the bits that were released. Not a bad method, but not exactly how I wanted to work and SVN was forcing me to do things it’s way.

So I have 2 things I’m looking for in a version control system:

  1. Painless branching/merging with decent history tracking between branches
  2. A good GUI client

I kept looking into alternatives, and the two that kept cropping up were git and Mercurial. I liked the idea of git, but the problem was no decent GUI support. Both, according to what I’ve read, seem to satisfy the first requirement, so it came down to GUI clients. I’m fully capable of using a command line and willing to as long as it’s and not on Windows or overly tedious, but I still prefer quickly glancing at a GUI to get a sense of what’s going on.

The Experiment With Mercurial

Enter Mercurial. Over the weekend I decided to take mercurial for a spin. And the GUI issue? MacHG seemed up to the task, and is free to try for non-commercial use (donation ware). @SnappyTouch, not sure if you’ve given macHG a look over but it’s definitely seems as robust if not more so than Versions :). I took about 30-40 minutes to go through the quick start guide for mercurial and once I had things down on the command line and understood what the terminology meant, I installed macHG to see if I could use this in a development environment. After a few false starts I was up and running. Surely, mercurial is rather different from SVN since it’s a distributed version control, but from my perspective it worked just the same, if not better than a central one. The biggest bonus was branching (in mercurial it’s usually called cloning) and merging were very painless. It was just as easy as committing changes.

For my test run, I was in the middle of prototyping our next project but wanted to use some framework code to help kick start things. I created a repository with the framework in it, cloned it and started developing the prototype on top of it. As I worked and modified the framework bits I would commit and periodically merge the framework back into ‘main’ repository once I knew it was working and tested. No hassle, no conflicts. To further see if there’d be any pain points, I worked in the ‘main’ repo for a bit of code clean-up while the cloned version was also modified. Still no issue, and it was intuitive as to wtf was merging and changing. As for MacHG, it works very similar to Versions except has full on support for merging, tracking changes, etc. It’s very well done.

The Current Downsides

The downside? It’s a local repository. My SVN repo is hosted with dreamhost so I can get to my code from just about anywhere. But in practice, I have an iMac and no macbook so the only place that code would be useful would be on my iMac. Accessing SVN from multiple machines was crucial a few months ago since I was still transitioning between Windows PC dev and OSX dev, and some of my tools are windows only. But VMWare Fusion and Dropbox solved that issue pretty quickly. If I really need a hosted mercurial solution I may look into Fogcreek’s Kiln since I already use FogBugz. Another downside: doesn’t seem to be any svn:external equivalent. I don’t use it currently for iPhone dev but I did extensively on the PC for shared code bases and such so it’s something I’ll have to try to figure out or look up as I’m sure others have worked around this already.

To Each His Own

If you’re looking to try out a version control alternative, but think ‘git’ is a bit too bleeding edge without a decent GUI client, mercurial seems like a mature and well supported option (particularly on the GUI client front). I’ll definitely be using it for my ‘play area’ and see if it grows on me before I use it on a longer term project. But as is usually the case, it comes down to your own workflow and whether you’re tools are shaping your workflow instead of them helping you get your task done the way you want it to be done.

« Previous Entries