SlideShare une entreprise Scribd logo
1  sur  49
Télécharger pour lire hors ligne
iPhone to iPhone
                            Peer to Peer networking with Game Kit




Tuesday, October 13, 2009
Where We Are Headed




Tuesday, October 13, 2009
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
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
How to get there

                    • Connect Peers
                    • Run Game Loop
                    • Process Events


Tuesday, October 13, 2009
Application Startup




                                             Connect Peers
            •      Start looking for peers




Tuesday, October 13, 2009
Application Startup




                                             Connect Peers
            •      Peer found and selected




Tuesday, October 13, 2009
Application Startup




                                           Connect Peers
            •      Shall we play a game?




Tuesday, October 13, 2009
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
Connect




                                                   Connect Peers
                              Server Mode
                             wait for connection
                                   requests




                               Client Mode
                              look for servers




Tuesday, October 13, 2009
Connect




                                                  Connect Peers
                               Peer Mode
                             wait for conn reqs
                              look for servers




Tuesday, October 13, 2009
Peer Picker Controller




                                                    Connect Peers
   - (void)startPeerPicker {
   !GKPeerPickerController *picker =
           [[GKPeerPickerController alloc] init];
   !picker.delegate = self;
   ![picker show];
   }




Tuesday, October 13, 2009
Peer Picker
                            Controller




                                                  Connect Peers
 - (void)startPeerPicker {
 !GKPeerPickerController *picker =
         [[GKPeerPickerController alloc] init];
 !picker.delegate = self;
 ![picker show];
 }




Tuesday, October 13, 2009
Connect




                                           Connect Peers
                Peer Mode
            wait for conn reqs
             look for servers




Tuesday, October 13, 2009
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
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
Connect Peers
Tuesday, October 13, 2009
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
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
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
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
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
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
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
Game Loop




                                               Run Game Loop
                    • Start the peer picker
                    • Send new disk messages


Tuesday, October 13, 2009
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
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
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
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
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
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
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
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
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
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
Messages
                                new disk




                            Client A        {color, location}   Client B




Tuesday, October 13, 2009
Messages
                                new disk                          new disk




                            Client A        {color, location}   Client B




Tuesday, October 13, 2009
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
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
Smash A Disk
                                       tap




                            Client A




Tuesday, October 13, 2009
Smash A Disk
                                       tap




                            Client A         {smash location}   Client B




Tuesday, October 13, 2009
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
Smashing Disks

  - (void)diskSmashedAt:(CGPoint)point {
    [self.server sendSmashAtPoint:point];
  }




Tuesday, October 13, 2009
Sending Smashes

  - (void)sendSmashAtPoint:(CGPoint)point {
    NSData *data = [NSData dataWithBytes:&point length:sizeof(point)];
    [self sendMessageTypeID:kServerSmashMessageType data:data];
  }




Tuesday, October 13, 2009
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
Remote Smash Forward

   - (void)remoteDiskSmashedAtPoint:(CGPoint)point {
     DiskSmashView *smashView = (DiskSmashView *)self.view;
     [smashView remoteSmash:point];
   }




Tuesday, October 13, 2009
Remote Smash

    - (void)remoteSmash:(CGPoint)point {
      CALayer *layer = [self.layer hitTest:point];
      if(layer != self.layer) {
        [(DiskLayer *)layer smash];
      }
    }




Tuesday, October 13, 2009
Conclusion

                    • Getting Connected is easy!
                    • Sending Data is easy
                    • Designing a good game, not so much.


Tuesday, October 13, 2009
Thanks!
                                Pragmatic iPhone Studio




                            PragProg.com discount code
                               voices_bill_dudney_10


Tuesday, October 13, 2009

Contenu connexe

En vedette

En vedette (12)

#SEJThinkTank: Harnessing the Networks of Your Podcast Guests & Audiences
#SEJThinkTank: Harnessing the Networks of Your Podcast Guests & Audiences #SEJThinkTank: Harnessing the Networks of Your Podcast Guests & Audiences
#SEJThinkTank: Harnessing the Networks of Your Podcast Guests & Audiences
 
Convert Excel Spreadsheet into Mobile iPhone Android App
Convert Excel Spreadsheet into Mobile iPhone Android AppConvert Excel Spreadsheet into Mobile iPhone Android App
Convert Excel Spreadsheet into Mobile iPhone Android App
 
Online bioinformatics forums: why do we keep asking the same questions?
Online bioinformatics forums: why do we keep asking the same questions?Online bioinformatics forums: why do we keep asking the same questions?
Online bioinformatics forums: why do we keep asking the same questions?
 
Steal from the Startups: Entrepreneur Style Growth Tactics for Big Brands by ...
Steal from the Startups: Entrepreneur Style Growth Tactics for Big Brands by ...Steal from the Startups: Entrepreneur Style Growth Tactics for Big Brands by ...
Steal from the Startups: Entrepreneur Style Growth Tactics for Big Brands by ...
 
