0
    「当たり判定」ということで、
    前回は、その考え方を説明しましたが、
    いよいよ今回は、それをプログラムで実装していきたいと思います

    [今回の内容]
    ■UIImageViewの中心座標を取得する
    ■ルートを使って、キリンさんとライオンさんの距離を計算
    ■ルートは使わない方が良い
    ■当たり判定の条件分岐
    ■当たり判定でキリンさんに影響を与える

    ■UIImageViewの中心座標を取得する

    前回の内容にも書きましたが、
    当たり判定に必要なものは、キリンさんとライオンさんの中心の座標です
    座標には、X座標とY座標がありますので、
    キリンさんの中心のX座標とY座標、ライオンさんの中心のX座標とY座標
    以上の4つの数値が必要になります

    ではまず、TestGameViewController.h でその4つの変数を指定しましょう

    BOOL moveLFlag, moveRFlag, startFlag;
       
    float kirinX, kirinY, lionX, lionY;

    .h

    ここで、はじめて float というものが出てきましたので説明を、

    float は、浮動小数点数型といわれ...
    まあ難しいこと抜きにして、
    float は「小数」です

    で、float型 で4つの変数を指定しています
    それぞれは、
       kirinX ---> キリンさんの中心のX座標
       kirinY ---> キリンさんの中心のY座標
       lionX ---> ライオンさんの中心のX座標
       lionY ---> ライオンさんの中心のY座標
    を取得するために利用します

    次に、その中心の座標を取得するために、
    TestGameViewController.m に移りましょう

    まずは初期化の - (void) loadView の中身から
    startBT = [[UIButton alloc] initWithFrame:CGRectMake(100.0, 300.0, 120.0, 80.0)];
    [startBT setTitle:@"START" forState:UIControlStateNormal];
    [startBT setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
    [startBT addTarget:self action:@selector(start_touchUp:) forControlEvents:UIControlEventTouchUpInside];
    startBT.backgroundColor = [UIColor blackColor];
    [self.view addSubview:startBT];

       
    CGPoint center;
    center = kirinIV.center;
    kirinX = center.x;
    kirinY = center.y;

    center = lionIV.center;
    lionX = center.x;
    lionY = center.y;


    赤い部分で、キリンさんとライオンさんの中心の座標を取得します

    これまで、キリンさんとライオンさんの座標とサイズを取得するときに
    CGRect frame として、CGRect を利用してきましたが、

    世の中には便利なものがありまして、
    CGPoint というものを利用すれば、UIImageView や UIButton などの
    オブジェクトの座標のみをさらりと取り出すことができます

    では、赤い部分を説明します

    1行目:早速その CGPoint を利用し、変数を center とします
    以下はキリンさんの値
    2行目:kirinIV の中心座標を center として取得
    3行目:取得したcenterのX座標の値を、kirinX に代入
    4行目:取得したcenterのY座標の値を、kirinY に代入
    ここからはライオンさんの値
    5行目:次は、lionIV の中心座標を center として取得
    6行目:取得したcenterのX座標の値を、lionX に代入
    7行目:取得したcenterのY座標の値を、lionY に代入

    これで、それぞれのスタート位置での中心座標を取得できました

    center

    初期化が完了したところで、
    - (void)drawFrame に移りましょう

    キリンさんとライオンさんの中心座標は、それぞれが移動する度に変化します
    なので、kirinXとkirinY、 lionXとlionYの値は、それぞれが移動するごとに
    あらたに取得し続けなければいけません

    ということで、アニメーションの中で、
    それぞれが移動したあとに、中心の座標を取得する記述を行います

    if(moveLFlag == TRUE){
        CGRect frame = kirinIV.frame;
        frame.origin.x -= 1.0;
        [kirinIV setFrame:frame];

        //NSLog(@"MOVE(L):%.1f", frame.origin.x);

        CGPoint center = kirinIV.center;
        kirinX = center.x;
        kirinY = center.y;
    }

    if(moveRFlag == TRUE){
        CGRect frame = kirinIV.frame;
        frame.origin.x += 1.0;
        [kirinIV setFrame:frame];

        //NSLog(@"MOVE(R):%.1f", frame.origin.x);

        CGPoint center = kirinIV.center;
        kirinX = center.x;
        kirinY = center.y;
    }

    CGRect frame = lionIV.frame;
    frame.origin.y += 1.0;
    if(frame.origin.y >= 480.0) frame.origin.y = -40.0;
    [lionIV setFrame:frame];

    //NSLog(@"LION:%.1f", frame.origin.y);

    CGPoint center = lionIV.center;
    lionX = center.x;
    lionY = center.y;

    赤い部分を追加しています
    上の赤い二行は、キリンさんを左に移動させているときに座標を取得
    中の赤い二行は、キリンさんを右に移動させているときに座標を取得
    下の赤い二行は、ライオンさんが常に移動しているので常に座標を取得
    という具合です

    center

    あと、緑の行ですが、今後の内容で NSLog が邪魔になるので、
    行の先頭に「//」をつけて、コメントアウト...
    つまり、その一行分の処理を無効化しています
    (もう消してしまってもいいです)

    ...

    さてこれで、キリンさんとライオンさんの移動に応じて、
    その中心の座標を取得できるようになりました

    ■ルートを使って、キリンさんとライオンさんの距離を計算

    それでは、取得した中心座標を使って、
    キリンさんとライオンさんの中心の距離を考えていきましょう

    おさらいとして、距離を求める計算式を図に示しておきます

    R

    先ほど取得した中心座標を式に当てはめます

    float kyori = sqrt((kirinX-lionX)*(kirinX-lionX) + (kirinY-lionY)*(kirinY-lionY));

    ※掛け算は「x」でなく「*」で記述します

    説明します
    float kyori ---> 上の式のRを、kyoriという名の小数型とします
    sqrt( ) ---> ルートを計算します ( )の中身の平方根を求めることができます
       (kirinX-lionX)*(kirinX-lionX) ---> 二乗の表記はないので、X座標の差を単純に掛ける
       (kirinY-lionY)*(kirinY-lionY) ---> 同じく、Y座標の差を単純に掛ける

    これを、- (void)drawFrame の中に記述しましょう
    3行追加します

    CGRect frame = lionIV.frame;
    frame.origin.y += 1.0;
    if(frame.origin.y >= 480.0) frame.origin.y = -40.0;
    [lionIV setFrame:frame];
           
    //NSLog(@"LION:%.1f", frame.origin.y);
           
    lionX = frame.origin.x + 20.0;
    lionY = frame.origin.y + 20.0;

    //Atari
    float kyori = sqrt((kirinX-lionX)*(kirinX-lionX) + (kirinY-lionY)*(kirinY-lionY));
    NSLog(@"R:%.1f", kyori);

    1行目:- (void)drawFrame の中が長くなったので「当たり判定」の目印
    2行目:中心座標の距離を [kyori] として取得
    3行目:NSLog を使って距離を表示
    ※1行目は単なる目印なので、なくても良い

    sqrt

    それでは、[Run]しましょう
    まず、キリンさんをライオンさんとぶつかる位置まで移動させてください
    そして、NSLog で表示された数値を確認してください
    キリンさんとライオンさんの中心の距離が表示されます

    40

    ちょっと早すぎて確認しづらいと思いますが、
    ライオンさんが、上から画面中心に近づくときに数値が小さくなり
    ライオンさんが、画面中心から下へ離れるときに数値が大きくなります

    そして、前回は話したように、
    数値が40より大きい」ときは、当たっていなくて
    数値が40より小さい」ときは、当たっている
    ことになります

    当たっている

    ■ルートは使わない方が良い

    さてここで、先ほど何の躊躇もなく、
    ルートの式  sqrt( ) を使っていましたが、この計算がパソコン、
    このアプリの場合は iPhone に負担を強いることになります

    まぁ、人間にとってもややこしい計算ですが、
    パソコンにとってもややこしい計算であるということなのです

    特に、iPhone の場合は、パソコンよりも処理能力は劣るので、
    できるだけ負担のかかる処理は行いたくありません

    では、どうするか?

    負担の根源 sqrt( ) を消しちゃいましょう

    //Atari
    float kyori = (kirinX-lionX)*(kirinX-lionX) + (kirinY-lionY)*(kirinY-lionY);
    NSLog(@"R:%.1f", kyori);

    no_sqrt

    でもこれじゃ、距離がおかしくなるよ?

    さて、ルートの計算をやめて、変更後に求められる [kyori] は、
    「X座標の差の二乗」と「Y座標の差の二乗」を足したものになります
    下図の一番下の式のように

    ピタゴラス


    ということで、[kyori] には、
    平方根を求める前の値(ルートの計算をする前の値)が代入されます

    これを「当たり判定」の基準である、40ピクセルで考えると

    当たっていない --(ルート使用)--> kyori > 40 --(変更後)--> kyori > 1600 (40x40)
    ちょうど当たった --(ルート使用)-->  kyori = 40 --(変更後)--> kyori = 1600 (40x40)
    当たっている --(ルート使用)-->  kyori < 40 --(変更後)--> kyori < 1600 (40x40)

    となります
    説明が下手なので、とりあえず [Run] してみましょう

    同じようにキリンさんを移動して、
    NSLog の表示内容を確認します

    1600

    表示された数値が大きくなっていますが、
    40 x 40 = 1600 を境に、当たっているかどうかを判断することができます

    ■当たり判定の条件分岐

    わかりにくかったかもしれませんが、
    以上をふまえて、「当たり判定の条件」を記述します

    当たり判定のところ (//Atari) の NSlogを消して、
    赤い部分6行を追加します

    //Atari
    float kyori = (kirinX-lionX)*(kirinX-lionX) + (kirinY-lionY)*(kirinY-lionY);
    if(kyori < 40.0*40.0){
         NSLog(@"ATARI:%.1f", kyori);
    }
    else {
         NSLog(@"HAZURE:%.1f", kyori);
    }

    ※掛け算は「x」でなく「*」で記述します

    追加部分の説明をする前に、
    if の説明をすると、
    「if (条件) 〜 else 〜」という書き方を使って、
    「もし (条件) のとき 〜、それ以外のとき 〜 」となり
    処理を分岐することができます

    追加部分の内容は

    もし、kyori が、40x40(=1600) より小さいとき {
         NSLog で「ATARI:距離」を表示する
    }
    それ以外(40x40以上)のとき{
         NSLog で「HAZURE:距離」を表示する
    }

    となります

    atari-hazure

    それでは、[Run]して同じように確認しましょう

    atari-hazure

    1600の数値を境にして、
    「ATARI」と「HAZURE」の表示が切り替わったのがわかりますか?

    これで、当たり判定の条件分岐を正しく機能させることができました

    ■当たり判定でキリンさんに影響を与える

    では、その条件分岐を利用してキリンさんの姿を変化させてみましょう
    やることは単純で、if の中身を変更するだけです

    //Atari
    float kyori = (kirinX-lionX)*(kirinX-lionX) + (kirinY-lionY)*(kirinY-lionY);
    if(kyori < 40.0*40.0){
            kirinIV.backgroundColor = [UIColor redColor];
    }
    else {
            kirinIV.backgroundColor = [UIColor yellowColor];
    }

    キリンさんの変化は、kirinIV の色を変更する記述をしています
    まず、上の「当たっている」条件の中には、
    キリンさんを赤くする記述
    下の「当たっていない」条件の中には、
    キリンさんの普段の姿、黄色の記述
    をしています

    color

    それでは、[Run]して色の変化を見てみます

    red

    キリンさんとライオンさんがぶつかると
    キリンさんが真っ赤に染まるのがわかります...

    ライオンさんに「ガブリッ!」とされて、
    キリンさんが真っ赤なち ... ... 「ギャ〜〜〜!!」

    ...

    ライオンさんが離れるといつものキリンさんに戻ります

    ...

    しかしながら、微妙に重なっているときには、
    キリンさんに変化は現れません

    yellow

    それは前回も書いたように、円の当たり判定を使っているからなのですが、
    後々、画像を使用したときにうまくいくようにしたいと思います

    こんな風に...

    image

    ということで、長くなりましたが、
    ようやく当たり判定を実装することができ、
    キリンさんに生きるか死ぬかの
    大きな危険が迫ってくることになりました

    キリンさんがじっとしてると何も起こらないですけどね...

    ...

    さてさて次回は、
    もう少しゲームらしさを高める記述をしてまいります

    それでは、また!







    コメント
    コメントする








       
    この記事のトラックバックURL
    トラックバック

    Calendar
    S M T W T F S
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    30      
    << June 2019 >>
    My Apps
    有料アプリ

    無料アプリ

    Selected entries
    Categories
    AdSense
    Sponsored Links
    Archives
    Recent comment
    Links
    Profile
    Search this site.
    Others
    Mobile
    qrcode
    powered
    無料ブログ作成サービス JUGEM