[iOS 10] SpriteKit の Tile Map をつかってミニゲームをつくってみた #3

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

前回の続きです。
フリックした時にエンペラーペンギンが移動する処理を作ります。
2羽のペンギンが出会ったら、ランデブー画像を表示してクリアです。

フリック移動処理とランデブー処理をつくる

GameScene.m を以下のようにメソッドを追加します。

- (void)swipe:(CMSSwipe)swipe {
    [self move:swipe];
}

-(void)move:(CMSSwipe)swipe {
    BOOL rendezvousFlg = NO;
    
    // 移動先のタイルインデックスを取得する。
    CGPoint toIndex = _emperorIndex;
    while (true) {
        CGPoint hitToIndex = [self moveIndex:toIndex swipe:swipe];
        
        if (_gentooIndex.x == hitToIndex.x && _gentooIndex.y == hitToIndex.y) {
            toIndex = hitToIndex;
            rendezvousFlg = YES;
            break;
        }
        
        SKTileDefinition *tileDefinition = [_tileMap tileDefinitionAtColumn:hitToIndex.x
                                                                        row:hitToIndex.y];
        if ([tileDefinition.name isEqualToString:@"light_gray"]
            || [tileDefinition.name isEqualToString:@"dark_gray"]) {
            break;
        }
        toIndex = hitToIndex;
    }
    
    // 移動距離を取得する。
    CGPoint fromIndex = _emperorIndex;
    int distance = abs((int)fromIndex.x - (int)toIndex.x) + abs((int)fromIndex.y - (int)toIndex.y);
    
    // 移動しない場合は処理終了。
    if (distance == 0) {
        return;
    }
    
    // 移動先の座標を取得する。
    CGPoint toPoint = [self convertPlayerPoint:toIndex];
    
    // 移動アクションを実行する。
    [_emperor removeAllActions];
    [_emperor runAction:[SKAction moveTo:toPoint duration:0.1 * distance]
            completion:^{
                // ランデブーしたときはクリア処理を行う。
                if (rendezvousFlg) {
                    [self rendezvous];
                }
            }];
    
    // エンペラーペンギンのタイルインデックスを更新する。
    _emperorIndex = toIndex;
}

-(CGPoint)moveIndex:(CGPoint)index swipe:(CMSSwipe)swipe {
    if (swipe == CMSSwipeUp) {
        return CGPointMake(index.x, index.y + 1);
    }
    
    if (swipe == CMSSwipeDown) {
        return CGPointMake(index.x, index.y - 1);
    }
    
    if (swipe == CMSSwipeLeft) {
        return CGPointMake(index.x - 1, index.y);
    }
    
    if (swipe == CMSSwipeRight) {
        return CGPointMake(index.x + 1, index.y);
    }
    return index;
}

-(void) rendezvous {
    // エンペラーペンギンとジェンツーペンギンを非表示にする。
    _emperor.hidden = YES;
    _gentoo.hidden = YES;
    
    // ランデブー画像を表示する。
    _rendezvous.hidden = NO;
    
    // ちょっとだけ拡大縮小アクションを行う。
    NSArray *actions = @[[SKAction scaleBy:1.4f duration:0.1f],
                         [SKAction scaleBy:1.0f / 1.4f duration:0.2f]];
    [_rendezvous runAction:[SKAction sequence:actions]];
}

SKTileMapNodetileDefinitionAtColumn:row: メソッドでタイル情報を取得することができます。今回はそのタイル情報から障害物か壁か何もないところかを判別しています。

うごかしてみる

では、動かしてみます。以下のようにフリックしていきます。

sk_tile_game_03_01

すると、、

sk_tile_game_03_02

ランデブーしました!
ひとまず、くぎりの良いところまでできました。

ゲームのコアなところがわずかに出来ましたが、まだまだ完成度が低いです。。
いろんなところを肉付けしていければ完成に近づけるかと思いますが、このつづきはまたいつか。。
ではでは。