Powered by Squarespace
Development Blog Archive
CIRCUS BLAST

Test your aiming skills! 

Circus Blast -- 3D Puzzle Shooter. You're a monkey. In a circus. Trying to help the other animals escape, with a cannon!

 

 App. is no longer available. 

SUMO TAP

Enter the dohyou to challenge yourself to a fast pace game of Sumo Tap! Play online with friends, using Bluetooth and post your high scores to Twitter.

 

 App is no longer available.

« Cocos2D on Top of SIO2 | Main | Ruby on Rails For iPhone »
Sunday
May022010

Twitter Integration with Cocos2D and Twitter-OAuth-iPhone

Twitter

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)

  1. Set USE_LIBXML to 1, near the top of the MGTwitterEngine.m file.

  2. Add libxml2.dylib in Other Frameworks. You'll find the library in:

    /usr/lib/libxml2.dylib

  3. 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/sumotapless than a minute ago via Sumo Tap


--yarri

 

References (7)

References allow you to track sources for this article, as well as articles that were written in response to this article.
  • Response
    Nice Web-site, Keep up the very good work. Thank you.
  • Response
    Response: lead generation
    play-N-give : Play, Give, Share - Blog - Twitter Integration with Cocos2D and Twitter-OAuth-iPhone
  • Response
    play-N-give : Play, Give, Share - Blog - Twitter Integration with Cocos2D and Twitter-OAuth-iPhone
  • Response
    play-N-give : Play, Give, Share - Blog - Twitter Integration with Cocos2D and Twitter-OAuth-iPhone
  • Response
    play-N-give : Play, Give, Share - Blog - Twitter Integration with Cocos2D and Twitter-OAuth-iPhone
  • Response
    Response: repair tampa
    play-N-give : Play, Give, Share - Blog - Twitter Integration with Cocos2D and Twitter-OAuth-iPhone
  • Response
    play-N-give : Play, Give, Share - Blog - Twitter Integration with Cocos2D and Twitter-OAuth-iPhone

Reader Comments (14)

Hi,

Can you let me know what View Controller you used here and how you set it up? By default in Cocos2D you do not need it, so I wondered how you set it up and what effect it had on the rest of the application?

Thanks

Nalin

June 8, 2010 | Unregistered CommenterNalin Sharma

One other thing I forgot to ask was do you have the code for -(void) updateGlobalLeaderboard:(int)matches; because this seems to be missing?

Basically it would help to know what code you use to actually update the status :)

thanks

Nalin

June 8, 2010 | Unregistered CommenterNalin Sharma

Hi, maybe it's best to ask this question on the Cocos2d forums but basically we have a simple main window which is a standard EAGLView and there's a simple CCMenu in the main scene we calls the Twitter registration.

We use an NSNotification to poll for a call from within Cocos2d. And the application itself is the OAuth delegate as you can see from the first code listing above.

As far as updating the status, this is application specific. We have this embedded in our game logic after a winner is determined, we create an NSString with a simple brag message: "Player X beat the pants off Player Y and earned 10 points on their way to a Maigashira ranking on Sumo Tap for iPhone!"

--yarri

June 14, 2010 | Registered Commenterplayngive

Thanks very much for responding Yarri

I would post on the Cocos Forum, but I have searched and you are the expert here :)

I hope you don't mind me asking, but I am just looking for a few lines of code:

1) Where is this initialised and how?
MainViewController *mainViewController;

2) What's the API call where you brag "Player X beat the pants off Player Y"
(I have never used MG Twitter)

Sorry if this is obvious to you. Hope you can help.

br

Nalin

June 15, 2010 | Unregistered CommenterNalin Sharma

Hi,

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

June 15, 2010 | Registered Commenterplayngive

Thanks for this Yarri.

I managed to get it working to a degree, but I am trying to figure out how to avoid the user logging in each time. I notice you save off the Username once authentication has been established, but I do not know how you use this to login subsequently without the ViewController coming up.

Cheers

Nalin

June 19, 2010 | Unregistered CommenterNalin Sharma

