SpriteKitとボタンの実装
検索するといくつか出てくるんだけど、
個人的にはこんな感じでイイかなぁーって思ってる。
そもそも、どんな用途を想定するのか?
- タイトル画面からゲーム画面への遷移
- 次のステージ(ゲーム画面)への遷移
- チェックボックスの実装
自分の場合は、これらを想定している。
3つ目のチェックボックスだけど、要はトグルできるボタンのこと。
BGMのOn/Offとか、SE(効果音)のOn/Offに使いたい。
どうやって実装するか?
現時点では、こんな感じ。
1.) SKLabelNodeを継承する
// MyButton.h #import <SpriteKit/SpriteKit.h> @interface MyButton : SKLabelNode @property (nonatomic, assign) SKAction *touchAction; @end // MyButton.m #import "MyButton.h" @implementation MyButton -(instancetype)initWithFontNamed:(NSString *)fontName { if ( self = [super initWithFontNamed:fontName] ) { _touchAction = nil; // touchesBegan/touchesEndedで発火させるアクション self.userInteractionEnabled = YES; } return self; } -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { /* タッチに反応させたければここ */ } -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { /* ボタンっぽく振る舞いたい場合は、指を離した位置をチェックする */ UITouch *touch = [touches anyObject]; CGPoint location = [touch locationInNode:self]; CGPoint locationInParent = [self convertPoint:location toNode:self.parent]; if ( CGRectContainsPoint(rect, locationInParent) ) { NSLog( @"Touch: x, y = %.1f, %.1f, Clicked!!!", location.x, location.y ); } else { NSLog( @"Touch: x, y = %.1f, %.1f", location.x, location.y ); } } @end
ポイントは、userInteractionEnabled
にYES
を代入するところ。
これをしないと、touchesBegan
が呼ばれないと同時に、
親NodeのtouchesBegan
が呼ばれてしまう。
これは、こちらを参考にさせて頂きました。
タップされたらSKActionを実行するSKLabelNodeを作ってみた – TATYUSA’S NOTE
2.) SKSceneのtouchesBeganで処理する
そもそも、タイトル画面からゲーム画面に遷移するだけだったら、
どの位置がタップされても良いので、
それなら、touchesBegan
で処理しても構わない気がする。
ただし、やはりラベルの領域でのみ反応したいとか、
タイトル画面にBGMのOn/Offを付けたいとかあると思う。
その場合は、1.)で紹介したCGRectContainsPoint
を使って判断すれば良いと思う。
おまけ
あと、個人的にラベルの範囲だけじゃなくて、
タッチに反応する領域を、もう少し増やしたいと思ってるんだけど、
これはどうやって実装したらいいだろう?
2.)の方法であれば、CGRectContainsPoint
を行う前に、
引数の領域(CGRect
)を膨らませることが考えられる。
もう一つは、SKLabelNode
をSKSpriteNode
に追加してとかかなー。
チェックボックスについては、そのうちということで。
おしまい。
素直にやるとnodeのframeプロパティにサイズを大きくしたCGRectをつっこめばいいじゃないですかねー
node.frame = CGRectInset(frame, -2, -2);
くらいの感じで。
OSX/Cocoaのラベルだとそんなんですね
あ、そっか。SKLabelNodeのframeプロパティを広げて、
それを使って、spriteNodeWithColorして、addChildすればいんですね。
あと、領域を変更する関数を探す手間が省けました、ありがとうございます!
OSXのAppKitだとhitTestをオーバーライドして
frame内のマウス当たり判定は好きにできるんですけど
その辺はどうなんでしょうねえ(あんまりまじめにSpriteKitの説明書読んでなし)
SKLabelNodeに関していうと、hitTestは無さそうですね。
textプロパティ変更でframeプロパティが更新されるので、
その辺を使うような気がします。
ラベルのみをボタンとして使う場合は、判定領域を少し膨らませたい訳ですが、
それならボタンの画像を用意すべきでは?って言われると、その通りでもあります。。。