本文讲述在用SpriteKit
制作iOS游戏的时候,如何让在用户在达到某种成就后分享自己的成就或分数,并附上一张游戏截屏,然后发到社交网络上
SpriteKit截屏
传统的截屏方法是用UIView的layer来读取渲染上下文,生成图片
1 2 3 4 5
| UIGraphicsBeginImageContext(self.view.frame.size); [self.view.layer renderInContext:UIGraphicsGetCurrentContext()]; UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext();
|
viewImage就是获取的截图,如果要将图片存入相册,只需在后面调用
1
| UIImageWriteToSavedPhotosAlbum(viewImage,nil,nil,nil)
|
而这一切都是基于UIKit
的,在SpriteKit
中,上面的方法是实效的,截屏的效果就是一张白色图片
但在苹果的官方文档中,明确提到了SKTexture
的作用,最后一条是说可以将节点树渲染成纹理,可以应用于对游戏截屏。苹果还告诉了我们SKView
的一个方法:textureFromNode:
,该方法将以node包含的内容渲染成一个纹理,但是如何将SKTexture
转换为UIView
呢?我在workoverflow的一个提问中找到了答案:
方法一:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| - (UIImage*) imageWithView:(UIView *)view { UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, 0.0);
[view drawViewHierarchyInRect:view.bounds afterScreenUpdates:YES];
UIImage * img = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext();
return img; }
- (UIImage*) imageFromNode:(SKNode*)node { SKTexture* tex = [self.scene.view textureFromNode:node]; SKView* view = [[SKView alloc]initWithFrame:CGRectMake(0, 0, tex.size.width, tex.size.height)]; SKScene* scene = [SKScene sceneWithSize:tex.size]; SKSpriteNode* sprite = [SKSpriteNode spriteNodeWithTexture:tex]; sprite.position = CGPointMake( CGRectGetMidX(view.frame), CGRectGetMidY(view.frame) ); [scene addChild:sprite]; [view presentScene:scene];
return [self imageWithView:view]; }
|
- get the SKTexture for your node using the current SKView
- make another SKView that is just big enough for your texture
- add a SKSpriteNode with the texture into your new scene, placing it in the middle
- render the view into a graphics context
方法二:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| -(UIImage *)imageFromNode:(SKNode *)node { SKView *view = node.scene.view; CGFloat scale = [UIScreen mainScreen].scale; CGRect nodeFrame = [node calculateAccumulatedFrame]; UIGraphicsBeginImageContextWithOptions(view.bounds.size, YES, 0.0); [view drawViewHierarchyInRect:view.bounds afterScreenUpdates:YES]; UIImage *sceneSnapshot = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); CGFloat originY = sceneSnapshot.size.height*scale - nodeFrame.origin.y*scale - nodeFrame.size.height*scale; CGRect cropRect = CGRectMake(nodeFrame.origin.x * scale, originY, nodeFrame.size.width*scale, nodeFrame.size.height*scale); CGImageRef croppedSnapshot = CGImageCreateWithImageInRect(sceneSnapshot.CGImage, cropRect); UIImage *nodeSnapshot = [UIImage imageWithCGImage:croppedSnapshot]; CGImageRelease(croppedSnapshot); return nodeSnapshot; }
|
以上两个方法亲测好使!
使用Social.Framework分享游戏战绩
因为比较懒不想在各种第三方社交网站申请APP注册然后使用SDK等,有点复杂,所以暂时用了苹果自带的Social.Framework
首先推荐一个比较好的Demo,代码很容易读,容易上手
首先到target,Build Phases->link binary with libraries,添加social.framework,然后在要使用这个framework的文件头添加@import Social;
记得要到iphone或者simulator里设置好对应社交网络的账号,填上用户名密码登录上,不然找不到account,不能post。如果找不到新浪微博,把系统语言调到中文。如果没有预先设置好账号,social.framework在真机和simulator上表现会不同。
使用UIActivityViewController
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| sharingImage = [self imageFromNode:self]; NSArray *activityItems; if (sharingImage != nil) { activityItems = @[sharingText, sharingImage]; } else { activityItems = @[sharingText]; } UIActivityViewController *activityController = [[UIActivityViewController alloc] initWithActivityItems:activityItems applicationActivities:nil]; [(UIViewController *)[self.view nextResponder] presentViewController:activityController animated:YES completion:nil];
|
[self.view nextResponder]
的作用是获取当前SKScene
的UIViewController
如果想系统的学一下UIActivityViewController
,建立看看这篇翻译自Mattt Thompson的博文
使用SLComposeViewController
这个就相当于上面里介绍的单个分享service
目前支持的平台有以下这些:
1 2 3 4 5
| SOCIAL_EXTERN NSString *const SLServiceTypeTwitter NS_AVAILABLE(10_8, 6_0); SOCIAL_EXTERN NSString *const SLServiceTypeFacebook NS_AVAILABLE(10_8, 6_0); SOCIAL_EXTERN NSString *const SLServiceTypeSinaWeibo NS_AVAILABLE(10_8, 6_0); SOCIAL_EXTERN NSString *const SLServiceTypeTencentWeibo NS_AVAILABLE(10_9, 7_0); SOCIAL_EXTERN NSString *const SLServiceTypeLinkedIn NS_AVAILABLE(10_9, NA);
|
先声明一个SLComposeViewController *slComposerSheet;
,然后在需要添加分享逻辑的地方加入下面代码:(依然以微博为例子)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| [slComposerSheet setCompletionHandler:^(SLComposeViewControllerResult result) { NSLog(@"start completion block"); NSString *output; switch (result) { case SLComposeViewControllerResultCancelled: output = @"Action Cancelled"; break; case SLComposeViewControllerResultDone: output = @"Post Successfull"; break; default: break; } if (result != SLComposeViewControllerResultCancelled) { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Weibo Message" message:output delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil]; [alert show]; } }]; if([SLComposeViewController isAvailableForServiceType:SLServiceTypeSinaWeibo]) { slComposerSheet = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeSinaWeibo]; [slComposerSheet setInitialText:self.sharingText]; [slComposerSheet addImage:self.sharingImage]; [slComposerSheet addURL:[NSURL URLWithString:@"http://www.weibo.com/"]]; [self presentViewController:slComposerSheet animated:YES completion:nil]; }
|
这种方法我没试过,代码是照抄自前面提到的Demo里