偶然发现SpriteKit
中的SKNode
也有userInteractionEnabled
属性,就像UIKit
中的userInteractionEnabled
一样,于是我对以前的代码进行重构,发现了在游戏中添加交互button的新的方式(估计很多大神们早就发现了)
在SKScene中添加SKNode对象作为Button
不得不承认,我以前在SKScene
中添加一个Button
的过程是这样的:
添加一个SKNode
(一般都是它的子类:SKLabelNode
和SKSpriteNode
)属性
1 | SKLabelNode *button = [SKLabelNode labelNodeWithFontNamed:@"Chalkduster"]; |
设置其填充的内容和放置位置,还有SKNode
的name
1 | button.text = @"Click me"; |
在SKScene
重写touchesEnded: withEvent:
方法,并在方法中判断触摸到哪个SKNode
1 | -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{ |
如果某个场景中需要设置很多Button,比如游戏设置界面,那么在touchesEnded: withEvent:
方法中就会出现好多if判断,这么多分支,每个分支可能还有很多操作,这样增加了SKScene的体积,使得代码可读性变差,维护也困难
通过继承来封装自己的Button
UIKit
中的userInteractionEnabled
大家一定都很熟悉,它默认值是YES
,也就是默认接受触摸事件,偶然发现SKNode
也有userInteractionEnabled
属性,但是默认值是NO
,而且SKNode
是继承UIResponder
的,这么说,我们可以在SKNode中一展拳脚了,不必再麻烦SKScene了
下面添加一个用于跳转到主菜单场景页面的Button为例:
新建一个类,名字叫MainSceneButton,继承SKLabelNode
,并构造出时候方法
1 | -(id)init{ |
这里碰到一个问题:如果用上面的代码初始化,将会出现 EXC_BAD_ACCESS
错误,问题的解决方法是在超类初始化时用init方法代替,然后再设置字体:
1 | -(id)init{ |
至于原因,我也没弄清楚,估计是SKLabelNode
的bug吧,因为初始化SKSpriteNode
时用initWithTexture: color: size:
方法就不会报错
在MainSceneButton中重写touchesEnded: withEvent:
方法
1 | -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{ |
MainScene是我的一个SKScene,通过点击MainSceneButton来切换到MainScene
最后在某个场景中将button添加上去,跟之前的类似
1 | MainSceneButton *mainScene = [[MainSceneButton alloc] init]; |
感觉这样做是不是很像以前继承一个UIView然后封装自己的Custom View呢?给SKScene瘦身的方法还有很多,参照给UIViewController瘦身的方法,我们还可以把其他SKNode也从SKScene中剥离出去,一些用于设置SKNode的方法也会随之剥离到自定义的类中,便于以后维护代码