iOS 7 Game Controller Tutorial

Learn how to add control your games with a joystick in this iOS 7 game controller tutorial! By Jake Gundersen.

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

Connecting Hardware Controllers

First, make sure your controller is on and paired to your device, following the instructions that came with your controller.

Next, you’ll add some code to connect your game with the controller. Start by opening HUDNode.m and importing the GameController framework:

@import GameController;

Then, add a new GCController property to your private interface:

@property (nonatomic, strong) GCController *controller;

Now you can add the code that interacts with the hardware. Add the following method to HUDNode.m:

- (void)toggleHardwareController:(BOOL)useHardware {
  //1
  if (useHardware) {
    //2
    self.alpha = 0.0;
    //3
    self.controller = [GCController controllers][0];
    //4
    if (self.controller.gamepad) {
      //5
      __weak typeof(self) weakself = self;
      [self.controller.gamepad.buttonA setValueChangedHandler:^(GCControllerButtonInput *button, float value, BOOL pressed) {
        weakself.aPushed = pressed;
      }];
      [self.controller.gamepad.buttonX setValueChangedHandler:^(GCControllerButtonInput *button, float value, BOOL pressed) {
        weakself.shouldDash = pressed;
      }];
      //Add controller pause handler here
    }
  } else {
    //7
    self.alpha = 1.0;
    self.controller = nil;
  }
}

There are two profiles. The gamepad profile and the extended gamepad profile. The extended gamepad profile has all the controls that the gamepad profile has plus a bunch more. In this app you are going to support both profiles by adding code that responds to both the dpad and the left analog stick. But, for now you are just adding support for the A and B buttons.

There are two ways to access the game controller object for input. First, you can query the state of these properties and read the state of the various buttons and controls. Alternatively, you can set the changeHandler which executes a block every time the state changes. For the buttons, you use change handlers.

I’ve mapped the A button on the controller to the A button in the HUD and the X button on the controller to the B button in the HUD. This is the most comfortable way to use both dash and jump on the physical control.

  1. First, you are passing in a boolean to this method. Passing in YES will initiate and set up the methods to handle the input from the controller. It will also hide the on screen HUD. Passing NO will reveal the on screen HUD and reset the controller.
  2. In this part you are just hiding the on screen controls by setting the entire node’s alpha to 0.0.
  3. Here, you set the property to the GCController object that controls the first controller connected. GCController has a controllers class method that returns an array of all the connected hardware. In this app you will only ever communicate with the first controller in the array. You can connect up to four controllers to a single iOS device.
  4. In this section you check for the presence of the gamepad profile. If you need to know what profile your controller supports you check for the .gamepad property or the .extendedGamepad property. If the property is not supported, accessing the property will return nil.
  5. Next, you set up the change handlers that will be called when the button is pressed. In this case, it’s very simple. You set the aPushed (or shouldDash) property to the value of pressed.
    Each button or control has a property on the gamePad (or extendedGamePad) object.
  6. If the method is passed NO, you reset the alpha property to 1.0 (revealing the HUD) and set the controller property to nil.

Now that you have that method in place, it’s time to connect to a controller. First, you will handle the case when a controller is already connected when the app starts. Make sure your bluetooth enables controller is paired with your device or plug your lightning connected controller in (when it’s time to test again).

Find the comment ‘//Add hardware controller code here’ in initWithSize and add this code:

if ([[GCController controllers] count]) {
  [self toggleHardwareController:YES];
}

This will check for any existing controllers and if it finds one or more, it will run the method you just added.

Note: If you have a controller that connects to the lightning cable, testing gets tricky because you have to disconnect your Xcode connected cable to plug your controller in. So, from now on, testing will be several steps:

You won’t be able to get logs in that case either, so you may need to create a logging SKLabelNode or do something else to debug issues. You won’t be relying on any specific NSLog statements in this tutorial, but if you get stuck or need to debug something, you won’t be able to do that with a lightning connected controller. If you have a bluetooth controller this will be easier.

  1. Build and run.
  2. Disconnect from your Mac.
  3. Connect the controller.
  4. Run your app by tapping on it.

Go ahead and connect your controller and run the app. The HUD should be gone and you should be able to dash and jump using the buttons.

Button response

Connecting the Thumb Stick

The next step is to connect the thumb stick to the controller. You already have a custom getter method that accesses the state of the on screen thumbstick, so you’ll be adding a little more code and reading (instead of using a change handler) the hardware left thumbstick input instead.

Change the xJoystickVelocity method to the following:

- (float)xJoystickVelocity {
  //1
  if (self.controller.extendedGamepad) {
    return self.controller.extendedGamepad.leftThumbstick.xAxis.value;
  //2
  } else if (self.controller.gamepad) {
    return self.controller.gamepad.dpad.xAxis.value;
  }
  //3
  return self.joystick.velocity.x / 60.0;
}
  1. You first check for the extended gamepad profile, if it exists, you return the value of its left thumbstick. Apple requires that controller readouts be standardized and have appropriate dead zones, so you don’t have to do any preprocessing of the values coming back from the controller. By the time you retrieve the value, you can just use it.
  2. If you don’t find an extended controller, you check for a gamepad profile. If it exists, you return the value of the dpad. All buttons are pressure sensitive, so the dpad will also return a value between -1.0 and 1.0 instead of just booleans for left/right.
  3. If you don’t have either a gamepad or extended gamepad, you revert to accessing the on screen HUD joystick class to retrieve a value. This code already existed in the method.

Go ahead and build and run now. You should now have full control over your Koala.

Hardware control

Not bad for just a few lines of code, eh? In my opinion this also makes the game much more fun than the on-screen controls as well.

Jake Gundersen

Contributors

Jake Gundersen

Author

Over 300 content creators. Join our team.