これまでのiPhoneには、端末同士が直接通信する方法はありませんでした。対戦ゲームや通信を行うには同一の無線LANに接続するか、3G回線でインターネットサーバを経由して通信するかのどちらかの方法でiPhone同士の通信を行うしかありません。
ノートPCが多い日本では無線LANは一般的ですが、世界的には決して多くなく、無線LANスポットを利用できる場所ということだと、結局家の中でしか対戦ができません。また、3G回線でサーバ経由で通信する方式では、場所は問いませんが、通信速度が遅いし、パケット料金が定額制の国以外では安心して使うことができません。
iPhone OS 3.0からBluetooth通信でアドホックに通信できるようになったため、iPhoneはさらにゲームプラットフォームとしての可能性が大きく広がりました。
最後に、iPhone OS 3.0で新たに追加されたAPIの1つ「Game Kit」を使用して、簡単に2台のiPhone(または、iPod touch)間をBluetoothで通信する方法を、サンプルコードを交えて説明していきたいと思います。
まず大きくステップ分けをすると、下記2つのステップにてiPhone(または、iPod touch)間で通信可能です(下記リストはインデックスになっています)。
Bluetooth以外には、インターネット接続「GKPeerPickerConnectionTypeOnline」を追加することが可能です。
picker.connectionTypeMask = GKPeerPickerConnectionTypeNearby |
                                        GKPeerPickerConnectionTypeOnline
このデリゲートメソッドは、ステップ【1-4】で表示されたダイアログで確立されたセッション情報を受け取るためのものです。
    -(void) startPicker{
        //Step1-1
        GKPeerPickerController* picker;
        Picker=[[GKPeerPickerController alloc] init];
        //Step1-2
        Picker.delegate=self;
        //Step1-3
        Picker.connectionTypesMask=GKPeerPickerConnectionTypeNearby;
        //Step1-4
        [picker show];
    }
 
    //Step1-5
    -(void)peerPickerController:(GKPeerPickerController*)picker didConnectPeer:(NSString *)peerID toSession:(GKSession *)session{
 
        self.gameSession=session;
        session.delegate=self;
        [session setDataReceiveHandler:self withContext:nil];
 
        //pickerの削除
        picker.delegate=nil;
        [picker dismiss];
        [picker autorelease];
 
          //ゲーム開始などのデータやりとりを開始する(省略)
    }
このデリゲートメソッドは、セッションの状態変更を感知するために実装します。
    - (void)session:(GKSession *)session peer:(NSString *)peerID didChangeState:(GKPeerConnectionState)connstate {
        switch (connstate) {
            case GKPeerStateAvailable:
                DEBUG_NSLog(@"%@ を見つけた!",peerID);
                break;
            case GKPeerStateUnavailable:
                DEBUG_NSLog(@"%@ を見失った!",peerID);
                break;
            case GKPeerStateConnected:
                DEBUG_NSLog(@"%@ が接続した!",peerID);
                       gamePeerId=peerID;
                break;
            case GKPeerStateDisconnected:
                DEBUG_NSLog(@"%@ が切断された!",peerID);
                break;
            case GKPeerStateConnecting:
                DEBUG_NSLog(@"%@ が接続中!",peerID);
                break;
            default:
                break;
        }
    }
    -(void) SendDataToPeers:(NSData *) data
    {
        [self.gameSession sendData:data
            toPeers:[NSArray arrayWithObject:gamePeerId]
             withDataMode:GKSendDataReliable error:nil];
    }
    -(void)receiveData:(NSData *)data fromPeer:(NSString *)peer inSession:(GKSession *)session context:(void *)context
    {
        //データのバイトを読み取り、アプリ固有の処理を実装する
    }
コメントの「データのバイトを読み取り、アプリ固有の処理を実装する」というのは、ゲームの場合は、あまり処理に時間がかかってしまうと、処理落ちなどしてしまうのでお勧めません。しかし、そのほか単純にデータを受信する場合などは、NSDictionaryをNSKeyedArchiverを使用してアーカイブ/アンアーカイブして送受信する方法も取れるということです。
    -(void)sessionCleanUp{
        [self.gameSession disconnectFromAllPeers];
        self.gameSession.available=NO;
        [self.gameSession setDataReceiveHandler:nil withContext:nil];
        self.gameSession.delegate=nil;
        self.gameSession=nil;
    }
今回は、セッションの確立をGKPeerPickerControllerを利用して行いました。この場合のセッションモードはPeerモードです。セッションモードには、3タイプあり、その1つがPeerモードです。
Peerモードの欠点は、ほかのiPhoneとのセッションを確立するまでかなりの時間を要することです。GKPeerPickerControllerを利用できるのはPeerモードだけなので、ダイアログ表示の手間を考えたら許容される部分なのかもしれません。しかし、GKPeerPickerControllerで表示されるダイアログ関連の部分を独自実装してしまえば、Peerモードより、断然セッションの確立が速い、Server/Clientモードでの実装を私はお勧めします。
その辺りは、GKSessionを調べていけば分かるかと思いますので、ぜひお試しあれ!
次回は、いよいよ最終回! 番外編として、「ここが大変だよiPhoneアプリ開発におけるOpenGL ES」というテーマでお送りしたいと思います。お楽しみに。
佐々木義一郎
初仕事から約8年、一貫してJava+Oracleなどのオープン系技術者として従事。大小さまざまな開発プロジェクトを経験し、現在はコニットにて念願の自社製品開発に奮起。手掛けたアプリ、サムライチェス、メロディベル、おならアプリ「メロディっ屁」、TapNextも販売中。
Copyright © ITmedia, Inc. All Rights Reserved.