cocos2dの使い方【実践】② 〜スプライトで簡単なゲーム 2/2〜

前回の続きから進めていきます。

とりあえず初めのサンプルコードとしてこちらをどうぞー


今回はとりあえず遊べるレベルまでにもっていきますが,

前回との仕様の変更が1点あります。

Spriteで square[20] と20個作ったのですが,これを再利用するため

if(squareNextNumber >= 20){
     squareNextNumber = 0;
}

としていたところをやめてsquareNextNumberが20までいってしまったら次は作らない事にします。
よって

- (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
   .
   .
   .

    //繰り返し使わないで20個落としたらもうおとせないようにする
    if (squareNextNumber < 20){
        square[squareNextNumber].visible = NO;
        //sakuraの位置をタッチした位置にする
        square[squareNextNumber].position = location;
    }
}

//タッチして動いている時
- (void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
  .
  .
  .

    if (squareNextNumber < 20){
        square[squareNextNumber].position = location;
    }
}

//タッチし終わった(離した)時
- (void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
  .
  .
  .

    if (squareNextNumber < 20){
        square[squareNextNumber].position = location;
        //sakuraを表示
        square[squareNextNumber].visible = YES;
        squareNextNumber++;
        gameScore++;
    }
}

といった様に20未満でしか処理をしない様にします。

そうしたら今回の話に入ります。まずせっかくtimerをつくったので時間をつくり表示しましょうということです。

//timerLabel
static CCLabelTTF *timer;
static float gameTime = 20;

を定義して,初期化処理,

//timerLabel
        timer = [CCLabelTTF labelWithString:@"TIME : 20" fontName:@"Cochin" fontSize:32];
        timer.anchorPoint = ccp(0.f, 2.f);
        timer.position = ccp(0, screenSize.height);
        [self addChild:timer z:1];

あとはtimerにて更新していく

- (void)timer:(ccTime)dt
{
   .
   .
   .
   
    //毎回たった時間を引いていく
    gameTime -= dt;
    //もし時間が0以下になったら
    if (gameTime <= 0) {
        //きれいに0にして
        gameTime = 0;
        //タイマーをとめる
        [self unschedule:@selector(timer:)];
    }
    //時間を更新していく
    NSString *timeString = [[NSString alloc] initWithFormat:@"TIME : %f", gameTime];
	[timer setString: [NSString stringWithFormat:@"%@",timeString]];
}

これで時間が減っていくのがわかると思います。

そして時間が0になったらGAMEOVERになることを想定しているので, gameoverLabelをつくっていきます。
今までと同じ様に

定義

static CCLabelTTF *gameover;

初期化

//gameoverLabel
        gameover = [CCLabelTTF labelWithString:@"GAME OVER" fontName:@"Cochin" fontSize:48];
        gameover.position = ccp(screenSize.width/2, screenSize.height/2);
        //まだ表示しない
        gameover.visible = NO;
        [self addChild:gameover z:1];

実行(表示)

- (void)timer:(ccTime)dt
{
    .
    .
    .

    if (gameTime <= 0) {
        //きれいに0にして
        gameTime = 0;
        //gameoverを表示
        gameover.visible = YES;
        //タイマーをとめる(GAMEOVER)
        [self unschedule:@selector(timer:)];
    }

    .
    .    
    .
}

といった具合で慣れてきたらどんどん自分でやってみましょう。

ここまでいったら実際実行してあとやる事を探しておきます。

のこりタスク
・時間外はsquareSpriteをつくれないようにする
・重力をつける
・当たり判定をつくる ←これが少し難しい

ではのこりタスクを仕上げます。

が,先にサンプルコードをここにあげておきます。



・時間外はsquareSpriteをつくれないようにする

まずこちらですが最初の修正の部分に付け加えて次の番号が20番未満かゲームオーバーではないかという判定にしたいと思います

if (squareNextNumber < 20){
}
 ↓
if (squareNextNumber < 20 && gameover.visible == NO){
}

という風に3つとも変更すれば大丈夫です。



・重力をつける

これは最初はどうすんだとか思うかもしれませんが,今まで定速だったのでその速度だった部分を加速させればよいのです。

ということでまず速度を新たに速度を定義しましょう

//速度
static float velocity[20];

そして速度の部分に入れるまえに加速処理を行います。

- (void)timer:(ccTime)dt
{
    for (int i = 0; i < squareSum; i++) {
        //もし見えていたら
        if (square[i].visible)
        {
            //下までいっていなかったら
            if (square[i].position.y > 0){
                //加速
                velocity[i] += 1000*dt;
                //落下
                square[i].position = ccp(square[i].position.x, square[i].position.y - velocity[i]*dt);
            }else{
                //下でとまる
                square[i].position = ccp(square[i].position.x, 0);
            }
        }
    }

    .
    .
    .
}

アプリでよく見る重力があるかのように落ちるものが出来たと思います。



・当たり判定をつくる

このあたり判定ですが自分のスプライト以外の19個と当たっていないのか確認する必要があります。

- (void)timer:(ccTime)dt
{
    for (int i = 0; i < squareSum; i++) {
        //もし見えていたら
        if (square[i].visible)
        {
            .
            .
            .
            //当たり判定処理
            for (int j = 0; j < squareSum; j++) {
                if (square[j].visible && i!=j){
                    float dx = square[i].position.x - square[j].position.x;
                    float dy = square[i].position.y - square[j].position.y;
                    float scale = square[i].scale;
                    if((dx < square[i].contentSize.width*scale && dx > -square[i].contentSize.width*scale) && (dy < square[i].contentSize.height*scale && dy > -square[i].contentSize.height*scale)){
                        //gameoverを表示
                        gameover.visible = YES;
                        //タイマーをとめる(GAMEOVER)
                        [self unschedule:@selector(timer:)];
                    }
                }
            }
        }
    } 

   .
   .
   .
}

これは四角形だったので少し大変でしたが座標と座標の距離だけで判断したいのであれば

float distance = ccpDistance(square[i].position, square[j].position);

という風にとる事も出来ます。

ここまででそれなりに遊べる様になった気がしますが

いろいろ修正していくといい点はたくさんあります。

どんな事があるかというと

・連打できない(手前のが落ちてから)にする
・上の方からしか落とせなくする
・跳ねる様にする
・時間を整数で表示する
・その他速さ大きさの調節 ←これは重要
など

いろいろゲームらしく制限を増やしていくと面白くなりますがややこしくなりすぎるのも厳禁です。

cocos2dの使い方は続きますが一回一つのゲームアプリとして完成させたい。
なので次回からソーシャルSDKのPANKIAの導入の仕方,使い方を説明していきます