【Xcode】鳴き声足し算ゲームiPhoneアプリを作成してみよう|CocoaPodsを使いこなす

みなさんこんにちは。Yuta Fujii(@HofuCamera)です。

今回は「鳴き声足し算ゲームiPhoneアプリ」を作成していきたいと思います。このアプリは、ある数字が表示されたあと、何と何を足したらその数字になるか考えるゲームです。また、数字を選択するときにかわいい音もならしてみたいと思います。この音をイヌやネコにすることでキッズ向けアプリケーションにもなります。

そして、よくアプリを新しく開始する際にみるイントロダクション部分も作成していきたいと思います。

それでははじめていきましょう!

↓Xcodeの環境構築がまだの方はこちら↓

Cocoa Podsを使用してみよう

今回のアプリでは、アプリがよりリッチになる便利なツールを使いながら進めていきたいと思います。
まず、以下のURLを見ていきましょう。

xcode_game2
cocoacontrols.com

このCocoa Controlsとは、便利なツールを検索したり、自分のプロジェクトに取り込むためにはどうしたらよいのかなどが書かれてあります。それでは、イントロダクション(アプリのはじめに出てくる説明)をこれを用いてつくっていきたいと思います。まず、検索窓にintroと入れます。
xcode_game3

すると、たくさんイントロダクションに関するサンプルが出てきます。
今回は、EAIntroViewを使ってみたいと思います。EAIntroViewと書かれた場所をクリックしてください。すると、詳細ページに飛びます。
xcode_game3

右上のDownload Sourceと書かれたところをクリックします。
xcode_game5
すると、このようなページが出てきます。
xcode_game6

下部へ行くとCocoaPodsと書かれた書かれた箇所があるかと思います。
xcode_game7
使い方を順に説明していきます。

CocoaPodsをインストールする

それでは、プロジェクトを作成していきます。
Xcodeを立ち上げ、Create a New Xcode projectをクリックします。
xcode_game9

以下のように進めていきます。
xcode_game10

名前はnumberGameとします。
xcode_game11

xcode_game12

ターミナルを使ってみる

続いて右上赤い部分の検索マークをクリックして、「ターミナル」検索してエンターを押します。
xcode_game13

すると、このような画面が出てきます。
続いて、sudo gem install cocoapodsと入力してエンターを押します。次に、pod setupと入力してエンターを押します。すると、CocoaPodsを使う準備が完了します。
xcode_game15

Xcodeに戻り、赤い部分を選択した状態で、File→New→Fileを選択していきます。
xcode_game16

普段であれば、左側にあるようにSourceという箇所を使用しますが、
xcode_game17

今回はOtherを選択します。
xcode_game18

Emptyを選択し、Nextをクリックします。
xcode_game19

ファイル名をPodfileとします。(ここの名前が重要です)
xcode_game20

そしてCreateを押します。
xcode_game21

すると、Podfileというファイルが作成されます。今は何も記述されていません。
xcode_game22

ここで、先ほどのサイトへ戻ります。赤い部分に注目してください。
xcode_game24a

ここがこのイントロダクションパーツの使い方になります。
それでは何が書かれているか順に説明していきます。
まず、1行目に先ほど作成したPodfileへ記述しなければならない項目が書かれています。
ここでは、pod ‘EAIntroView’, ‘~> 2.8.0’がそれにあたります。
これを先ほど作成したPodfileへ記述します。
xcode_game23

2行目、pod installと書かれた部分があります。これは先ほどのターミナルで実行するものになります。詳しい記述方法は後ほど説明します。
3行目にはファイルにインポートする際にどう書くべきかが記述されています。
最後はデリゲートを指定する際の書き方が説明されてあります。

それではターミナルに戻りましょう。
ここで、cd とまず記入します。これはチェンジディレクトリの略で、今から次のファイルある所まで移動しますという意味になります。
xcode_game25

このcdのあとに続いて、numberGameというファイルをドラッグ&ドロップします。
xcode_game26

すると以下のようになります。
xcode_game27

ここでエンターを押します。
するとプロジェクトファイルのある位置まで移動することができました。
ここでpod installと記述してエンターを押します。
xcode_game28

次々と処理が進みます。
xcode_game29

最後まで終わったらexitと記述してターミナルを終了します。
xcode_game31

すると、numberGameのプロジェクトを開こうとした際に白いnumberGame.xcworkspaceというものが出来上がっているのがわかります。
xcode_game33
これをダブルクリックしてプロジェクトを開始します。
赤い部分をクリックしてファイル郡を開きます。
xcode_game34