How to Combine text from two or more cells in Excel
How to Combine text from two or more cells in ExcelHow to Combine text from two or more cells in Excel
How to Combine text from two or more cells in Excel
 
Predikin and PredikinDB: tools to predict protein kinase peptide specificity
Predikin and PredikinDB:  tools to predict protein kinase peptide specificityPredikin and PredikinDB:  tools to predict protein kinase peptide specificity
Predikin and PredikinDB: tools to predict protein kinase peptide specificity
 
Introduction to Perl - Day 1
Introduction to Perl - Day 1Introduction to Perl - Day 1
Introduction to Perl - Day 1
 
Link Building Metrics: Managing Projects and SEOs with Page One Power
Link Building Metrics: Managing Projects and SEOs with Page One PowerLink Building Metrics: Managing Projects and SEOs with Page One Power
Link Building Metrics: Managing Projects and SEOs with Page One Power
 
Winning with Authority - 15 Experts on Integrated Online Marketing
Winning with Authority - 15 Experts on Integrated Online MarketingWinning with Authority - 15 Experts on Integrated Online Marketing
Winning with Authority - 15 Experts on Integrated Online Marketing
 
How to Get More Engagement on Instagram with Kelsey Jones
How to Get More Engagement on Instagram with Kelsey JonesHow to Get More Engagement on Instagram with Kelsey Jones
How to Get More Engagement on Instagram with Kelsey Jones
 
Transforming Customer Experience: From Moments to Journeys
Transforming Customer Experience: From Moments to JourneysTransforming Customer Experience: From Moments to Journeys
Transforming Customer Experience: From Moments to Journeys
 
How to Become a Thought Leader in Your Niche
How to Become a Thought Leader in Your NicheHow to Become a Thought Leader in Your Niche
How to Become a Thought Leader in Your Niche
 

Dernier

Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
WSO2
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(☎️+971_581248768%)**%*]'#abortion pills for sale in dubai@
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
panagenda
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 

Dernier (20)

Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
WSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering DevelopersWSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering Developers
 
Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)
 
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
 
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
 
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
Understanding the FAA Part 107 License ..
Understanding the FAA Part 107 License ..Understanding the FAA Part 107 License ..
Understanding the FAA Part 107 License ..
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistan
 

Game Kit - iPhone

  • 1. iPhone to iPhone Peer to Peer networking with Game Kit Tuesday, October 13, 2009
  • 2. Where We Are Headed Tuesday, October 13, 2009
  • 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. 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. How to get there • Connect Peers • Run Game Loop • Process Events Tuesday, October 13, 2009
  • 6. Application Startup Connect Peers • Start looking for peers Tuesday, October 13, 2009
  • 7. Application Startup Connect Peers • Peer found and selected Tuesday, October 13, 2009
  • 8. Application Startup Connect Peers • Shall we play a game? Tuesday, October 13, 2009
  • 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. Connect Connect Peers Server Mode wait for connection requests Client Mode look for servers Tuesday, October 13, 2009
  • 11. Connect Connect Peers Peer Mode wait for conn reqs look for servers Tuesday, October 13, 2009
  • 12. Peer Picker Controller Connect Peers - (void)startPeerPicker { !GKPeerPickerController *picker = [[GKPeerPickerController alloc] init]; !picker.delegate = self; ![picker show]; } Tuesday, October 13, 2009
  • 13. Peer Picker Controller Connect Peers - (void)startPeerPicker { !GKPeerPickerController *picker = [[GKPeerPickerController alloc] init]; !picker.delegate = self; ![picker show]; } Tuesday, October 13, 2009
  • 14. Connect Connect Peers Peer Mode wait for conn reqs look for servers Tuesday, October 13, 2009
  • 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. 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
  • 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. 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. 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. 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. 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. 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. 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. Game Loop Run Game Loop • Start the peer picker • Send new disk messages Tuesday, October 13, 2009
  • 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. Messages new disk Client A {color, location} Client B Tuesday, October 13, 2009
  • 37. Messages new disk new disk Client A {color, location} Client B Tuesday, October 13, 2009
  • 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. 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. Smash A Disk tap Client A Tuesday, October 13, 2009
  • 41. Smash A Disk tap Client A {smash location} Client B Tuesday, October 13, 2009
  • 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. Smashing Disks - (void)diskSmashedAt:(CGPoint)point { [self.server sendSmashAtPoint:point]; } Tuesday, October 13, 2009
  • 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. 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. Remote Smash Forward - (void)remoteDiskSmashedAtPoint:(CGPoint)point { DiskSmashView *smashView = (DiskSmashView *)self.view; [smashView remoteSmash:point]; } Tuesday, October 13, 2009
  • 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. Conclusion • Getting Connected is easy! • Sending Data is easy • Designing a good game, not so much. Tuesday, October 13, 2009
  • 49. Thanks! Pragmatic iPhone Studio PragProg.com discount code voices_bill_dudney_10 Tuesday, October 13, 2009