Hi. I have followed your tutorial and got to a point where, when i tap the "Twitter" button, I see the Login UI for a fraction of a second than it disappears.
I implemented this code in a project created from the "cocos2d" template.

Any ideas why this happens?

November 5, 2010 | Unregistered Commentercriistii

In the twitterAccountLogin method, you have the following code...

controller = [SA_OAuthTwitterController controllerToEnterCredentialsWithTwitterEngine: _engine delegate: self];

A little further down, you then have

[controller release];

Isn't this releasing an autoreleased object and will therefore cause problems?

Thanks.

March 30, 2011 | Unregistered CommenterNB

Hi,

I trying to implement this on a project created in unity and exported to iOS.
soo far good whit some errors.
i have implemented the FBConnect in that project too, works good.

but the Twitter dont, just cicles on this line


UIViewController *controller = [SA_OAuthTwitterController controllerToEnterCredentialsWithTwitterEngine:_engine delegate:self];

I notice some times works, but figured out only works after being launched the FBConnect first, i doesnt make sence in the example works perfect, any help will be apreciated.
here is the .h file


#import <UIKit/UIKit.h>

#import "SA_OAuthTwitterController.h"
@class SA_OAuthTwitterEngine;

@interface AppController : NSObject<UIAccelerometerDelegate, UIApplicationDelegate, SA_OAuthTwitterControllerDelegate>
{
UIWindow* _window;

SA_OAuthTwitterEngine *_engine;
}
- (void) startUnity:(UIApplication*)application;
- (void) startRendering:(UIApplication*)application;

@end

and the .mm file

#import "SA_OAuthTwitterEngine.h"
#define kOAuthConsumerKey @"5uXUkRWIYNBMLCi9Qe7FpQ" //REPLACE With Twitter App OAuth Key
#define kOAuthConsumerSecret @"YVUCnOr8aB3XLT7lGoEGcyw5q00IDQ8CBvFV01GtC0" //REPLACE With Twitter App OAuth Secret


#pragma mark Twitter implementation
- (void) twetMesage {

if(!_engine){
_engine = [[SA_OAuthTwitterEngine alloc] initOAuthWithDelegate:self];
_engine.consumerKey = kOAuthConsumerKey;
_engine.consumerSecret = kOAuthConsumerSecret;
}

UIViewController *controller = [SA_OAuthTwitterController controllerToEnterCredentialsWithTwitterEngine:_engine delegate:self];

if (controller){
[self presentModalViewController: controller animated: YES];
}

}
//=======================================================================================
#pragma mark SA_OAuthTwitterEngineDelegate
- (void) storeCachedTwitterOAuthData: (NSString *) data forUsername: (NSString *) username {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

[defaults setObject: data forKey: @"authData"];
[defaults synchronize];
}

- (NSString *) cachedTwitterOAuthDataForUsername: (NSString *) username {
return [[NSUserDefaults standardUserDefaults] objectForKey: @"authData"];
}

//===============================================================================
#pragma mark TwitterEngineDelegate
- (void) requestSucceeded: (NSString *) requestIdentifier {
NSLog(@"Request %@ succeeded", requestIdentifier);
}

- (void) requestFailed: (NSString *) requestIdentifier withError: (NSError *) error {
NSLog(@"Request %@ failed with error: %@", requestIdentifier, error);
}

April 4, 2011 | Unregistered CommenterFco Garcia

Hi, can you pass the completed code, because the function -(void) updateGlobalLeaderboard:(int)matches; i don't know how to do.

all i got, went post some phrase and post on twitter...