あとはいつも通りMain.stroyboardをクリックして、iPhone4.7-inchを選択してプログラムファイルを開きます。
xcode_game37

xcode_game38

ここで、以前のサイトへまた戻ります。
xcode_game39

下記のマニュアル通り

#import "EAIntroView.h" 

と記述します。
xcode_game40

これで先ほどのイントロダクションを使用する準備が整いました。

デリゲートも記述して、
xcode_game41

ここをコピー&ペーストします。
xcode_game42

// custom
EAIntroPage *page2 = [EAIntroPage page];
page2.title = @"This is page 2";
page2.titleFont = [UIFont fontWithName:@"Georgia-BoldItalic" size:20];
page2.titlePositionY = 220;
page2.desc = sampleDescription2;
page2.descFont = [UIFont fontWithName:@"Georgia-Italic" size:18];
page2.descPositionY = 200;
page2.titleIconView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"title2"]];
page2.titleIconPositionY = 100;

すると、エラーがでました。
xcode_game43
ここは、descと書かれてあります。おそらくディスクリプション(文章)のことだと思うので、

こんな感じで変更します。
xcode_game44

続いてイントロダクションの背景になる画像を取り込みます。
ドラッグ&ドロップして、Finishします。
xcode_game46

xcode_game47

全体的に以下のように変更します。
xcode_game48

    // custom
    EAIntroPage *page1 = [EAIntroPage page];
    page1.title = @"このようにつかいます1";
    page1.titleFont = [UIFont fontWithName:@"Georgia-BoldItalic" size:20];
    page1.desc = @"これは使い方1のページです";
    page1.descFont = [UIFont fontWithName:@"Georgia-Italic" size:18];
    page1.bgImage = [UIImage imageNamed:@"intro1.jpg"];
    
    
    
    // custom
    EAIntroPage *page2 = [EAIntroPage page];
    page2.title = @"このようにつかいます2";
    page2.titleFont = [UIFont fontWithName:@"Georgia-BoldItalic" size:20];
    page2.desc = @"これは使い方2のページです";
    page2.descFont = [UIFont fontWithName:@"Georgia-Italic" size:18];
    page2.bgImage = [UIImage imageNamed:@"intro2.jpg"];
    
    
    
    
    // custom
    EAIntroPage *page3 = [EAIntroPage page];
    page3.title = @"このようにつかいます3";
    page3.titleFont = [UIFont fontWithName:@"Georgia-BoldItalic" size:20];
    page3.desc = @"これは使い方3のページです";
    page3.descFont = [UIFont fontWithName:@"Georgia-Italic" size:18];
    page3.bgImage = [UIImage imageNamed:@"intro3.jpg"];
    
    
    
    
    // custom
    EAIntroPage *page4 = [EAIntroPage page];
    page4.title = @"このようにつかいます4";
    page4.titleFont = [UIFont fontWithName:@"Georgia-BoldItalic" size:20];
    page4.desc = @"これは使い方4のページです";
    page4.descFont = [UIFont fontWithName:@"Georgia-Italic" size:18];
    page4.bgImage = [UIImage imageNamed:@"intro4.jpg"];
    
    
    EAIntroView *intro = [[EAIntroView alloc] initWithFrame:self.view.bounds andPages:@[page1,page2,page3,page4]];
    
    
    [intro setDelegate:self];
    
    
    [intro showInView:self.view animateDuration:0.0];

続いてサイトを参考に、
xcode_game49

記述します。
xcode_game50

ここでエラーが出ています。
page2、page3 、page4がありませんということです。
なので作ります。
xcode_game51
するとエラーが消えました。
xcode_game52

またサイトを参考に、以下を加えます。
xcode_game53

そして、全体的に以下のように変更します。(必要なところだけ記述します。)
xcode_game54

さらに、全てをviewDidLoad内に書くのは見づらいので、showIntroというメソッドを新しくつくってみます。
xcode_game55

このメソッドの中に先ほど書いたコードをそのままコピー&ペーストして、viewDidLoad内のコードは消去します。
xcode_game56

そして、この新しく作成したshowIntroをviewDidLoad内で呼び出してあげます。
xcode_game57

xcode_game59

シミュレーターで確認してみよう

