integrating with game controllers
TRANSCRIPT
![Page 1: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/1.jpg)
These are confidential sessions—please refrain from streaming, blogging, or taking pictures
Session 501
Integrating with Game Controllers
Jacques Gasselin de RichebourgGame Technologies
![Page 2: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/2.jpg)
Game Controllers
![Page 3: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/3.jpg)
Game ControllersMulti-Touch and Motion
![Page 4: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/4.jpg)
Game controller MFi specificationIntroduction
• Physical hardware requirements• For third-party accessory developers•MFi Program membership required
![Page 5: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/5.jpg)
Game controller frameworkIntroduction
• Connect with physical controllers• Read inputs in-game• For iOS and OS X game developers
![Page 6: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/6.jpg)
The Controllers
Edwin FooiOS Accessories Engineering
![Page 7: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/7.jpg)
GoalsThe Controllers
• Consistently high-quality controllers from MFi partners• Focus on making great games, not dealing with controller differences
![Page 8: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/8.jpg)
Key featuresThe Controllers
• Consistent control layouts• Transport agnostic• Fast report rate• Buttons
■ Pressure sensitive■ Consistent feel
• Thumbsticks and D-pads■ Minimum unit circle coverage■ No drift■ No dead zones
YX B
A
R L
![Page 9: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/9.jpg)
Form-fitting standard gamepad
• Form-fitting■ Physically encases the device■ User can touch the screen
• Controls■ D-pad■ ABXY■ Shoulders
The Controllers
YX B
A
R L
![Page 10: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/10.jpg)
YX B
A
R2
R1 L1
L2
Form-fitting extended gamepadThe Controllers
• Form-fitting■ Physically encases the device■ User can touch the screen
• Controls■ D-pad■ ABXY■ Shoulders■ Thumbsticks■ Triggers
![Page 11: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/11.jpg)
Standalone extended gamepadThe Controllers
• Standalone■ Not attached to device
• Controls■ D-pad■ ABXY■ Shoulders■ Thumbsticks■ Triggers
YX B
A
R2
R1
L2
L1
![Page 12: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/12.jpg)
The ControllersRecap
YX B
A
R L
YX B
A
R2
R1
L2
L1
YX B
A
R2
R1 L1
L2
![Page 13: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/13.jpg)
Apple MFi programThe Controllers
• Technical information•Hardware components• Testing tools• Technical support•Accessory certification• Logos and compatibility icons
http://developer.apple.com/mfi/
![Page 14: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/14.jpg)
AvailabilityThe Controllers
•Working with key partners•On store shelves later this fall
![Page 15: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/15.jpg)
Connecting to Controllers
JJ CwikGame Technologies
![Page 16: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/16.jpg)
Integrating with game controllersAgenda
•Overview•Handling connection and disconnection• Reading controller inputs•Using pause button and player indicators• Best practices
![Page 17: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/17.jpg)
OverviewGCController
• Represents a connected game controller• Same class for all supported controllers
YX B
A
R2
R1
L2
L1
YX B
A
R L
YX B
A
R2
R1 L1
L2
![Page 18: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/18.jpg)
What it providesGCController
![Page 19: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/19.jpg)
What it providesGCController
•Methods for finding controllers■ Get controllers currently connected■ Notifications for live connect or disconnect■ Discover wireless controllers
![Page 20: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/20.jpg)
What it providesGCController
•Methods for finding controllers■ Get controllers currently connected■ Notifications for live connect or disconnect■ Discover wireless controllers
•Access to physical input data■ D-pad, buttons, triggers, thumbsticks
![Page 21: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/21.jpg)
What it providesGCController
•Methods for finding controllers■ Get controllers currently connected■ Notifications for live connect or disconnect■ Discover wireless controllers
•Access to physical input data■ D-pad, buttons, triggers, thumbsticks
• Information about this controller■ Type, vendor, player index
![Page 22: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/22.jpg)
Main entry pointConnecting and Disconnecting
@interface GCController : NSObject+ (NSArray *)controllers...
• List of currently connected controllers•Array of GCController instances (empty if none)•Updated whenever controllers connect or disconnect
![Page 23: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/23.jpg)
Main entry pointConnecting and Disconnecting
@interface GCController : NSObject+ (NSArray *)controllers...
• List of currently connected controllers•Array of GCController instances (empty if none)•Updated whenever controllers connect or disconnect
![Page 24: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/24.jpg)
ExampleConnecting and Disconnecting
- (void)setupControllers:(NSNotification *)notification{ // Get Controllers self.controllerArray = [GCController controllers];
if ([self.controllerArray count] > 0) { // Found controllers } else { // No controllers }}
![Page 25: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/25.jpg)
ExampleConnecting and Disconnecting
- (void)setupControllers:(NSNotification *)notification{ // Get Controllers self.controllerArray = [GCController controllers];
if ([self.controllerArray count] > 0) { // Found controllers } else { // No controllers }}
![Page 26: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/26.jpg)
ExampleConnecting and Disconnecting
- (void)setupControllers:(NSNotification *)notification{ // Get Controllers self.controllerArray = [GCController controllers];
if ([self.controllerArray count] > 0) { // Found controllers } else { // No controllers }}
![Page 27: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/27.jpg)
NotificationsConnecting and Disconnecting
•User may connect or disconnect controller■ Provides notification of the change
NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
// Set up connect notification[ center addObserver:self selector:@selector(setupControllers:) name:GCControllerDidConnectNotification object:nil];
// Set up disconnect notification[ center addObserver:self selector:@selector(setupControllers:) name:GCControllerDidDisconnectNotification object:nil];
![Page 28: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/28.jpg)
NotificationsConnecting and Disconnecting
•User may connect or disconnect controller■ Provides notification of the change
NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
// Set up connect notification[ center addObserver:self selector:@selector(setupControllers:) name:GCControllerDidConnectNotification object:nil];
// Set up disconnect notification[ center addObserver:self selector:@selector(setupControllers:) name:GCControllerDidDisconnectNotification object:nil];
![Page 29: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/29.jpg)
Wireless controllers
•Must be “discovered” before use■ Generally needed once per device pair■ Connects automatically thereafter
•App can initiate discovery+startWirelessControllerDiscoveryWithCompletionHandler:
■ Search runs asynchronously until finished, timeout, or stopped■ Use in conjunction with Notifications
• To stop early+stopWirelessControllerDiscovery
Discovery
![Page 30: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/30.jpg)
ExampleDiscovery
- (void)userStartedDiscovery{ [self startMySpinner]; // Find wireless controllers - triggers notifications [GCController startWirelessControllerDiscoveryWithCompletionHandler:^{ // Discovery ended [self stopMySpinner]; }];}
- (void)userStoppedDiscovery{ // Stop discovery early [GCController stopWirelessControllerDiscovery];}
![Page 31: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/31.jpg)
ExampleDiscovery
- (void)userStartedDiscovery{ [self startMySpinner]; // Find wireless controllers - triggers notifications [GCController startWirelessControllerDiscoveryWithCompletionHandler:^{ // Discovery ended [self stopMySpinner]; }];}
- (void)userStoppedDiscovery{ // Stop discovery early [GCController stopWirelessControllerDiscovery];}
![Page 32: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/32.jpg)
ExampleDiscovery
- (void)userStartedDiscovery{ [self startMySpinner]; // Find wireless controllers - triggers notifications [GCController startWirelessControllerDiscoveryWithCompletionHandler:^{ // Discovery ended [self stopMySpinner]; }];}
- (void)userStoppedDiscovery{ // Stop discovery early [GCController stopWirelessControllerDiscovery];}
![Page 33: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/33.jpg)
CaveatsConnecting and Disconnecting
![Page 34: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/34.jpg)
CaveatsConnecting and Disconnecting
• [GCController controllers] array will always be empty in-application:didFinishLaunchingWithOptions:
■ Set up notifications there GCControllerDidConnectNotification GCControllerDidDisconnectNotification
![Page 35: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/35.jpg)
CaveatsConnecting and Disconnecting
• [GCController controllers] array will always be empty in-application:didFinishLaunchingWithOptions:
■ Set up notifications there GCControllerDidConnectNotification GCControllerDidDisconnectNotification
•Note:■ If your game waits to set up notifications later■ Controller array may already be populated by then
![Page 36: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/36.jpg)
Reading Controller Input
![Page 37: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/37.jpg)
Controller Profiles
YX B
A
YX B
A
YX B
A
![Page 38: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/38.jpg)
Controller Profiles
Standard Gamepad Profile
YX B
A
YX B
A
YX B
A
![Page 39: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/39.jpg)
Extended Gamepad Profile
Controller Profiles
Standard Gamepad Profile
YX B
A
YX B
A
YX B
A
![Page 40: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/40.jpg)
Standard gamepad profileController Profiles
• Four face buttons■ A, B, X, Y
• Two shoulder buttons■ L, R
•One D-pad
Standard Gamepad Profile
YX B
A
![Page 41: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/41.jpg)
Standard Gamepad Profile
Control Property Name Type
Face buttons
buttonA
ButtonInputFace buttonsbuttonB
ButtonInputFace buttons
buttonXButtonInputFace buttons
buttonY
ButtonInput
Shoulder buttonsleftShoulder
ButtonInputShoulder buttonsrightShoulder
ButtonInput
D-pad dpad DirectionPad
self.myController.gamepad
![Page 42: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/42.jpg)
Extended gamepad profileController Profiles
• Two thumbsticks■ Left, right
• Two triggers■ L2, R2
• Four face buttons■ A, B, X, Y
• Two shoulder buttons■ L1, R1
•One D-pad Extended Gamepad Profile
YX B
A
YX B
A
![Page 43: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/43.jpg)
Extended Gamepad Profile
Control Name Type
ThumbsticksleftThumbstick
DirectionPadThumbsticksrightThumbstick
DirectionPad
TriggersleftTrigger
ButtonInputTriggersrightTrigger
ButtonInput
Face buttons
buttonA
ButtonInputFace buttonsbuttonB
ButtonInputFace buttonsbuttonX
ButtonInputFace buttons
buttonY
ButtonInput
Shoulder buttonsleftShoulder
ButtonInputShoulder buttonsrightShoulder
ButtonInput
D-pad dpad DirectionPad
self.myController.extendedGamepad
![Page 44: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/44.jpg)
GCControllerButtonInputElement Types
• Classic button state BOOL pressed; // Whether button is pressed
• Buttons are also pressure sensitivefloat value; // Amount of pressure (analog) // Normalized from 0.0 to 1.0
![Page 45: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/45.jpg)
GCControllerDirectionPad
• Treated as four buttonsGCControllerButtonInput *up, *down, *left, *right;
•Or as two axesGCControllerAxisInput *xAxis, *yAxis;
Element Types
![Page 46: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/46.jpg)
GCControllerAxisInputElement Types
•Measures movement along a particular axisfloat value; // Normalized from -1.0 to 1.0; 0.0 is neutral
•Non-zero values indicate movement is outside neutral dead-zone
+1.0
-1.0
-1.0 +1.00.0
![Page 47: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/47.jpg)
Three techniquesReading Element Values
![Page 48: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/48.jpg)
Three techniquesReading Element Values
• Poll elements directly■ For querying current value■ Best for values changing over time (query each game loop)■ e.g., thumbstick position
![Page 49: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/49.jpg)
Three techniquesReading Element Values
• Poll elements directly■ For querying current value■ Best for values changing over time (query each game loop)■ e.g., thumbstick position
• Register a value change callback■ For detecting changes of state■ e.g., callback for trigger started being pulled
![Page 50: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/50.jpg)
Three techniquesReading Element Values
• Poll elements directly■ For querying current value■ Best for values changing over time (query each game loop)■ e.g., thumbstick position
• Register a value change callback■ For detecting changes of state■ e.g., callback for trigger started being pulled
• Take snapshot of entire controller state■ For capturing all elements simultaneously■ e.g., button combos, input recording
![Page 51: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/51.jpg)
PollingReading Element Values
• Typically done each game loop iteration•All elements can be accessed directly via current profile
// face buttonself.myController.gamepad.buttonY.pressed;self.myController.gamepad.buttonY.value;
// thumbstickself.myController.extendedGamepad.leftThumbstick.yAxis.value;self.myController.extendedGamepad.leftThumbstick.up.value;self.myController.extendedGamepad.leftThumbstick.up.pressed;
![Page 52: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/52.jpg)
PollingReading Element Values
• Typically done each game loop iteration•All elements can be accessed directly via current profile
// face buttonself.myController.gamepad.buttonY.pressed;self.myController.gamepad.buttonY.value;
// thumbstickself.myController.extendedGamepad.leftThumbstick.yAxis.value;self.myController.extendedGamepad.leftThumbstick.up.value;self.myController.extendedGamepad.leftThumbstick.up.pressed;
![Page 53: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/53.jpg)
PollingReading Element Values
• Typically done each game loop iteration•All elements can be accessed directly via current profile
// face buttonself.myController.gamepad.buttonY.pressed;self.myController.gamepad.buttonY.value;
// thumbstickself.myController.extendedGamepad.leftThumbstick.yAxis.value;self.myController.extendedGamepad.leftThumbstick.up.value;self.myController.extendedGamepad.leftThumbstick.up.pressed;
![Page 54: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/54.jpg)
Polling exampleReading Element Values
-(void)update{ // Using Extended Gamepad controller GCExtendedGamePad *profile = self.myController.extendedGamepad;
// Take actions for triggers if (profile.rightTrigger.isPressed) [self fireLasers]; if (profile.leftTrigger.isPressed) [self launchMissiles];
// Apply thrust based on Y value of thumbstick [self applyThrust: profile.leftThumbstick.yAxis.value];}
![Page 55: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/55.jpg)
Polling exampleReading Element Values
-(void)update{ // Using Extended Gamepad controller GCExtendedGamePad *profile = self.myController.extendedGamepad;
// Take actions for triggers if (profile.rightTrigger.isPressed) [self fireLasers]; if (profile.leftTrigger.isPressed) [self launchMissiles];
// Apply thrust based on Y value of thumbstick [self applyThrust: profile.leftThumbstick.yAxis.value];}
![Page 56: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/56.jpg)
Polling exampleReading Element Values
-(void)update{ // Using Extended Gamepad controller GCExtendedGamePad *profile = self.myController.extendedGamepad;
// Take actions for triggers if (profile.rightTrigger.isPressed) [self fireLasers]; if (profile.leftTrigger.isPressed) [self launchMissiles];
// Apply thrust based on Y value of thumbstick [self applyThrust: profile.leftThumbstick.yAxis.value];}
![Page 57: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/57.jpg)
Polling exampleReading Element Values
-(void)update{ // Using Extended Gamepad controller GCExtendedGamePad *profile = self.myController.extendedGamepad;
// Take actions for triggers if (profile.rightTrigger.isPressed) [self fireLasers]; if (profile.leftTrigger.isPressed) [self launchMissiles];
// Apply thrust based on Y value of thumbstick [self applyThrust: profile.leftThumbstick.yAxis.value];}
![Page 58: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/58.jpg)
Value change handlerReading Element Values
• Register a block as a change handler•How it works:
■ Framework updates profile(s) on main thread at 60Hz■ When updating, any handlers will be called
•Handlers can be registered on:■ Specific element(s)■ Collections (D-pad, axis)■ An entire profile
![Page 59: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/59.jpg)
Example 1Value Change Handler
-(void)setupHandlers{ // Using extended gamepad profile GCExtendedGamepad *profile = self.myController.extendedGamepad;
// Set up callback for right trigger profile.rightTrigger.valueChangedHandler = ^(GCControllerButtonInput *button, float value, BOOL pressed) { // Take action if pressed if (pressed) [self fireLasers]; };}
![Page 60: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/60.jpg)
Example 1Value Change Handler
-(void)setupHandlers{ // Using extended gamepad profile GCExtendedGamepad *profile = self.myController.extendedGamepad;
// Set up callback for right trigger profile.rightTrigger.valueChangedHandler = ^(GCControllerButtonInput *button, float value, BOOL pressed) { // Take action if pressed if (pressed) [self fireLasers]; };}
![Page 61: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/61.jpg)
Example 1Value Change Handler
-(void)setupHandlers{ // Using extended gamepad profile GCExtendedGamepad *profile = self.myController.extendedGamepad;
// Set up callback for right trigger profile.rightTrigger.valueChangedHandler = ^(GCControllerButtonInput *button, float value, BOOL pressed) { // Take action if pressed if (pressed) [self fireLasers]; };}
![Page 62: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/62.jpg)
Example 2: Shared handlersValue Change Handler
// Using standard gamepad profileGCGamepad *profile = self.myController.gamepad;
// Shared handlervoid (^myFaceButtonsHandler)(GCControllerButtonInput *, float, BOOL) = ^(GCControllerButtonInput *button, float value, BOOL pressed){ // Face button pressed [self dismissUI];};
// “Press any face button to continue”profile.buttonA.valueChangedHandler = myFaceButtonsHandler;profile.buttonB.valueChangedHandler = myFaceButtonsHandler;profile.buttonX.valueChangedHandler = myFaceButtonsHandler;profile.buttonY.valueChangedHandler = myFaceButtonsHandler;
![Page 63: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/63.jpg)
Example 2: Shared handlersValue Change Handler
// Using standard gamepad profileGCGamepad *profile = self.myController.gamepad;
// Shared handlervoid (^myFaceButtonsHandler)(GCControllerButtonInput *, float, BOOL) = ^(GCControllerButtonInput *button, float value, BOOL pressed){ // Face button pressed [self dismissUI];};
// “Press any face button to continue”profile.buttonA.valueChangedHandler = myFaceButtonsHandler;profile.buttonB.valueChangedHandler = myFaceButtonsHandler;profile.buttonX.valueChangedHandler = myFaceButtonsHandler;profile.buttonY.valueChangedHandler = myFaceButtonsHandler;
![Page 64: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/64.jpg)
Example 2: Shared handlersValue Change Handler
// Using standard gamepad profileGCGamepad *profile = self.myController.gamepad;
// Shared handlervoid (^myFaceButtonsHandler)(GCControllerButtonInput *, float, BOOL) = ^(GCControllerButtonInput *button, float value, BOOL pressed){ // Face button pressed [self dismissUI];};
// “Press any face button to continue”profile.buttonA.valueChangedHandler = myFaceButtonsHandler;profile.buttonB.valueChangedHandler = myFaceButtonsHandler;profile.buttonX.valueChangedHandler = myFaceButtonsHandler;profile.buttonY.valueChangedHandler = myFaceButtonsHandler;
![Page 65: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/65.jpg)
Example 2: Shared handlersValue Change Handler
// Using standard gamepad profileGCGamepad *profile = self.myController.gamepad;
// Shared handlervoid (^myFaceButtonsHandler)(GCControllerButtonInput *, float, BOOL) = ^(GCControllerButtonInput *button, float value, BOOL pressed){ // Face button pressed [self dismissUI];};
// “Press any face button to continue”profile.buttonA.valueChangedHandler = myFaceButtonsHandler;profile.buttonB.valueChangedHandler = myFaceButtonsHandler;profile.buttonX.valueChangedHandler = myFaceButtonsHandler;profile.buttonY.valueChangedHandler = myFaceButtonsHandler;
![Page 66: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/66.jpg)
Example 3: Element CollectionsValue Change Handler
// Using extended gamepad profileGCExtendedGamepad *profile = self.myController.extendedGamepad;
// “Move right thumbstick to look around”profile.rightThumbstick.valueChangedHandler = ^(GCControllerDirectionPad *dpad, float xValue, float yValue){ // Right thumbstick position changed NSLog(@"Right thumbstick value changed: (%f, %f)", xValue, yValue);};
![Page 67: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/67.jpg)
Example 3: Element CollectionsValue Change Handler
// Using extended gamepad profileGCExtendedGamepad *profile = self.myController.extendedGamepad;
// “Move right thumbstick to look around”profile.rightThumbstick.valueChangedHandler = ^(GCControllerDirectionPad *dpad, float xValue, float yValue){ // Right thumbstick position changed NSLog(@"Right thumbstick value changed: (%f, %f)", xValue, yValue);};
![Page 68: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/68.jpg)
Example 3: Element CollectionsValue Change Handler
// Using extended gamepad profileGCExtendedGamepad *profile = self.myController.extendedGamepad;
// “Move right thumbstick to look around”profile.rightThumbstick.valueChangedHandler = ^(GCControllerDirectionPad *dpad, float xValue, float yValue){ // Right thumbstick position changed NSLog(@"Right thumbstick value changed: (%f, %f)", xValue, yValue);};
![Page 69: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/69.jpg)
Hierarchy of precedenceValue Change Handler
• Value change handlers called in hierarchical order• From individual elements to profile• e.g., order of handler callbacks when D-pad pressed:
■ Four D-pad buttons■ Two D-pad axes■ D-pad itself■ Controller profile
![Page 70: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/70.jpg)
SnapshotsReading Element Values
• Captures all elements in profile simultaneously•Allows serialization of controller state
■ Pack to and from NSData■ Mutable
•Use in conjunction with polling or value change handlers• Example usage:
■ Input recording and replay■ Send over network■ Debugging
![Page 71: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/71.jpg)
Example 1: Capture snapshotSnapshot
- (BOOL)writeSnapshotToFile:(NSString *)filePath{ // Grab snapshot GCGamepadSnapshot *snapshot = [self.myController.gamepad saveSnapshot];
// NSData representation of snapshot NSData *snapshotData = snapshot.snapshotData;
// Save data to file return [snapshotData writeToFile:filePath atomically:YES];}
![Page 72: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/72.jpg)
Example 1: Capture snapshotSnapshot
- (BOOL)writeSnapshotToFile:(NSString *)filePath{ // Grab snapshot GCGamepadSnapshot *snapshot = [self.myController.gamepad saveSnapshot];
// NSData representation of snapshot NSData *snapshotData = snapshot.snapshotData;
// Save data to file return [snapshotData writeToFile:filePath atomically:YES];}
![Page 73: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/73.jpg)
Example 1: Capture snapshotSnapshot
- (BOOL)writeSnapshotToFile:(NSString *)filePath{ // Grab snapshot GCGamepadSnapshot *snapshot = [self.myController.gamepad saveSnapshot];
// NSData representation of snapshot NSData *snapshotData = snapshot.snapshotData;
// Save data to file return [snapshotData writeToFile:filePath atomically:YES];}
![Page 74: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/74.jpg)
Example 1: Capture snapshotSnapshot
- (BOOL)writeSnapshotToFile:(NSString *)filePath{ // Grab snapshot GCGamepadSnapshot *snapshot = [self.myController.gamepad saveSnapshot];
// NSData representation of snapshot NSData *snapshotData = snapshot.snapshotData;
// Save data to file return [snapshotData writeToFile:filePath atomically:YES];}
![Page 75: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/75.jpg)
Example 2: Retrieve snapshotSnapshot
- (GCGamepadSnapshot *)snapshotFromFile:(NSString *)filePath{ // Read data from file NSData *data = (NSData *)[NSData dataWithContentsOfFile:filePath];
// Init snapshot GCGamepadSnapshot *snapshot = [[GCGamepadSnapshot alloc] initWithSnapshotData:data];
return snapshot;}
![Page 76: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/76.jpg)
Example 2: Retrieve snapshotSnapshot
- (GCGamepadSnapshot *)snapshotFromFile:(NSString *)filePath{ // Read data from file NSData *data = (NSData *)[NSData dataWithContentsOfFile:filePath];
// Init snapshot GCGamepadSnapshot *snapshot = [[GCGamepadSnapshot alloc] initWithSnapshotData:data];
return snapshot;}
![Page 77: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/77.jpg)
Example 2: Retrieve snapshotSnapshot
- (GCGamepadSnapshot *)snapshotFromFile:(NSString *)filePath{ // Read data from file NSData *data = (NSData *)[NSData dataWithContentsOfFile:filePath];
// Init snapshot GCGamepadSnapshot *snapshot = [[GCGamepadSnapshot alloc] initWithSnapshotData:data];
return snapshot;}
![Page 78: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/78.jpg)
Demo
![Page 79: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/79.jpg)
Additional Controls
![Page 80: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/80.jpg)
Pause buttonAdditional Controls
• Every controller includes Pause button•Handling required
■ If game supports controllers
• Treat as a toggle■ Active Pause■ Paused Active
• Consider UI state
YX B
A
R2
R1 L1
L2
![Page 81: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/81.jpg)
Pause buttonAdditional Controls
• Every controller includes Pause button•Handling required
■ If game supports controllers
• Treat as a toggle■ Active Pause■ Paused Active
• Consider UI state
YX B
A
R2
R1 L1
L2
![Page 82: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/82.jpg)
Pause button exampleAdditional Controls
- (void)setupControllers{
// ...
// Add Pause Handler self.myController.controllerPausedHandler = ^(GCController *controller) {
// Pause button pressed [self togglePauseResumeState];
}}
![Page 83: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/83.jpg)
Pause button exampleAdditional Controls
- (void)setupControllers{
// ...
// Add Pause Handler self.myController.controllerPausedHandler = ^(GCController *controller) {
// Pause button pressed [self togglePauseResumeState];
}}
![Page 84: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/84.jpg)
Pause button exampleAdditional Controls
- (void)setupControllers{
// ...
// Add Pause Handler self.myController.controllerPausedHandler = ^(GCController *controller) {
// Pause button pressed [self togglePauseResumeState];
}}
![Page 85: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/85.jpg)
YX B
A
R2
R1
L2
L1
Player indicator LEDsAdditional Controls
• Controllers may include player indicators■ Four LEDs■ API to set/get■ Persistent
•Always set LEDs■ For controllers being used■ Player index
![Page 86: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/86.jpg)
YX B
A
R2
R1
L2
L1
Player indicator LEDsAdditional Controls
• Controllers may include player indicators■ Four LEDs■ API to set/get■ Persistent
•Always set LEDs■ For controllers being used■ Player index
![Page 87: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/87.jpg)
Player indicator exampleAdditional Controls
• Single-controller game// If unset, illuminate first LEDif (self.myController.playerIndex == GCControllerPlayerIndexUnset){ self.myController.playerIndex = 0; // Zero-based index}
•Multiple-controller game// If any are unset, present UI to assign players to controllersif ((self.myControllers[0].playerIndex == GCControllerPlayerIndexUnset) || (self.myControllers[1].playerIndex == GCControllerPlayerIndexUnset)){ [self launchControllerPicker];}
![Page 88: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/88.jpg)
Player indicator exampleAdditional Controls
• Single-controller game// If unset, illuminate first LEDif (self.myController.playerIndex == GCControllerPlayerIndexUnset){ self.myController.playerIndex = 0; // Zero-based index}
•Multiple-controller game// If any are unset, present UI to assign players to controllersif ((self.myControllers[0].playerIndex == GCControllerPlayerIndexUnset) || (self.myControllers[1].playerIndex == GCControllerPlayerIndexUnset)){ [self launchControllerPicker];}
![Page 89: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/89.jpg)
Player indicator exampleAdditional Controls
• Single-controller game// If unset, illuminate first LEDif (self.myController.playerIndex == GCControllerPlayerIndexUnset){ self.myController.playerIndex = 0; // Zero-based index}
•Multiple-controller game// If any are unset, present UI to assign players to controllersif ((self.myControllers[0].playerIndex == GCControllerPlayerIndexUnset) || (self.myControllers[1].playerIndex == GCControllerPlayerIndexUnset)){ [self launchControllerPicker];}
![Page 90: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/90.jpg)
Best Practices
![Page 91: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/91.jpg)
Controllers enhance gameplayBest Practices
•Games can not require a controller ■ Game controllers are optional■ Games supporting controllers must also work without controllers
•Design first for native input■ iOS: Touch, motion■ OS X: Keyboard, mouse
![Page 92: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/92.jpg)
Follow standard conventionsBest Practices
• Button A is action, button B is cancel•When connected
■ Move to controller-based input■ Illuminate player indicator■ Remove on-screen control overlays
•When disconnecting■ Pause gameplay■ Return to regular controls
![Page 93: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/93.jpg)
Think through your inputBest Practices
• Touch■ Ideal for direct manipulation■ i.e., taps, gestures, swipes
• Controller■ Good for precise controls■ i.e., moves, actions
• Touch and form-fitting controller together■ Fine-grain controls plus direct manipulation
![Page 94: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/94.jpg)
In the Lab
Developer PreviewPrototype Logitech Controller
![Page 95: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/95.jpg)
More Information
Allan SchafferGraphics and Game Technologies [email protected]
Apple Developer Forumshttp://devforums.apple.com/
Developer Documentationhttp://developer.apple.com/library/
![Page 96: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/96.jpg)
Related Sessions
Introduction to Sprite Kit PresidioWednesday 11:30AM
Designing Games with Sprite Kit MissionWednesday 2:00PM
Advances in OpenGL ES MissionThursday 9:00AM
![Page 97: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/97.jpg)
Labs
Game Controllers Lab Graphics and Games Lab BTuesday 4:30PM
Game Controllers Lab Graphics and Games Lab BWednesday 9:00AM
Sprite Kit Lab Graphics and Games Lab BWednesday 3:15PM
![Page 98: Integrating with Game Controllers](https://reader031.vdocument.in/reader031/viewer/2022020704/61fb67152e268c58cd5dc01b/html5/thumbnails/98.jpg)