iPhone SDK 3.0 - Playing with Game Kit - Part 1

I finally got some time to play with GameKit today and it is pretty simple to establish connectivity between two devices over bluetooth.

All you need to understand are 2 classes.

GKPeerPickerController and GKSession

You could create your own interface for establishing connection between 2 devices, but Apple provides a nice interface via the GKPeerPickerController

As with the Map Kit and other frameworks supported by Apple, they use the powerful delegate pattern to accomplish communication between the devices.

As such there are two delegates you need to make yourself familiar with. They are

GKPeerPickerControllerDelegate and GKSessionDelegate

Just create a simple View based project, Add Game Kit framework to your project, then Just go to your controller and implement the 2 delegates from above. Here is my code, My project is named GameKitTest, thus the name of the file GameKitTestController

The data transfer between the clients happens using NSData objects. For purposes of this discussion you just need to know how to convert back and forth from NSData to NSString. Here is a quick snippet

From NSString to NSData:


NSString* aStr;
aStr = [[NSString alloc] initWithData:aData encoding:NSASCIIStringEncoding];

From NSData to NSString:


NSData* aData;
aData = [aStr dataUsingEncoding: NSASCIIStringEncoding];

OK, Now with our further adieu here is the code

Header File



//
//  GameKitTestViewController.h
//  GameKitTest
//
//  Created by Gavi Narra on 6/16/09.
//  Copyright ObjectGraph LLC 2009. All rights reserved.
//

#import 
#import 

@interface GameKitTestViewController : UIViewController {
	GKPeerPickerController *mPicker;
	GKSession *mSession;
	IBOutlet UITextField *mTextField;
	IBOutlet UITextView *mTextView;
	NSMutableArray *mPeers;
}

-(IBAction) connectClicked:(id)sender;
-(IBAction) sendData:(id)sender;
@property (retain) GKSession *mSession;

@end


Main File


//
//  GameKitTestViewController.m
//  GameKitTest
//
//  Created by Gavi Narra on 6/16/09.
//  Copyright ObjectGraph LLC 2009. All rights reserved.
//

#import "GameKitTestViewController.h"

@implementation GameKitTestViewController

@synthesize mSession;


/*
// The designated initializer. Override to perform setup that is required before the view is loaded.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
        // Custom initialization
    }
    return self;
}
*/

/*
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView {
}
*/



// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
    [super viewDidLoad];

	mPicker=[[GKPeerPickerController alloc] init];
	mPicker.delegate=self;
	mPicker.connectionTypesMask = GKPeerPickerConnectionTypeNearby | GKPeerPickerConnectionTypeOnline;
	mPeers=[[NSMutableArray alloc] init];
}





/*
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
*/

- (void)didReceiveMemoryWarning {
	// Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];
	
	// Release any cached data, images, etc that aren't in use.
}

- (void)viewDidUnload {
	// Release any retained subviews of the main view.
	// e.g. self.myOutlet = nil;
}


- (void)dealloc {
	[mPeers release];
    [super dealloc];
}

#pragma mark Events

-(IBAction) connectClicked:(id)sender{
//Show the connector
	[mPicker show];
}

#pragma mark PeerPickerControllerDelegate stuff

/* Notifies delegate that a connection type was chosen by the user.
 */
- (void)peerPickerController:(GKPeerPickerController *)picker didSelectConnectionType:(GKPeerPickerConnectionType)type{
	if (type == GKPeerPickerConnectionTypeOnline) {
        picker.delegate = nil;
        [picker dismiss];
        [picker autorelease];
		// Implement your own internet user interface here.
    }
}

/* Notifies delegate that the connection type is requesting a GKSession object.
 
 You should return a valid GKSession object for use by the picker. If this method is not implemented or returns 'nil', a default GKSession is created on the delegate's behalf.
 */
- (GKSession *)peerPickerController:(GKPeerPickerController *)picker sessionForConnectionType:(GKPeerPickerConnectionType)type{
	
	//UIApplication *app=[UIApplication sharedApplication];
	NSString *txt=mTextField.text;
	
	GKSession* session = [[GKSession alloc] initWithSessionID:@"gavi" displayName:txt sessionMode:GKSessionModePeer];
    [session autorelease];
    return session;
}

/* Notifies delegate that the peer was connected to a GKSession.
 */
- (void)peerPickerController:(GKPeerPickerController *)picker didConnectPeer:(NSString *)peerID toSession:(GKSession *)session{

	NSLog(@"Connected from %@",peerID);
	
	// Use a retaining property to take ownership of the session.
    self.mSession = session;
	// Assumes our object will also become the session's delegate.
    session.delegate = self;
    [session setDataReceiveHandler: self withContext:nil];
	// Remove the picker.
    picker.delegate = nil;
    [picker dismiss];
    [picker autorelease];
	// Start your game.
}

-(IBAction) sendData:(id)sender{
	
	NSString *str=@"Hello SaiBaba";
	[mSession sendData:[str dataUsingEncoding: NSASCIIStringEncoding] toPeers:mPeers withDataMode:GKSendDataReliable error:nil];
}

- (void) receiveData:(NSData *)data fromPeer:(NSString *)peer inSession: (GKSession *)session context:(void *)context
{
    // Read the bytes in data and perform an application-specific action.
	
	NSString* aStr;
	aStr = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
	NSLog(@"Received Data from %@",peer);
	mTextView.text=aStr;
	

}

/* Notifies delegate that the user cancelled the picker.
 */
- (void)peerPickerControllerDidCancel:(GKPeerPickerController *)picker{

}

#pragma mark GameSessionDelegate stuff

/* Indicates a state change for the given peer.
 */
- (void)session:(GKSession *)session peer:(NSString *)peerID didChangeState:(GKPeerConnectionState)state{
	
	switch (state)
    {
        case GKPeerStateConnected:
		{
			NSString *str=[NSString stringWithFormat:@"%@\n%@%@",mTextView.text,@"Connected from pier ",peerID];
			mTextView.text= str;
			NSLog(str);
			[mPeers addObject:peerID];
			break;
		}
        case GKPeerStateDisconnected:
		{
			[mPeers removeObject:peerID];
			
			NSString *str=[NSString stringWithFormat:@"%@\n%@%@",mTextView.text,@"DisConnected from pier ",peerID];
			mTextView.text= str;
			NSLog(str);
			break;
		}
    }
}

@end

By: gavi on: