integrating with game controllers

98
These are confidential sessions—please refrain from streaming, blogging, or taking pictures Session 501 Integrating with Game Controllers Jacques Gasselin de Richebourg Game Technologies

Upload: others

Post on 03-Feb-2022

1 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Integrating with Game Controllers

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

Game Controllers

Page 3: Integrating with Game Controllers

Game ControllersMulti-Touch and Motion

Page 4: Integrating with Game Controllers

Game controller MFi specificationIntroduction

• Physical hardware requirements• For third-party accessory developers•MFi Program membership required

Page 5: Integrating with Game Controllers

Game controller frameworkIntroduction

• Connect with physical controllers• Read inputs in-game• For iOS and OS X game developers

Page 6: Integrating with Game Controllers

The Controllers

Edwin FooiOS Accessories Engineering

Page 7: Integrating with Game Controllers

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

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

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

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

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

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

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

AvailabilityThe Controllers

•Working with key partners•On store shelves later this fall

Page 15: Integrating with Game Controllers

Connecting to Controllers

JJ CwikGame Technologies

Page 16: Integrating with Game Controllers

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

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

What it providesGCController

Page 19: Integrating with Game Controllers

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

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

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

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

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

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

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

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

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

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

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

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

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

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

CaveatsConnecting and Disconnecting

Page 34: Integrating with Game Controllers

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

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

Reading Controller Input

Page 37: Integrating with Game Controllers

Controller Profiles

YX B

A

YX B

A

YX B

A

Page 38: Integrating with Game Controllers

Controller Profiles

Standard Gamepad Profile

YX B

A

YX B

A

YX B

A

Page 39: Integrating with Game Controllers

Extended Gamepad Profile

Controller Profiles

Standard Gamepad Profile

YX B

A

YX B

A

YX B

A

Page 40: Integrating with Game Controllers

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

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

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

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

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

GCControllerDirectionPad

• Treated as four buttonsGCControllerButtonInput *up, *down, *left, *right;

•Or as two axesGCControllerAxisInput *xAxis, *yAxis;

Element Types

Page 46: Integrating with Game Controllers

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

Three techniquesReading Element Values

Page 48: Integrating with Game Controllers

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Demo

Page 79: Integrating with Game Controllers

Additional Controls

Page 80: Integrating with Game Controllers

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

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

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

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

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

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

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

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

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

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

Best Practices

Page 91: Integrating with Game Controllers

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

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

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

In the Lab

Developer PreviewPrototype Logitech Controller

Page 95: Integrating with Game Controllers

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

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

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