Cocos2Dでのボタン作成: シンプル、ラジオ、トグルボタン

Ray Wenderlich

このチュートリアルは次の言語で閲覧可能です: 簡体中国語, 英語

Buttons Tutorial Screenshot

Buttons Tutorial Screenshot

Cocos2Dでのゲーム開発に於いてとりあえず無くてはならない物、それはボタンですね。このチュートリアルではCocos2Dでのボタンの作り方を分かりやすく解説していきます。始めは、初歩的なボタンから始まって、トグル、ラジオ・ボタンも勉強しちゃいましょう。このチュートリアルでは先にCocos2Dでシンプルなゲームの作成チュートリアルをご覧になる事をお勧めします。

私が初めてCocos2Dを使ってボタンを作成し始めた時、Spriteでボタンを作成してボタンがタップされたかどうかを判定する方法が一番良い方法だと思ってました。もちろん、これも有りでしょう。しかし、Cocos2Dにはもっと、簡単な方法があるんです。それはCocos2D”menu”システムです。

Cocos2Dメニュー·システムは、その中にたくさんのメニュー項目を有する”menu”で構成されています。”menu item”は”イメージ”でも”テキスト”でも構いません。”menu”では”menu”アイテムをアレンジする事も出来ます。例えば、”menu”がタップされた時にアイテムをハイライトしたり、アイテムの切り替え(Toggle)、その他色々あります。それでは、Cocos2Dを使っての作成を始めましょう!

シンプルなボタンの作成

それではXcodeを開いて、新規プロジェクトを作成しましょう、Coco2Dのテンプレートを選択して、プロジェクト名を”CCButtons”にして下さい。次にこのチュートリアルの為に適当なイメージが必要ですね。自身で適用なイメージを作成して用意しても良いですし、作成したボタンのイメージからダウンロードしても構いません。とにかくイメージが用意出来たら、プロジェクトの”resources”フォルダにドラッグして、”Copy items into destination group’s folder (if needed)”にチェックを入れます。

次に”HelloWorldScene.h”を開いて、”HelloWorld”クラスに以下のメンバ変数を加えます:

CCLabelTTF *_label;

おっと、忘れないように”HelloWorldScene.m”を開いて、deallocメソッドに”お掃除コード”を追加しておきます:

[_label release];
_label = nil;

次に、同じく”HelloWorldScene.m”のinitメソッドの中を 以下と置き換えて下さい:

-(id) init
{
  if( (self=[super init] )) {
 
    CGSize winSize = [[CCDirector sharedDirector] winSize];
 
    // Create a label for display purposes
    _label = [[CCLabelTTF labelWithString:@"Last button: None" 
      dimensions:CGSizeMake(320, 50) alignment:UITextAlignmentCenter 
      fontName:@"Arial" fontSize:32.0] retain];
    _label.position = ccp(winSize.width/2, 
      winSize.height-(_label.contentSize.height/2));
    [self addChild:_label];
 
    // Standard method to create a button
    CCMenuItem *starMenuItem = [CCMenuItemImage 
      itemFromNormalImage:@"ButtonStar.png" selectedImage:@"ButtonStarSel.png" 
      target:self selector:@selector(starButtonTapped:)];
    starMenuItem.position = ccp(60, 60);
    CCMenu *starMenu = [CCMenu menuWithItems:starMenuItem, nil];
    starMenu.position = CGPointZero;
    [self addChild:starMenu];
 
  }
  return self;
}

始めにデバッグ目的の為にラベルを作成します。ここは前のチュートリアルで勉強しましたから、分かりますね。しかし、今回はラベルのディメンションとアライメントを設定する新しいコンストラクタを使っている事に注意して下さい。この方法を使って、ラベルのサイズをスクリーンの幅と同じにして、テキストをスクリーンの真ん中に配置します。この方法は、特にテキストを左や右に寄せて揃えたい時に使える簡単な方法です。

次はボタンを作成する配置です。まず始めに”menu”アイテムを”CCMenuItemImage”を使って作成して、ボタンがタップされた時に呼び出されるコールバック関数を設定します。最後ステップは、ボタンを格納する為のmenuを作成します。

ここで“CGPointZero”でmenuを作成している事に注目して下さい。これはmenuの中心が何処にあるかを指定しています。しかし”menu”アイテムの中心を(60,60)に設定しているため、スクリーン上はこのボタンの中心は(60,60)になります。

後少しコードを追加しましょう。initメソッドの下にボタンがタップされた時に呼び出される、コールバック関数を追加しましょう:

- (void)starButtonTapped:(id)sender {
    [_label setString:@"Last button: *"];
}

