Введение
Если вам интересно как объеденить cocos2d вместе с социальными сетями (в данной статье будут рассмотрены twitter и facebook), то прошу под кат.
Что нужно сделать
Для начала сформулируем задачу. Есть исходное меню с несколькими вариантами:
- Start game
- Settings
- Social features
При выборе последнего пункта должно появляться другое меню на новом слое, на котором должны быть отображены следующие опции:
- Post screenshot to twitter
- Post screenshot to facebook
- Back to main menu
Видно, что если пользователь выберет Post screenshot to twitter, то программа должна сделать скриншот главного слоя (под главным слоем понимается слой, где отрисовывается ваш игровой процесс) и отправить его в twitter вместе с некоторым сообщением. Аналогичный функционал привязан к кнопке Post screenshot to facebook.
Share kit настройка и модфикация
Для интеграции своего проекта с twitter и facebook я выбрал SDK ShareKit. После установки ShareKit, нужно исправить некоторые баги в исходном коде данного SDK. Данные баги связаны c изменениями в twitter-api. И так, что нужно сделать. Открываем
SHKTwitter.m
ищем строчки с номерами 54-56 и заменяем их на следующий код:
self.authorizeURL = [NSURL URLWithString:@"https://api.twitter.com/oauth/authorize"];
self.requestURL = [NSURL URLWithString:@"https://api.twitter.com/oauth/request_token"];
self.accessURL = [NSURL URLWithString:@"https://api.twitter.com/oauth/access_token"];
Далее, заменяем строчку с номером 323 на следующую:
OAMutableURLRequest *oRequest = [[OAMutableURLRequest alloc] initWithURL:[NSURL URLWithString:@"https://api.twitter.com/1/statuses/update.json"]
consumer:consumer
token:accessToken
realm:nil
signatureProvider:nil];`
После небольших модификаций, открываем
SHKConfig.h
и заполняем для facebook и twitter соответствующие поля. Стоит отметить, что если у вас нет сайта, то можно использовать сайт-заглушку для заполнения поля
SHKTwitterCallbackUrl
(например mysite.wtf/lol)
Создаем меню
Добавляем в проект три класса, которые наследуются от CCLayer. Называем их HelloWorldLayer, IntroLayer, OptionsLayer. Пусть в IntroLayer будет базовое меню, а в OptionsLayer — меню, через которое пользователь может размещать сриншоты через facebook или twitter, а в MainGameScene — будет отображаться этикетка.
Код для header и implementation MainGameSceneLayer:
-
MainGameSceneLayer.h
#import <GameKit/GameKit.h> // When you import this file, you import all the cocos2d classes #import "cocos2d.h" // HelloWorldLayer @interface HelloWorldLayer : CCLayer { } // returns a CCScene that contains the HelloWorldLayer as the only child +(CCScene *) scene; @end
-
MainGameSceneLayer.m
// Import the interfaces #import "HelloWorldLayer.h" // Needed to obtain the Navigation Controller #import "AppDelegate.h" #pragma mark - HelloWorldLayer // HelloWorldLayer implementation @implementation HelloWorldLayer // Helper class method that creates a Scene with the HelloWorldLayer as the only child. +(CCScene *) scene { // 'scene' is an autorelease object. CCScene *scene = [CCScene node]; // 'layer' is an autorelease object. HelloWorldLayer *layer = [HelloWorldLayer node]; // add layer as a child to scene [scene addChild: layer]; // return the scene return scene; } // on "init" you need to initialize your instance -(id) init { // always call "super" init // Apple recommends to re-assign "self" with the "super's" return value if( (self=[super init]) ) { // create and initialize a Label CCLabelTTF *label = [CCLabelTTF labelWithString:@"Hello World" fontName:@"Marker Felt" fontSize:64]; // ask director for the window size CGSize size = [[CCDirector sharedDirector] winSize]; // position the label on the center of the screen label.position = ccp( size.width /2 , size.height/2 ); // add the label as a child to this Layer [self addChild: label]; } return self; } // on "dealloc" you need to release all your retained objects - (void) dealloc { // in case you have something to dealloc, do it in this method // in this particular example nothing needs to be released. // cocos2d will automatically release all the children (Label) // don't forget to call "super dealloc" [super dealloc]; } @end
Код для header и implementation IntroLayer с комментариями внутри:
-
IntroLayer.h
#import "cocos2d.h" //Конструктор класса @interface IntroLayer : CCLayer { } +(CCScene *) scene; @end
-
IntroLayer.m
// Нужно импортировать все заголовочные файлы слоев, между которыми будет переключение. В данном случае, нужно импортировать только IntroLayer.h, HelloWorldLayer.h, OptionsLayer.h #import "IntroLayer.h" #import "HelloWorldLayer.h" #import "OptionsLayer.h" #pragma mark - IntroLayer @implementation IntroLayer +(CCScene *) scene { CCScene *scene = [CCScene node]; IntroLayer *layer = [IntroLayer node]; [scene addChild: layer]; return scene; } //Как только появится слой IntroLayer, сразу отображаем исходное меню -(void) onEnter { [super onEnter]; [self addMenuToTheIntroLayer]; } //Тело метода, в котором создаем и добавляем на слой Introlayer исходное меню -(void)addMenuToTheIntroLayer { //Создаем пункты меню. В конце статьи будет дана ссылка на урок, где вместо текста используются //Пункт первый - Start game //Тип шрифта [CCMenuItemFont setFontName:@"Marker Felt"]; //Размер шрифта [CCMenuItemFont setFontSize:25]; //Указатель на пункт меню со ссылкой на обработчик нажатия. CCMenuItemFont* start_game=[CCMenuItemFont itemWithString:@"Start game" target:self selector:@selector(switchToTheGameScene:)]; //Конец создания пункта - Start game [CCMenuItemFont setFontName:@"Marker Felt"]; [CCMenuItemFont setFontSize:25]; CCMenuItemFont* switch_to_socials=[CCMenuItemFont itemWithString:@"Social features" target:self selector:@selector(switchToSocialFeatures:)]; CCMenu *menu=[CCMenu menuWithItems:start_game, switch_to_socials, nil]; [menu alignItemsVertically]; [self addChild:menu]; } //Обработчики нажатий на меню -(void) switchToTheGameScene:(id)sender { //Прыгаем на другой слой HelloWorldLayer [[CCDirector sharedDirector] replaceScene:[HelloWorldLayer scene]]; } -(void)switchToSocialFeatures:(id)sender { [[CCDirector sharedDirector] replaceScene:[OptionsLayer scene]]; } @end
Код для header и implementation OptionsLayer с комментариями внутри:
-
OptionsLayer.h
#import "cocos2d.h" //подключаем библиотеки для отправки твито и постов на стенку facebook #import "SHK.h" #import "SHKTwitter.h" #import "SHKFacebook.h" @interface OptionsLayer : CCNode { } +(CCScene *) scene; @end
-
OptionsLayer.m
#import "OptionsLayer.h" #import "HelloWorldLayer.h" //Переходите сразу к обработчикам событий так как там будет описан функционал отправки твитов и сообщений к себе на стенку facebook @implementation OptionsLayer +(CCScene *) scene { CCScene *scene = [CCScene node]; OptionsLayer *layer = [OptionsLayer node]; [scene addChild: layer]; return scene; } -(void) onEnter { [super onEnter]; [self addMenuToTheIntroLayer]; } -(void)addMenuToTheIntroLayer { [CCMenuItemFont setFontName:@"Marker Felt"]; [CCMenuItemFont setFontSize:25]; CCMenuItemFont* start_game=[CCMenuItemFont itemWithString:@"Post to twitter" target:self selector:@selector(postToTwitter:)]; [CCMenuItemFont setFontName:@"Marker Felt"]; [CCMenuItemFont setFontSize:25]; CCMenuItemFont* switch_to_socials=[CCMenuItemFont itemWithString:@"Post to facebook" target:self selector:@selector(postToFacebook:)]; [CCMenuItemFont setFontName:@"Marker Felt"]; [CCMenuItemFont setFontSize:25]; CCMenuItemFont* back_to_game=[CCMenuItemFont itemWithString:@"Back to game" target:self selector:@selector(backToGame:)]; CCMenu *menu=[CCMenu menuWithItems:start_game, switch_to_socials,back_to_game, nil]; [menu alignItemsVertically]; [self addChild:menu]; } -(void) postToFacebook:(id)sender { SHKItem *facebookItem = [SHKItem image:imgToPost title:@"Check out my highscore! #RobotWarsProject"]; [SHKFacebook shareItem:facebookItem]; } -(void)postToTwitter:(id)sender { //метод для создания скриншотов [self takeScreenShot]; //создаем сущность для отправки через twitter //в данном случае это будет картинка с комментарием и хэш-тегом SHKItem *twitterItem = [SHKItem image:imgToPost title:@"Check out my highscore! #RobotWarsProject"]; [SHKTwitter shareItem:twitterItem]; } -(void)backToGame:(id)sender { //если пользователь хочет вернуться обратно и продолжить игру [[CCDirector sharedDirector] replaceScene:[HelloWorldLayer scene]]; } @end
Делаем скриншоты
Сразу скажу, что если вы используете cocos2d 0.99, то создание скриншотов выглядит достаточно просто:
UIImage *image = [[CCDirector sharedDirector] screenshotUIImage]
Для тех, кто использует более новую версию этого замечательного графического фреймворка, нужно создавать отдельны метод создания скриншотов. Для этого модифицируем код OptionsLayer следующим образом:
-
OptionsLyer.h
#import "cocos2d.h" #import "SHK.h" #import "SHKTwitter.h" #import "SHKFacebook.h" @interface OptionsLayer : CCLayer { //в этой переменной будем хранить сриншот UIImage *imgToPost; } //метод, который создает скриншот //первый параметр - название слоя, с которого будем создаваться скриншот -(CCRenderTexture*) screenshotWithStartNode:(CCNode*)startNode filename:(NSString*)filename; @end
-
OptionsLyer.m
//Добавляем описание метода - (void) takeScreenShot { //Называем файл, который будет сохраняться в фото-библиотеку NSString* file = @"//imageforphotolib.png"; //Путь к фотографиям. По-моему, это единственное место куда Apple разрашает что-то сохранять без создания песочницы NSArray* paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES); NSString* documentsDirectory = [paths objectAtIndex:0]; NSString* screenshotPath = [documentsDirectory stringByAppendingPathComponent:file]; // [CCDirector sharedDirector].nextDeltaTimeZero = YES; //Поулчаем разамер экрана CGSize winSize = [CCDirector sharedDirector].winSize; //Включаем рендер и передаем ему размеры окна CCRenderTexture* rtx = [CCRenderTexture renderTextureWithWidth:winSize.width height:winSize.height]; //Начинаем отрисовку [rtx begin];// открываем текстуру [[MainGameLayer node] visit];//получаем ссылку на игровой слой [rtx end];//закрываем текстуру // Сохраяем картинку в документы как *.PNG файл. [rtx saveToFile:@"imageforphotolib.png" format:kCCImageFormatPNG]; //Конвертируем скриншот из нулей и единичек в UIImage NSData *data = [NSData dataWithContentsOfFile:screenshotPath]; //create an image from the raw data UIImage *img = [UIImage imageWithData:data]; //Сохраняем в Photo Library и передаем полученную картинку свойству imgToPost imgToPost=img; UIImageWriteToSavedPhotosAlbum(img, nil, nil, nil); }
На этом статья закончена. Если у вас будут вопросы и/или комментарии, то пишите, с удовольствием на них отреагирую.
Список статей на английском языке
- Детальная статья о том, как использовать CCRenderTexture (масса полезной информации);
- ShareKitDocs;
- ссылка на исходник, дропбокс.
ПЫСЫ попробуйте интегрировать этот проект с моим старым проектом
Автор: getbraine