Game Kit - iPhone

23,971 views

Published on

Published in: Technology, News & Politics
2 Comments
6 Likes
Statistics
Notes
  • Check out Apple's New iPod nano with Multi-Touch Product Review
    http://www.slideshare.net/Zanura/i-pod-nano-multi-touch-review
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

  • elenh eisia kala

    <b>[Comment posted from</b> http://bill.dudney.net/roller/objc/]
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Views
Total views
23,971
On SlideShare
0
From Embeds
0
Number of Embeds
15,717
Actions
Shares
0
Downloads
152
Comments
2
Likes
6
Embeds 0
No embeds

No notes for slide

Game Kit - iPhone

  1. 1. iPhone to iPhone Peer to Peer networking with Game Kit Tuesday, October 13, 2009
  2. 2. Where We Are Headed Tuesday, October 13, 2009
  3. 3. The ‘Game’ One becomes the ‘server’ and creates new disks adds them locally to the view and packages them up and sends them to the client One becomes the ‘client’ listens for new disks, when found creates a new one and adds it locally Tuesday, October 13, 2009
  4. 4. The ‘Game’ User taps on the disks and they spin in 3D and disappear the game sends what was hit to the other peer so both know what has been hit Tuesday, October 13, 2009
  5. 5. How to get there • Connect Peers • Run Game Loop • Process Events Tuesday, October 13, 2009
  6. 6. Application Startup Connect Peers • Start looking for peers Tuesday, October 13, 2009
  7. 7. Application Startup Connect Peers • Peer found and selected Tuesday, October 13, 2009
  8. 8. Application Startup Connect Peers • Shall we play a game? Tuesday, October 13, 2009
  9. 9. Peer Picker Process Anyone There? (A, B) Connect Peers I’m Here (A, B) Display A (B) Display B (A) Client A Client B Choose B (A) Confirm A (B) Conn passed to App (A, B) Send/Receive (A,B) Tuesday, October 13, 2009
  10. 10. Connect Connect Peers Server Mode wait for connection requests Client Mode look for servers Tuesday, October 13, 2009
  11. 11. Connect Connect Peers Peer Mode wait for conn reqs look for servers Tuesday, October 13, 2009
  12. 12. Peer Picker Controller Connect Peers - (void)startPeerPicker { !GKPeerPickerController *picker = [[GKPeerPickerController alloc] init]; !picker.delegate = self; ![picker show]; } Tuesday, October 13, 2009
  13. 13. Peer Picker Controller Connect Peers - (void)startPeerPicker { !GKPeerPickerController *picker = [[GKPeerPickerController alloc] init]; !picker.delegate = self; ![picker show]; } Tuesday, October 13, 2009
  14. 14. Connect Connect Peers Peer Mode wait for conn reqs look for servers Tuesday, October 13, 2009
  15. 15. Connect Connect Peers Peer Mode Peer Picker wait for conn reqs look for servers Bill’s iPod Bill’s 2G iPod Bill’s 1G iPod Tuesday, October 13, 2009
  16. 16. Connect Connect Peers Peer Mode Peer Picker wait for conn reqs look for servers Bill’s iPod Tap Bill’s 2G iPod Bill’s 1G iPod Tuesday, October 13, 2009
  17. 17. Connect Peers Tuesday, October 13, 2009
  18. 18. Connect Bill’s 3G iPhone Bill’s 2G iPod Connect Peers Peer Mode connected Peer Mode wait for conn reqs wait for conn reqs look for servers look for servers Tuesday, October 13, 2009
  19. 19. Session Connect Peers - (GKSession *)peerPickerController:(GKPeerPickerController *)picker sessionForConnectionType:(GKPeerPickerConnectionType)type { return [[[GKSession alloc] initWithSessionID:@"_net.dudney.examples_" displayName:nil sessionMode:GKSessionModePeer] autorelease]; } Tuesday, October 13, 2009
  20. 20. Make the Connection - (void)peerPickerController:(GKPeerPickerController *)picker didConnectPeer:(NSString *)peerId Connect Peers toSession:(GKSession *)session { if([peerId hash] > [session.peerID hash]) { _status = kServerGameStartedClientStatus; } else { _status = kServerGameStartedServerStatus; } self.peerId = peerId; self.gameSession = session; self.gameSession.delegate = self; [self.gameSession setDataReceiveHandler:self withContext:NULL]; [picker dismiss]; picker.delegate = nil; [picker autorelease]; } Tuesday, October 13, 2009
  21. 21. Make the Connection - (void)peerPickerController:(GKPeerPickerController *)picker didConnectPeer:(NSString *)peerId Connect Peers toSession:(GKSession *)session { if([peerId hash] > [session.peerID hash]) { _status = kServerGameStartedClientStatus; } else { _status = kServerGameStartedServerStatus; } self.peerId = peerId; self.gameSession = session; self.gameSession.delegate = self; [self.gameSession setDataReceiveHandler:self withContext:NULL]; [picker dismiss]; picker.delegate = nil; [picker autorelease]; } Tuesday, October 13, 2009
  22. 22. Loose Connection? Connect Peers/Game Loop - (void)session:(GKSession *)session peer:(NSString *)peerID didChangeState:(GKPeerConnectionState)state { if(_status != kServerPickerShownStatus) { if(GKPeerStateDisconnected == state) { // got disconnected from the other peer NSString *message = [NSString stringWithFormat:@"Could not reconnect with %@.", [session displayNameForPeer:peerID]]; UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Lost Connection" message:message delegate:self cancelButtonTitle:@"End Game" otherButtonTitles:nil]; [alert show]; [alert release]; } } } Tuesday, October 13, 2009
  23. 23. Session Connect Peers/Game Loop - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { // index zero is the 'End Game' button, the only one !if(buttonIndex == 0) { !! _status = kServerNotStartedStatus; !} } Tuesday, October 13, 2009
  24. 24. Game Loop - (id) init { Run Game Loop self = [super init]; if (self != nil) { ... self.link = [CADisplayLink displayLinkWithTarget:self selector:@selector(gameLoop)]; self.link.frameInterval = 2; ... } return self; } - (void)start { [self.link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; } Tuesday, October 13, 2009
  25. 25. Game Loop Run Game Loop • Start the peer picker • Send new disk messages Tuesday, October 13, 2009
  26. 26. Start the Picker - (void)gameLoop { _loopId++; Run Game Loop if(kServerNotStartedStatus == _status) { _status = kServerPickerShownStatus; [self startPeerPicker]; } else if(kServerGameStartedServerStatus == _status) { if(0 == (_loopId % _diskFrequency)) { srandom(_loopId); long x = random() % 300 + 10; long y = random() % 460 + 10; CGPoint location = CGPointMake((CGFloat)x, (CGFloat)y); long colorIndex = random() % _colors.count; NSMutableData *data = [NSMutableData dataWithBytes:&location length:sizeof(location)]; [data appendBytes:&colorIndex length:sizeof(colorIndex)]; [self sendMessageTypeID:kServerNewDiskMessageType data:data]; UIColor *color = [_colors objectAtIndex:colorIndex]; [self.delegate diskAtPoint:location withColor:color]; } } } Tuesday, October 13, 2009
  27. 27. Send New Disks - (void)gameLoop { _loopId++; Run Game Loop if(kServerNotStartedStatus == _status) { _status = kServerPickerShownStatus; [self startPeerPicker]; } else if(kServerGameStartedServerStatus == _status) { if(0 == (_loopId % _diskFrequency)) { srandom(_loopId); long x = random() % 300 + 10; long y = random() % 460 + 10; CGPoint location = CGPointMake((CGFloat)x, (CGFloat)y); long colorIndex = random() % _colors.count; NSMutableData *data = [NSMutableData dataWithBytes:&location length:sizeof(location)]; [data appendBytes:&colorIndex length:sizeof(colorIndex)]; [self sendMessageTypeID:kServerNewDiskMessageType data:data]; UIColor *color = [_colors objectAtIndex:colorIndex]; [self.delegate diskAtPoint:location withColor:color]; } } } Tuesday, October 13, 2009
  28. 28. Send New Disks - (void)gameLoop { _loopId++; Run Game Loop if(kServerNotStartedStatus == _status) { _status = kServerPickerShownStatus; [self startPeerPicker]; } else if(kServerGameStartedServerStatus == _status) { if(0 == (_loopId % _diskFrequency)) { srandom(_loopId); long x = random() % 300 + 10; long y = random() % 460 + 10; CGPoint location = CGPointMake((CGFloat)x, (CGFloat)y); long colorIndex = random() % _colors.count; NSMutableData *data = [NSMutableData dataWithBytes:&location length:sizeof(location)]; [data appendBytes:&colorIndex length:sizeof(colorIndex)]; [self sendMessageTypeID:kServerNewDiskMessageType data:data]; UIColor *color = [_colors objectAtIndex:colorIndex]; [self.delegate diskAtPoint:location withColor:color]; } } } Tuesday, October 13, 2009
  29. 29. Send New Disks - (void)gameLoop { _loopId++; Run Game Loop if(kServerNotStartedStatus == _status) { _status = kServerPickerShownStatus; [self startPeerPicker]; } else if(kServerGameStartedServerStatus == _status) { if(0 == (_loopId % _diskFrequency)) { srandom(_loopId); long x = random() % 300 + 10; long y = random() % 460 + 10; CGPoint location = CGPointMake((CGFloat)x, (CGFloat)y); long colorIndex = random() % _colors.count; NSMutableData *data = [NSMutableData dataWithBytes:&location length:sizeof(location)]; [data appendBytes:&colorIndex length:sizeof(colorIndex)]; [self sendMessageTypeID:kServerNewDiskMessageType data:data]; UIColor *color = [_colors objectAtIndex:colorIndex]; [self.delegate diskAtPoint:location withColor:color]; } } } Tuesday, October 13, 2009
  30. 30. Send New Disks - (void)gameLoop { _loopId++; Run Game Loop if(kServerNotStartedStatus == _status) { _status = kServerPickerShownStatus; [self startPeerPicker]; } else if(kServerGameStartedServerStatus == _status) { if(0 == (_loopId % _diskFrequency)) { srandom(_loopId); long x = random() % 300 + 10; long y = random() % 460 + 10; CGPoint location = CGPointMake((CGFloat)x, (CGFloat)y); long colorIndex = random() % _colors.count; NSMutableData *data = [NSMutableData dataWithBytes:&location length:sizeof(location)]; [data appendBytes:&colorIndex length:sizeof(colorIndex)]; [self sendMessageTypeID:kServerNewDiskMessageType data:data]; UIColor *color = [_colors objectAtIndex:colorIndex]; [self.delegate diskAtPoint:location withColor:color]; } } } Tuesday, October 13, 2009
  31. 31. Send New Disks - (void)gameLoop { _loopId++; Run Game Loop if(kServerNotStartedStatus == _status) { _status = kServerPickerShownStatus; [self startPeerPicker]; } else if(kServerGameStartedServerStatus == _status) { if(0 == (_loopId % _diskFrequency)) { srandom(_loopId); long x = random() % 300 + 10; long y = random() % 460 + 10; CGPoint location = CGPointMake((CGFloat)x, (CGFloat)y); long colorIndex = random() % _colors.count; NSMutableData *data = [NSMutableData dataWithBytes:&location length:sizeof(location)]; [data appendBytes:&colorIndex length:sizeof(colorIndex)]; [self sendMessageTypeID:kServerNewDiskMessageType data:data]; UIColor *color = [_colors objectAtIndex:colorIndex]; [self.delegate diskAtPoint:location withColor:color]; } } } Tuesday, October 13, 2009
  32. 32. Send New Disks - (void)gameLoop { _loopId++; Run Game Loop if(kServerNotStartedStatus == _status) { _status = kServerPickerShownStatus; [self startPeerPicker]; } else if(kServerGameStartedServerStatus == _status) { if(0 == (_loopId % _diskFrequency)) { srandom(_loopId); long x = random() % 300 + 10; long y = random() % 460 + 10; CGPoint location = CGPointMake((CGFloat)x, (CGFloat)y); long colorIndex = random() % _colors.count; NSMutableData *data = [NSMutableData dataWithBytes:&location length:sizeof(location)]; [data appendBytes:&colorIndex length:sizeof(colorIndex)]; [self sendMessageTypeID:kServerNewDiskMessageType data:data]; UIColor *color = [_colors objectAtIndex:colorIndex]; [self.delegate diskAtPoint:location withColor:color]; } } } Tuesday, October 13, 2009
  33. 33. Send New Disks - (void)gameLoop { _loopId++; Run Game Loop if(kServerNotStartedStatus == _status) { _status = kServerPickerShownStatus; [self startPeerPicker]; } else if(kServerGameStartedServerStatus == _status) { if(0 == (_loopId % _diskFrequency)) { srandom(_loopId); long x = random() % 300 + 10; long y = random() % 460 + 10; CGPoint location = CGPointMake((CGFloat)x, (CGFloat)y); long colorIndex = random() % _colors.count; NSMutableData *data = [NSMutableData dataWithBytes:&location length:sizeof(location)]; [data appendBytes:&colorIndex length:sizeof(colorIndex)]; [self sendMessageTypeID:kServerNewDiskMessageType data:data]; UIColor *color = [_colors objectAtIndex:colorIndex]; [self.delegate diskAtPoint:location withColor:color]; } } } Tuesday, October 13, 2009
  34. 34. Send Data Run Game Loop - (void)sendMessageTypeID:(ServerPacketTypeId)packetTypeId data:(NSData *)data { NSMutableData *sentData = [NSMutableData data]; [sentData appendBytes:&packetTypeId length:sizeof(packetTypeId)]; [sentData appendData:data]; [self.gameSession sendData:sentData toPeers:[NSArray arrayWithObject:self.peerId] withDataMode:GKSendDataUnreliable error:nil]; } Tuesday, October 13, 2009
  35. 35. Receive Data - (void) receiveData:(NSData *)data fromPeer:(NSString *)peer Run Game Loop inSession:(GKSession *)session context:(void *)context { ServerPacketTypeId typeId; [data getBytes:&typeId length:sizeof(typeId)]; if(kServerNewDiskMessageType == typeId) { CGPoint point; NSRange range; range.location = sizeof(typeId); range.length = sizeof(point); [data getBytes:&point range:range]; NSUInteger colorIndex = 0; range.location = range.location + range.length; range.length = sizeof(colorIndex); [data getBytes:&colorIndex range:range]; [self.delegate diskAtPoint:point withColor:[_colors objectAtIndex:colorIndex]]; } else if(kServerSmashMessageType == typeId) { ... } } Tuesday, October 13, 2009
  36. 36. Messages new disk Client A {color, location} Client B Tuesday, October 13, 2009
  37. 37. Messages new disk new disk Client A {color, location} Client B Tuesday, October 13, 2009
  38. 38. New Disk Layer - (void)displayDiskAt:(CGPoint)point ofColor:(UIColor *)color { DiskLayer *layer = [DiskLayer layerWithColor:color]; layer.position = point; [self.layer addSublayer:layer]; [self performSelector:@selector(disapearLayer:) withObject:layer afterDelay:0.1f]; } - (void)disapearLayer:(CALayer *)layer { layer.opacity = 0.0f; } Tuesday, October 13, 2009
  39. 39. New Disk Layer - (id) initWithColor:(UIColor *)color { self = [super init]; if (self != nil) { CGRect frame = CGRectMake(0.0f, 0.0f, 40.0f, 40.0f); self.frame = frame; self.diskLayer = [CAShapeLayer layer]; self.diskLayer.frame = frame; CGPathRef path = [self newCirclePath]; self.diskLayer.path = path; self.diskLayer.fillColor = [color CGColor]; self.diskLayer.strokeColor = [color CGColor]; CFRelease(path); CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"opacity"]; animation.duration = 4.9f; animation.delegate = self; self.actions = [NSDictionary dictionaryWithObject:animation forKey:@"opacity"]; [self addSublayer:self.diskLayer]; _smashed = NO; } return self; } Tuesday, October 13, 2009
  40. 40. Smash A Disk tap Client A Tuesday, October 13, 2009
  41. 41. Smash A Disk tap Client A {smash location} Client B Tuesday, October 13, 2009
  42. 42. Process Events - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { CGPoint point = [[touches anyObject] locationInView:self]; CGPoint location = [self.layer convertPoint:point toLayer:self.layer.superlayer]; CALayer *layer = [self.layer hitTest:location]; if(layer != self.layer) { [self.delegate diskSmashedAt:location]; [(DiskLayer *)layer smash]; } } Tuesday, October 13, 2009
  43. 43. Smashing Disks - (void)diskSmashedAt:(CGPoint)point { [self.server sendSmashAtPoint:point]; } Tuesday, October 13, 2009
  44. 44. Sending Smashes - (void)sendSmashAtPoint:(CGPoint)point { NSData *data = [NSData dataWithBytes:&point length:sizeof(point)]; [self sendMessageTypeID:kServerSmashMessageType data:data]; } Tuesday, October 13, 2009
  45. 45. Receive Smash - (void) receiveData:(NSData *)data fromPeer:(NSString *)peer inSession:(GKSession *)session context:(void *)context { ... } else if(kServerSmashMessageType == typeId) { CGPoint point; NSRange range; range.location = sizeof(typeId); range.length = sizeof(point); [data getBytes:&point range:range]; [self.delegate remoteDiskSmashedAtPoint:point]; } } Tuesday, October 13, 2009
  46. 46. Remote Smash Forward - (void)remoteDiskSmashedAtPoint:(CGPoint)point { DiskSmashView *smashView = (DiskSmashView *)self.view; [smashView remoteSmash:point]; } Tuesday, October 13, 2009
  47. 47. Remote Smash - (void)remoteSmash:(CGPoint)point { CALayer *layer = [self.layer hitTest:point]; if(layer != self.layer) { [(DiskLayer *)layer smash]; } } Tuesday, October 13, 2009
  48. 48. Conclusion • Getting Connected is easy! • Sending Data is easy • Designing a good game, not so much. Tuesday, October 13, 2009
  49. 49. Thanks! Pragmatic iPhone Studio PragProg.com discount code voices_bill_dudney_10 Tuesday, October 13, 2009

×