How To Make a Simple Playing Card Game with Multiplayer and Bluetooth, Part 1

This is a post by iOS Tutorial Team member Matthijs Hollemans, an experienced iOS developer and designer. You can find him on Google+ and Twitter. Card games are quite popular on the App Store – over 2,500 apps and counting – so it’s about time that raywenderlich.com shows you how to make one! In addition, […] By Matthijs Hollemans.

Leave a rating/review
Save for later
Share
You are currently viewing page 5 of 5 of this article. Click here to view the first page.

The MatchingmakingClient

Add a new Objective-C class to the project that extends NSObject, name it MatchmakingClient, and put it in the Networking group. Replace the contents of MatchmakingClient.h with:

@interface MatchmakingClient : NSObject <GKSessionDelegate>

@property (nonatomic, strong, readonly) NSArray *availableServers;
@property (nonatomic, strong, readonly) GKSession *session;

- (void)startSearchingForServersWithSessionID:(NSString *)sessionID;

@end

This somewhat mirrors what the MatchmakingServer did, but instead of connected clients, it has a list of available servers. Replace the contents of MatchmakingClient.m with:

#import "MatchmakingClient.h"

@implementation MatchmakingClient
{
	NSMutableArray *_availableServers;
}

@synthesize session = _session;

- (void)startSearchingForServersWithSessionID:(NSString *)sessionID
{
	_availableServers = [NSMutableArray arrayWithCapacity:10];

	_session = [[GKSession alloc] initWithSessionID:sessionID displayName:nil sessionMode:GKSessionModeClient];
	_session.delegate = self;
	_session.available = YES;
}

- (NSArray *)availableServers
{
	return _availableServers;
}

#pragma mark - GKSessionDelegate

- (void)session:(GKSession *)session peer:(NSString *)peerID didChangeState:(GKPeerConnectionState)state
{
	#ifdef DEBUG
	NSLog(@"MatchmakingClient: peer %@ changed state %d", peerID, state);
	#endif
}

- (void)session:(GKSession *)session didReceiveConnectionRequestFromPeer:(NSString *)peerID
{
	#ifdef DEBUG
	NSLog(@"MatchmakingClient: connection request from peer %@", peerID);
	#endif
}

- (void)session:(GKSession *)session connectionWithPeerFailed:(NSString *)peerID withError:(NSError *)error
{
	#ifdef DEBUG
	NSLog(@"MatchmakingClient: connection with peer %@ failed %@", peerID, error);
	#endif
}

- (void)session:(GKSession *)session didFailWithError:(NSError *)error
{
	#ifdef DEBUG
	NSLog(@"MatchmakingClient: session failed %@", error);
	#endif
}

@end

Again, this is a very barebones version of this class, and you’ll fill it out as you go along. Note that you now create the GKSession object in mode GKSessionModeClient, so that it will start looking for available servers (but not broadcast a service of its own).

Now integrate this new class into the JoinViewController, so you can start connecting servers with clients. First, add an import to JoinViewController.h:

#import "MatchmakingClient.h"

Then add an instance variable in JoinViewController.m:

@implementation JoinViewController
{
	MatchmakingClient *_matchmakingClient;
}

And get the whole thing started in viewDidAppear:

- (void)viewDidAppear:(BOOL)animated
{
	[super viewDidAppear:animated];

	if (_matchmakingClient == nil)
	{
		_matchmakingClient = [[MatchmakingClient alloc] init];
		[_matchmakingClient startSearchingForServersWithSessionID:SESSION_ID];

		self.nameTextField.placeholder = _matchmakingClient.session.displayName;
		[self.tableView reloadData];
	}
}

At this point, you can start testing. Make sure you either have two (or more!) devices that all have Bluetooth enabled, or put your device on the local Wi-Fi network and run the app on both the Simulator and your device. On one of the devices, tap Host Game, and on the other tap Join Game.

The app doesn’t show anything happening on the screen, but you should see a fair amount of debug output from Game Kit itself in Xcode’s Debug Pane.

The server will say things like:

Snap[3810:707] BTM: attaching to BTServer
Snap[3810:707] BTM: posting notification BluetoothAvailabilityChangedNotification
Snap[3810:707] BTM: received BT_LOCAL_DEVICE_CONNECTABILITY_CHANGED event
Snap[3810:707] BTM: posting notification BluetoothConnectabilityChangedNotification

These are messages from Game Kit itself. The client may also show messages from Game Kit, but it should say:

Snap[94530:1bb03] MatchmakingClient: peer 663723729 changed state 0

This message comes from the GKSessionDelegate method session:peer:didChangeState: in your MatchmakingClient class. It tells us that the peer with ID “663723729” has become available. In other words, the client has detected the presence of the server.

Note: The peer ID is an internal number used by Game Kit to identify the different devices that are partaking in the session. Every time you run the app, your peers will get different IDs. You’ll be using these peer IDs quite a bit later on.

If you have two or more devices, you can have more than one function as a server. For the purposes of this tutorial, a client can connect to only one of them, but it should detect them both. Try it out!

Where to Go From Here?

Here is a sample project with all of the code from the tutorial so far.

Congratulations – you now have a good-looking and smoothly animated main menu for the app, and the basic implementation of the host and join game screens. In addition, you have implemented broadcasting and detecting servers with GameKit and Bonjour!

This is great, but obviously you want to show the detected servers onscreen so the user can select which server to join. That is the topic of Part 2 of this epic series!

If you have any questions or comments about this part of the series, please join the forum discussion below!


This is a post by iOS Tutorial Team member Matthijs Hollemans, an experienced iOS developer and designer. You can find him on and Twitter.

Contributors

Over 300 content creators. Join our team.