Twitter Integration with Cocos2D and Twitter-OAuth-iPhone
If Facebook is the new email, then Twitter is the new... what? Text messaging? Micro-blogging? Or perhaps just simply a better way than either email or texting to keep your friends updated on your latest comings, goings and accomplishments. It's not too surprising then to see Twitter integration in games, especially iPhone games. One of the more popular integrations was Canabalt (http://www.canabalt.com) which used Twitter as it's exclusive global high-score service rather than the more typical Open Feint. For our game Sumo Tap, we wanted to use that as well:
With the addition of Twitter annotation "meta tags," which were recently announced at the Chirp developer conference (http://bit.ly/twitterannotations2010) I would expect more game specific features to be rolled out by Twitter developers and game developers as well. Simple tagging to identify high-score posts would be easy enough, but how about also sending links to game replays or trophy shots in the tweet as well?
Finally, as many have noted, Twitter has decide to change their authentication process (http://dev.twitter.com/announcements) and move everyone towards OAuth -- well at least for the RESTful API's: http://bit.ly/twcountdown
So, what are we to do for iPhone apps? One answer has been provided by Ben Gottlieb: http://github.com/bengottlieb/Twitter-OAuth-iPhone
OAuth
In short, OAuth is a more secure way for users to authorize applications to access their Twitter accounts. It currently is possible to use a simple dialog to request a users account and password and then post that (in the clear) to twitter.com but it's not a liability that I want for my application -- why should I be in the middle of a transaction between Twitter and my user? Just authorize my app, and let me get on with it. I don't want to broker any more information that I need.
OAuth on Twitter currently works by generating a token for each authorized application. This requires that you, as an iPhone app developer need to first register you app with Twitter.
Twitter API
The first thing you'll need to do is register you iPhone application with Twitter, which is easy enough to do here: http://dev.twitter.com/apps
You'll need to set your application type to "client" and the access type to "read & write" in order to work with Ben's library; see the screenshot below:
Twitter Application Keys
Once you register with Twitter, you'll be able to get you OAuth 1.0a keys from dev.twitter.com by going to "Your Apps" the selecting "Application Details" and look for the OAuth consumer key and secret key. You'll need both to get Ben's library working for you.
Twitter-OAuth-iPhone
In order to integrate Ben's library, you'll first need to start using git which you can install from the official Google code site, here: http://code.google.com/p/git-osx-installer
And then installing Ben's library (in the same directory as your iPhone app, if you wish) with a simple git command:
git git://github.com/bengottlieb/Twitter-OAuth-iPhone.git
XCode Integration with Cocos2D
Ben's library is a collection of three open source projects and so the challenging part can be getting the library settings to work correctly, which basically means you have to hunt through the different build requirements for each of the individual projects. Fortunately, the only challenge was limited to the MGTwitterEngine requirement for libxml2 library.
libxml2 dynamic library (from MTTwitterEngine readme)
-
Set USE_LIBXML to 1, near the top of the MGTwitterEngine.m file.
-
Add libxml2.dylib in Other Frameworks. You'll find the library in:
/usr/lib/libxml2.dylib
-
Add "/usr/include/libxml2" as a Header Search Path in your Project Settings.
The settings in my Xcode build look like the following:
Cocos2D Usage Pattern
So hopefully this will lead to a successful build of the Twitter-OAuth-iPhone library, but then how should you integrate into your Cocos2D application? For our Sumo Tap application, we're actually using the Xcode "Utility Application" template for our game. We found the easiest integration to be to place the Twitter login delegates into our applicationDelegate:
Then in our Cocos2D main scene, we create a CCMenu button with a "Twitter" CCMenuItem and in our callback function we simply call the main application delegate:
This allows us to put all of our < SA_OAuthTwitterControllerDelegate > logic in our app delegate, and a simple method to log into Twitter as well:
And the only change we had to make to the standard Twitter-OAuth delegate was to add a call to stop the Cocos2D animation in the SA_OAuthTwitterControllerDelegate like this:
Finally, here's what the post will look like on your Twitter homepage:
Just won 95 matches on Sumo Tap for iPhone from @playngive http://itunes.com/apps/sumotap
--yarri
Hi, I'm posting a follow-up to the article in answer to some questions in the comments... hopefully this post has better formatting.
1)Where is mainViewController initialized?
I'm using the design pattern of attaching cocos2d to an EAGLView, the EAGLView is controlled by the MainViewController and it's view is simply loaded from a nib file (MainView.xib) which I've taken from the XCode template for a utility application. It's initialized in the applicationDidFinishLaunching:
method like this:
- (void)applicationDidFinishLaunching:(UIApplication *)application {
MainViewController *aController = [[MainViewController alloc] initWithNibName:@"MainView" bundle:nil];
self.mainViewController = aController;
[aController release];
...
2) What's the API call where you brag "Player X beat the pants off Player Y"
This is just a call to the sendUpdate:
method of the MGTwitterEngine. In my case, I have the following initialization:
// SA_OAuthTwitterEngine *_engine;
if (!_engine) {
_engine = [[SA_OAuthTwitterEngine alloc] initOAuthWithDelegate: self];
_engine.consumerKey = kOAuthConsumerKey;
_engine.consumerSecret = kOAuthConsumerSecret;
UIViewController *controller = [SA_OAuthTwitterController controllerToEnterCredentialsWithTwitterEngine: _engine delegate: self];
if (controller) {
// Something wrong happened... the twitter account should have been determined. Raise error dialog, handle error.
return;
}
else {
// Post message to users twitter account
[_engine sendUpdate:[NSString stringWithFormat:@"Player X beat the pants off Player Y"]];
}
}
--yarri