それではシミュレーターで確認してみましょう。
左上の▶ボタンをクリックしてシミュレーターを立ち上げます。
すると、このようにイントロダクションが出るようになりました。
xcode_game60

シミュレーターの画面を横にスライドさせると次のページへと進んでいきます。
xcode_game61

さらに、右下のSkipボタンをクリックすると、
xcode_game62

何もパーツを載せていない画面が現れます。
xcode_game63

【イントロ部分の改変】イントロダクション部分を1回だけの表示にする

前回、cocoa Podsを使用して、イントロダクションを取り込みました。
通常イントロダクションは、はじめてアプリをインストールして起動した際に1回のみ表示され、その後は表示されないというのが一般的かと思います。
まずは、イントロダクション部分を1回表示したらその後はアプリを起動しても表示しないという機能を実装していきたいと思います。

NSUserDefaultsを使用して管理する

前回までの講座でアプリ内にデータを半永久的に保存する「NSUserdefaults」の使い方についても見てきたと思います。今回この中にデータを入れて、もしイントロダクションが表示されたら次回からはイントロダクションを表示しないという形で作成していきます。

まず、下記のようにNSUserdefaultを使用することを宣言します。
xcode_gamese1

NSUserDefaults *ud;
xcode_gamese0
    ud = [NSUserDefaults standardUserDefaults];

さらに、次のように記述します。
xcode_gamese2

BOOL flag = [ud boolForKey:@"intro"];
   
    if (flag != YES) {
        [self showIntro];
        [ud setBool:YES forKey:@"intro"];
    }

順を追って説明していきます。
まず、NSUserDefaultsの変数である、udからキー値introでbool値(YES or NO)を取り出しています。デフォルト状態ではYESではないので(何も値をintroというキー値で入れていないので)、