それでは、コンパイルしてランして下さい。何も問題が無ければ、スクリーンには以下の様に表示されるはずです:

Simple Button Screenshot

切り替え(Toggle)ボタン

iPhoneゲーム開発に於いて、他によく見るタイプのボタンと言えば、切り替え(Toggle)ボタンでしょう。始めは1つのイメージがあって、ボタンがされると他のイメージに切り替わるタイプのボタンです。このタイプのボタンはiPhone上の限られたスクリーンのスペースを最大限に活用する為に、コントロールパネル等を切り替える用途によく使われます。

幸運にも、Cocos2Dにはこの機能を簡単に設定出来る”CCMenuItemToggle”という特別なクラスがあります。それではこれを試してみましょう。始めに、”HelloWorldScene.h”に以下の新しいメンバー関数を2つ追加します:

CCMenuItem *_plusItem; 
CCMenuItem *_minusItem;

それから、お掃除コードをdeallocメソッドへ追加:

[_plusItem release];
_plusItem = nil;
[_minusItem release];
_minusItem = nil;

次に以下のコードをinitメソッドの中の[self addChild:starMenu]の下に追加します:

_plusItem = [[CCMenuItemImage itemFromNormalImage:@"ButtonPlus.png" 
  selectedImage:@"ButtonPlusSel.png" target:nil selector:nil] retain];
_minusItem = [[CCMenuItemImage itemFromNormalImage:@"ButtonMinus.png" 
  selectedImage:@"ButtonMinusSel.png" target:nil selector:nil] retain];
CCMenuItemToggle *toggleItem = [CCMenuItemToggle itemWithTarget:self 
  selector:@selector(plusMinusButtonTapped:) items:_plusItem, _minusItem, nil];
CCMenu *toggleMenu = [CCMenu menuWithItems:toggleItem, nil];
toggleMenu.position = ccp(60, 120);
[self addChild:toggleMenu];

まず2つの”CCMenuItemImages”を作成(手順は先ほどと同じ)し、2つを”CCMenuItemToggle”に格納します。このクラスは、2つの間の切り替えを保持し、現在どちらが表示されているかを把握します。

“CCMenuItemImages”を作成する時にコールバックを”nil”を渡している事に注意して下さい。しかし”CCMenuItemToggle”ではコールバックを設定しています。この事から、”CCMenuItemToggle”に”CCMenuItemImagesが格納される場合、”CCMenuItemImages”のコールバックは呼び出されず、”CCMenuItemToggle”のそれが呼び出される事が分かります。幸運にもどちらのmenuアイテムが表示されるかをコールバックに実装するのは簡単です。

コールバックにどの様に実装するのかをみてみましょう。以下をinitメソッドの下に加えて下さい:

- (void)plusMinusButtonTapped:(id)sender {  
  CCMenuItemToggle *toggleItem = (CCMenuItemToggle *)sender;
  if (toggleItem.selectedItem == _plusItem) {
    [_label setString:@"Visible button: +"];    
  } else if (toggleItem.selectedItem == _minusItem) {
    [_label setString:@"Visible button: -"];
  }  
}

このように、”CCMenuItemToggle”には”selectedItem”プロパティがあって、どちらのアイテムが今表示されているかを簡単に設定出来ます(どちらがタップされたかではなく、どちらが表示されているかである事に中注意して下さい)。
コンパイルしてランして下さい。問題が無ければ以下の様に表示されるはずです:

Toggle Button Screenshot

ラジオボタン

3つ目の良く見るボタンのタイプはラジオボタンです。今開発途中のゲームでラジオボタンが必要だったのですが、Cocos2Dの実装ではラジオボタンが見当たらなかったので、自分で実装する為のソースを書いてみました。このチュートリアルを執筆中に2人の方がCocos2Dでサポートされるラジオボタンの実装 を書いていた事を知りました。ですからCocos2Dのソースでこのような方法を見つける事が出来る様になると思います。

しかし、今はまだ見つける事が出来ませんから、その間に私が書いた実装方法や上記の”CCRedioMenu”ファイルをどうぞ自由にお使いください。このチュートリアルの目的のために、”CCRadioMenu”を使用してラジオボタンを実装してみましょう。 まずはCCRadioMenu.hとCCRadioMenu.m をダウンロードしてそれらをプロジェクトに追加して”Copy items into destination group’s folder (if needed)”に忘れずにチェックして下さい。

次に”HelloWorldScene.m”の一番上に以下の様にimportしてください:

#import "CCRadioMenu.h"

