文章目录
  1. 1. 在SKScene中添加SKNode对象作为Button
  2. 2. 通过继承来封装自己的Button

偶然发现SpriteKit中的SKNode也有userInteractionEnabled属性,就像UIKit中的userInteractionEnabled一样,于是我对以前的代码进行重构,发现了在游戏中添加交互button的新的方式(估计很多大神们早就发现了)

在SKScene中添加SKNode对象作为Button

不得不承认,我以前在SKScene中添加一个Button的过程是这样的:

添加一个SKNode(一般都是它的子类:SKLabelNodeSKSpriteNode)属性

1
SKLabelNode *button = [SKLabelNode labelNodeWithFontNamed:@"Chalkduster"];

设置其填充的内容和放置位置,还有SKNodename

1
2
3
4
5
6
button.text = @"Click me";
button.name = @"button";
button.fontSize = 40;
button.fontColor = [SKColor purpleColor];
button.position = CGPointMake(self.size.width/2, self.size.height/2);
[self addChild:button];

SKScene重写touchesEnded: withEvent:方法,并在方法中判断触摸到哪个SKNode

1
2
3
4
5
6
7
8
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch * touch = [touches anyObject];
CGPoint location = [touch locationInNode:self];
SKSpriteNode *touchedNode = (SKSpriteNode *)[self nodeAtPoint:location];
if ([touchedNode.name isEqualToString:@"button"]) {
//TODO:
}
}

如果某个场景中需要设置很多Button,比如游戏设置界面,那么在touchesEnded: withEvent:方法中就会出现好多if判断,这么多分支,每个分支可能还有很多操作,这样增加了SKScene的体积,使得代码可读性变差,维护也困难

通过继承来封装自己的Button

UIKit中的userInteractionEnabled大家一定都很熟悉,它默认值是YES,也就是默认接受触摸事件,偶然发现SKNode也有userInteractionEnabled属性,但是默认值是NO,而且SKNode是继承UIResponder的,这么说,我们可以在SKNode中一展拳脚了,不必再麻烦SKScene了
下面添加一个用于跳转到主菜单场景页面的Button为例:
新建一个类,名字叫MainSceneButton,继承SKLabelNode,并构造出时候方法

1
2
3
4
5
6
7
8
-(id)init{
if (self = [super initWithFontNamed:@"Chalkduster"]) {
self.text = @"MENU";
self.fontSize = 20;
self.userInteractionEnabled = YES;
}
return self;
}

这里碰到一个问题:如果用上面的代码初始化,将会出现 EXC_BAD_ACCESS 错误,问题的解决方法是在超类初始化时用init方法代替,然后再设置字体:

1
2
3
4
5
6
7
8
9
-(id)init{
if (self = [super init]) {
self.fontName = @"Chalkduster";
self.text = @"MENU";
self.fontSize = 20;
self.userInteractionEnabled = YES;
}
return self;
}

至于原因,我也没弄清楚,估计是SKLabelNode的bug吧,因为初始化SKSpriteNode时用initWithTexture: color: size:方法就不会报错
在MainSceneButton中重写touchesEnded: withEvent:方法

1
2
3
4
5
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
SKTransition *reveal = [SKTransition flipHorizontalWithDuration:0.5];
SKScene * myScene = [[MainScene alloc] initWithSize:self.scene.size];
[self.scene.view presentScene:myScene transition: reveal];
}

MainScene是我的一个SKScene,通过点击MainSceneButton来切换到MainScene
最后在某个场景中将button添加上去,跟之前的类似

1
2
3
MainSceneButton *mainScene = [[MainSceneButton alloc] init];
mainScene.position = CGPointMake(self.size.width/2, self.size.height/2);
[self addChild:mainScene];

感觉这样做是不是很像以前继承一个UIView然后封装自己的Custom View呢?给SKScene瘦身的方法还有很多,参照给UIViewController瘦身的方法,我们还可以把其他SKNode也从SKScene中剥离出去,一些用于设置SKNode的方法也会随之剥离到自定义的类中,便于以后维护代码

文章目录
  1. 1. 在SKScene中添加SKNode对象作为Button
  2. 2. 通过继承来封装自己的Button