if (flag != YES) {

もし、flagの中身がYESでなかったら

[self showIntro];

[ud setBool:YES forKey:@"intro"];

showIntroメソッドを呼ぶ、つまりイントロダクションを出します。
次に、introというキー値でYESを入れます。
すると、次回からintroというキー値でBool値を取り出した際、YESであるので、このif文の中にはプログラムは入ってきません。
このBool値は半永久的に保存されるのでイントロダクションはその後表示されなくなります。

問題を作成していく

それでは、問題の数字が入るようint型の変数を準備します。
xcode_gamese3

int question;

さらに、このquestionという変数の中に乱数で発生させた数字を入れます。
xcode_gamese4

question = (int)arc4random()%10;

次に、Storyboard上にラベルを配置します。
このラベルはquestionの数字を表示することになります。
xcode_gamese5
文字を変更します。
xcode_gamese6
さらに、数字を入力するテキストフィールドも画面の上にのせます。
xcode_gamese7
+というラベルものせて
xcode_gamese8
もう1つテキストフィールドを画面にのせます。
xcode_gamese9

Cocoa Podsを使用する【キーボードを準備する】

ここで再度、cocoa podsを使用します。
今回は、キーボードを扱います。
通常のキーボードとは別に数字に特化したものを使用します。
Podfileに以下のように記述します。
xcode_gamese10

pod ‘MMNumberKeyboard’

次にターミナルを開いて、前回同様cd→ドラッグ&ドロップでプロジェクトのある階層まで行きます。
xcode_gamese11
最後に pod installと書いて、エンターを押します。するとプロジェクトへの取り込みが開始されます。
xcode_gamese12
とりこむ処理が開始されます。
xcode_gamese13
全て終わったらexitと打ってターミナルを終了させます。
xcode_gamese14

今回使用したものは下記のMMNumberKeyboard for iOSというものになります。

https://github.com/matmartinez/MMNumberKeyboard
xcode_gamese15

続いて、このMMNumberKeyboardをプログラムへ取り込みます。

xcode_gamese16
#import “MMNumberKeyboard.h"

説明を参考にデリゲートも書きます。
xcode_gamese17

さらに、MMNumberKeyboardの使い方に書いてあるように、以下のようにコードを記述していきます。
xcode_gamese18

    // Create and configure the keyboard.
    MMNumberKeyboard *keyboard = [[MMNumberKeyboard alloc] initWithFrame:CGRectZero];
    keyboard.allowsDecimalPoint = YES;
    keyboard.delegate = self;

続いて画面のパーツをプログラムに認識させていきます。

下記のようにテキストフィールドを選択して、commandを押しながらドラッグ&ドロップしていきます。ここではtextfield1という名前をつけました。
xcode_gamese19

もう一方のテキストフィールドも同じ方法で認識させていきます。
こちらはtextfield2と名づけました。
xcode_gamese20
xcode_gamese21

さらに、MMNumberKeyboardもデリゲートメソッドも記述します。
xcode_gamese22

- (BOOL)numberKeyboardShouldReturn:(MMNumberKeyboard *)numberKeyboard
{
    // Do something with the done key if neeed. Return YES to dismiss the keyboard.
    return YES;
}

さらに、テキストフィールドの体裁を整えていきます。
以下のようにtextfield1、textfield2ともに記述していきます。
ただ、ここは後ほど変更していきます。
xcode_gamese23
変更後のプログラムは以下になります。

textField1.inputView = keyboard;
    textField1.text = @"";
    textField1.placeholder = @"数字1";
    textField1.font = [UIFont systemFontOfSize:24.0f];
    textField1.contentVerticalAlignment = UIControlContentVerticalAlignmentTop;

textField2.inputView = keyboard;
    textField2.text = [NSString stringWithFormat:@"%d",number];
    textField2.placeholder = @"数字2";
    textField2.font = [UIFont systemFontOfSize:24.0f];
    textField2.contentVerticalAlignment = UIControlContentVerticalAlignmentTop;

次に、答え合わせボタンを画面上へ置きます。
xcode_gamese24

さらに、プログラムへ認識させます。
xcode_gamese25
answerという名前をつけました。
xcode_gamese26

現在textfield2でnumberという箇所にエラーが出ているかと思います。
このnumberは今から作成しますが、問題の数字が乱数によって生成され、ラベルに表示された後、テキストフィールド2にも乱数によって生成した数字を記入します。

ゲームのルールを、問題の数字にはテキストフィールド2にある数字と何を足したらなるのかということで正誤判定をしていきたいと思います。

正誤判定は答え合わせボタンをタップしたときに行います。

それでは、テキストフィールド2のなかに入れておくための箱を準備します。
xcode_gamese27

    int number;

そしてnumberへ乱数を発生させた数字を入れておきます。(ここも後ほど変更します)
xcode_gamese28
続いて、数字を文字列へ変換します。これをキャストといいます。
xcode_gamese29
さらに問題正誤判定が終わったあと、問題をリセットする場所を作成します。
ボタンを画面の上へ置き、リセットと名前をつけメソッドの名前をresetとしました。
xcode_gamese30
ここに、リセットボタンが押されたときの処理を記述していきます。
xcode_gamese31
ここで行っているのは、numberへ乱数を再びいれて新しくした後、textfield1の文字列を空にします。次に、textfield2のテキストをnumberとします。

また、問題の数字というラベルをプログラムへ認識させていきます。
resultLabelと名づけました。
xcode_gamese32
xcode_gamese33
続いて、問題の数字のラベルへ乱数を発生させた数字を反映させていきます。
questionに乱数を発生させた後、その数字を文字列にキャストしてラベルの文字として反映させます。
xcode_gamese35

resultLabel.text = [NSString stringWithFormat:@"%d",question];

さらに、リセットが押されたときも同様に問題の数字を新しくします。
xcode_gamese36

    resultLabel.text = [NSString stringWithFormat:@"%d",question];

乱数へ範囲を設ける

ここで乱数に関して範囲をもうけていきたいと思います。
viewDidLoad内を変更します。
xcode_gamese39

    int question2 = 5.0 + arc4random() % 6; //5から10までの乱数を取得
    question = question2;

次に、numberも同様に範囲を指定します。
xcode_gamese40

   int number2 = rand()%3 + 1; //1から3までの乱数を取得
    number = number2;

リセットボタンの箇所も同様に変更します。
xcode_gamese41

    int question2 = 5.0 + arc4random() % 6; //5から10までの乱数を取得
    question = question2;
xcode_gamese42
   int number2 = rand()%3 + 1; //1から3までの乱数を取得
    number = number2;

最後に正誤判定用に数字を入れておく箱を準備します。
xcode_gamese43

int result;

answerの部分へ以下のように記述します。
xcode_gamese45

  result = number + [textField1.text intValue];

    if (result == question) {
        resultLabel.text = @"正解!";
    }else{
        
        resultLabel.text = @"間違い!";
        
    }

まず、textfield2で用いるnumberとtextfield1で入力された文字列を数字へ変換したものを足し算してresultへ入れます。

そして、もしresultの中の数字と問題の数字、つまりquestionの値が同じであれば、
resultlabelのテキストを正解、そうでなければ間違いとします。

シミュレーターで確認してみよう

それでは左上の▶ボタンをクリックしてシミュレーターを立ち上げて確認してみましょう。
試しに、間違ってみます。
2 + 2 = 8となるかどうか試しています。
xcode_gamese47
答え合わせボタンをタップすると、間違い!と判定されました。
xcode_gamese48
次に、3 + 2 = 5となるか確認してみます。
xcode_gamese49

正解と表示されました。
xcode_gamese50

音声ファイルをプロジェクトへ取り込む

xcode_gameth1
それでは、音声ファイルを取り込んでいきたいと思います。
mp3の音源を準備し、それをプロジェクトへドラッグ&ドロップしてください。
xcode_gameth2

音源が必要な方はこちらから

jokersounds.com

ここでは、neko.mp3を取り込みました。

音声用フレームワークを導入する

今までの講座の中で、フレームワークを導入して処理を行うことをしてきたと思います。
ここでも同様に音声用のフレームワークを使用して音声を鳴らしてみたいと思います。
まず。赤い部分を選択した状態で、
xcode_gameth3

下へスクロールすると、赤い部分に+と書かれた箇所があるのでそこをクリックします。
xcode_gameth4

検索窓が出てきますので、AVFoundation.frameworkを選択し、Addをクリックします。
xcode_gameth5

下のように導入されたら準備完了です。
xcode_gameth6

とりこんできたもののプログラムを確認する

今回は、外部からとりこんだ数字のみのキーボードに対して、数字をタップすると音を鳴らすという処理をしていきます。
ということは、cocoa podsを用いて取り込んだもののプログラムを改変しなければなりません。
そのプログラムの見つけ方について説明します。

まず、下記のようにデリゲートの箇所をcommandをクリックしながら選択します。
xcode_gameth7
すると、そのプログラムの.hファイルへ行きました。
xcode_gameth8
ただ、具体的な処理が記述されているのは実装ファイルである.mファイルなので、
赤い部分をクリックして、
xcode_gameth9
.mファイルを選択すると、ロックがかかっています。
赤い部分をクリックして、ロックを解除します。
xcode_gameth10

すると、実装ファイルを確認することができました。

次に、キーボードをタップした時に反応する場所を探していくのですが、その前にフレームワークを使えるようにインポートしておきます。
xcode_gameth11

#import <AVFoundation/AVFoundation.h>

次に音声再生ようの変数を準備します。
xcode_gameth12

AVAudioPlayer *audioPlayer

そして、下記のようにボタンをタップしたときに反応する箇所を見つけました。
xcode_gameth13
ここに音声を再生するプログラムを書いていきます。
xcode_gameth14

下記のように記述します。

  NSError *error = nil;
    // 再生する audio ファイルのパスを取得
    NSString *path = [[NSBundle mainBundle] pathForResource:@"neko" ofType:@"mp3"];
    // パスから、再生するURLを作成する
    NSURL *url = [[NSURL alloc] initFileURLWithPath:path];
    // auido を再生するプレイヤーを作成する
    audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&error];
    audioPlayer.numberOfLoops = 0;
    [audioPlayer play];

以上で完成です。

シミュレーターで確認してみよう

それでは、本当にタップしたときに音がなるかためしてみてください。
xcode_gameth15

このように連続でクリックしてもにゃーという音がなるのがわかります。
xcode_gameth16

鳴き声足し算ゲームのまとめ

いかがでしたか?
もし今日にのある方はキッズアプリのように、背景に画像をつけてみましょう。

画像の素材はこちらからダウンロードしてみてください。

画像をドラッグ&ドロップして、プロジェクトへ導入したあと、イメージビューを置いてそこに設定します。
xcode_gameth19
イメージビューは最下部へ配置しなおして完成です。
xcode_gameth20

背景画像をセットして、音をつけてあげて、かつキーボードやイントロダクションを外部から取り込むことで、子供が喜びそうな本格的な知育系アプリにしてみたいと思います。
xcode_gameth21
ぜひオリジナルアプリをつくるときに参考にしてみてください。

この記事をかいた人

知識ゼロからプロのInstagram風画像加工iPhoneアプリを作る 特別クーポン配布中! 詳しくはこちらから! エンジニアでプロデューサー ピーターティールが大好きです! Twitter:Yuta Fujii 質問はお気軽にどうぞ!