and i don`t know how to put "via "thegame" "

help please... thanks

May 19, 2011 | Unregistered CommenterFabio

Do you have some function to go BACK to MenuScene?
thanks

May 23, 2011 | Unregistered CommenterJohn

Owesome man !!! you did a great tutorial, thanks

September 12, 2011 | Unregistered CommenterEduardo

Hello,

I am using Xcode 4 and xmlparser version libxml2.2.dylib. I have added the Header search Path as all you described here and also added the dynamic parser. But still I am having the same problem.

The error says:


ld: warning: ignoring file /Users/afanurrashid/Desktop/TwitterTest/libxml2.2.dylib, missing required architecture i386 in file
Undefined symbols for architecture i386:
"_xmlReaderForMemory", referenced from:
-[MGTwitterLibXMLParser initWithXML:delegate:connectionIdentifier:requestType:responseType:URL:] in MGTwitterLibXMLParser.o
"_xmlTextReaderIsEmptyElement", referenced from:
-[MGTwitterLibXMLParser _nodeValue] in MGTwitterLibXMLParser.o
-[MGTwitterLibXMLParser _statusDictionaryForNodeWithName:] in MGTwitterLibXMLParser.o
-[MGTwitterLibXMLParser _userDictionaryForNodeWithName:] in MGTwitterLibXMLParser.o
-[MGTwitterLibXMLParser _hashDictionaryForNodeWithName:] in MGTwitterLibXMLParser.o
-[MGTwitterMessagesLibXMLParser _directMessageDictionaryForNodeWithName:] in MGTwitterMessagesLibXMLParser.o
................................
.....................

"_xmlFree", referenced from:
-[MGTwitterLibXMLParser initWithXML:delegate:connectionIdentifier:requestType:responseType:URL:] in MGTwitterLibXMLParser.o
-[MGTwitterLibXMLParser _nodeValueAsString] in MGTwitterLibXMLParser.o
-[MGTwitterLibXMLParser _nodeValueAsDate] in MGTwitterLibXMLParser.o
-[MGTwitterLibXMLParser _nodeValueAsInt] in MGTwitterLibXMLParser.o
-[MGTwitterLibXMLParser _nodeValueAsBool] in MGTwitterLibXMLParser.o
ld: symbol(s) not found for architecture i386
collect2: ld returned 1 exit status

Can anyone help me in this regard. I am having great problem with this error.

Thanks in advance.

September 23, 2011 | Unregistered CommenterSajeeb

I have done everything what you have described but it seems that i may be doing some mistake. for this reason it says i am authenticated but my tweet is not posted in my wall.

Here is my appsDelegate.h


#import <UIKit/UIKit.h>
#import "SA_OAuthTwitterController.h"

@class SA_OAuthTwitterEngine;
@class RootViewController;

@interface AppDelegate : NSObject <UIApplicationDelegate, SA_OAuthTwitterControllerDelegate> {
UIWindow *window;
RootViewController *viewController;
SA_OAuthTwitterEngine *_engine;
}

@property (nonatomic, retain) UIWindow *window;
-(void)twitterAccountLogin;

@end


My appsDelegate.m file:


#import "cocos2d.h"

#import "AppDelegate.h"
#import "GameConfig.h"
#import "HelloWorldLayer.h"
#import "RootViewController.h"
#import "SA_OAuthTwitterEngine.h"
#import "SA_OAuthTwitterController.h"

#define kOAuthConsumerKey @"e7MGLzDySl8LPqKrunFt6Q"
#define kOAuthConsumerSecret @"Rg2r0Zntzho4B4Mvv6DKKBEK7TBwFjmlgX8Zz2DlocQ"
.......
.......


-(void)twitterAccountLogin {

if (_engine) {
return;
}
_engine = [[SA_OAuthTwitterEngine alloc] initOAuthWithDelegate: self];
_engine.consumerKey = kOAuthConsumerKey;
_engine.consumerSecret = kOAuthConsumerSecret;

UIViewController *controller = [SA_OAuthTwitterController controllerToEnterCredentialsWithTwitterEngine: _engine delegate: self];

if (controller)
{
NSLog(@"Unable to post tweet");
[viewController presentModalViewController: controller animated: YES];
}
else {
NSLog(@"I am in the Send Update Method");
[_engine sendUpdate: [NSString stringWithFormat: @"Player X beat the pants off Player Y"]];
}
}



From the NSLog It shows that i am in the if(controller) section which shouldn't be.

Where is my Problem. If anyone wants I can send him the complete code....

Please help me....

October 1, 2011 | Unregistered CommenterSajeeb Saha

PostPost a New Comment

Enter your information below to add a new comment.

My response is on my own website »
Author Email (optional):
Author URL (optional):
Post:
 
Some HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>