そして以下をinitメソッドの中の[self addChild:toggleMenu]のすぐ下に追加して下さい:

CCMenuItem *menuItem1 = [CCMenuItemImage itemFromNormalImage:@"Button1.png" 
  selectedImage:@"Button1Sel.png" target:self selector:@selector(button1Tapped:)];
CCMenuItem *menuItem2 = [CCMenuItemImage itemFromNormalImage:@"Button2.png" 
  selectedImage:@"Button2Sel.png" target:self selector:@selector(button2Tapped:)];
CCMenuItem *menuItem3 = [CCMenuItemImage itemFromNormalImage:@"Button3.png" 
  selectedImage:@"Button3Sel.png" target:self selector:@selector(button3Tapped:)];
CCRadioMenu *radioMenu = 
  [CCRadioMenu menuWithItems:menuItem1, menuItem2, menuItem3, nil];
radioMenu.position = ccp(120, 180);
[radioMenu alignItemsHorizontally];
radioMenu.selectedItem = menuItem1;
[menuItem1 selected];
[self addChild:radioMenu];

今まで通り、”CCMenuItemImages”を作成し、”CCMenu”に格納するよりも、新しい”CCRadioMenu”クラス格納します。このクラスは1回に1つしか選択出来ません。加えて”menuItem1”をデフォルトで選択された状態に設定しています。

ここでの新しい事と言えば、Cocos2Dでmenuに利用出来るカッコいいAuto Layout機能”alignItemsHorizontally”です。アイテムがmenuの中心に対してレイアウトされる事に注意して下さい。ですからmenu基準となる中心が(0,0)ではなくなります。

最後にいつもの様にコールバックメソッドを追加します:

- (void)button1Tapped:(id)sender {
  [_label setString:@"Last button: 1"];
}
- (void)button2Tapped:(id)sender {
  [_label setString:@"Last button: 2"];
}
- (void)button3Tapped:(id)sender {
  [_label setString:@"Last button: 3"];
}

それでは、コンパイルしてランして下さい。すると以下の様に表示されるはずです:

Radio Buttons Creenshot

Sceneの裏舞台

“menu”システムの実装方法を見てみると、”menu”アイテムは”CCNode”で、”Menu”は”CCLayer”である事に気付きます。 Cocos2D best practicesによると、あまり多くのlayer層を作成するべきではなく、可能な限り少なくするべきとあります。

つまり必要なmenuアイテムは1つの”menu layer”に出来るだけたくさん束ねておくべきです。MenuはCCLayerから派生しているので、MoveTo等のアクションは実装出来ません。以前、menuアイテムを全て動かそうとした時、出来なくて、何故なんだろうと疑問に思った事がありました。 :] アップデート:Ericからのコメントで、CCLayerはCCNodeからの派生なのでやろうと思えばアクションを実装出来るとの事です。私が以前試してみて動かなかった時は何か他の原因があったんだと思います。勉強になりました!Ericに感謝です!:]

以上です、有り難うございました!

このチュートリアルのサンプルコードはこちらからどうぞ。
このチュートリアルが貴方のこれからの開発に有益なものになれば幸いです。もし、Cocos2Dのボタンについて何かためになる事をご存知でしたら是非教えてください!

Ray Wenderlich

Ray is an indie software developer currently focusing on iPhone and iPad development, and the administrator of this site. He’s the founder of a small iPhone development studio called Razeware, and is passionate both about making apps and teaching others the techniques to make them.

When Ray’s not programming, he’s probably playing video games, role playing games, or board games.

ユーザーのコメント

0 Comment

Other Items of Interest

Ray's 月刊ニュースレター

月刊ニュースレターを受け取る為にサインアップすると、得点として無料長編チュートリアルを受け取る事が出来ます。

広告掲載のご案内!

Hang Out With Us!

Every month, we have a free live Tech Talk - come hang out with us!


Coming up in July: Facebook Pop Tech Talk!

Sign Up - July

RWDevCon Conference?

We are considering having an official raywenderlich.com conference called RWDevCon in DC in early 2015.

The conference would be focused on high quality Swift/iOS 8 technical content, and connecting as a community.

Would this be something you'd be interested in?

    ローディング ... ローディング ...

書籍

チームメンバー

チュートリアルチーム

  • Kyle Richter

... 50 名在籍

Update Team

  • Riccardo D'Antoni

エディトリアルチーム

... 23 名在籍

Code Team

  • Orta Therox

... 1 名在籍

翻訳チーム

  • Lin Ma
  • Marina Mukhina

... 33 名在籍

サブジェクトマター専門チーム

  • Richard Casey

... 4 名在籍