Thank you for coming.
My name is Jacques Gasselin and I'm the manager of Game Technologies Team here at Apple.
Today, I'm talking about Game Controllers.
[ Applause ]
So, as you heard yesterday, in the state of the union just I'll mention we have a lot of games in our platform.
It's immensely successful.
We have games that capture your imagination, we have games that you play on the go or at home in the couch and games interact with the user.
They give you an experience and that's what this is all about, interaction.
Game controllers will allow you to give the users another experience, another way to interact with your game content and that I think is very important.
But you won't just have game controllers we still have the existing mechanics on the phone.
So, touch is fantastic and a flexible way for giving the users ways to provide actions through tapping, tilting when motion, swiping or touching direct locations from the screen.
Game controllers on the other hand are fantastic for directional inputs.
And with our precious sensitive buttons they give you an option to provide gameplay mechanics such as picking a ball or throwing a ball maybe executing a special maneuver in a flight simulator or whatever else you guys come up with.
So, when we bring this two together you have an amazing opportunity to thrill your users and give them an even better experience and perhaps bringing games to the next level.
So, we have two parts.
There's a hardware specification by the MFi program which makes sure that hardware is consistent so you're users know what they're going to get and they know that what they've purchased is going to work with your content.
There's also a software framework which is what you will be interacting with in order to read inputs from this controllers and this ensures that with the hardware specification and the software specification you know that the controller you have testing with is going to work with the controller that you use or is using.
And this is obviously for iOS and OS X.
So, to talk about the actual controllers and MFi specification I'd like to invite Edwin Foo up on stage.
Thank you very much.
[ Applause ]
Good afternoon everybody.
I'm Edwin from our accessories engineering team and I'm really, really excited to be up here talking to talk to you of today about the hardware component of this feature that worse in conjunction with the software component that Jacques' team has worked so hard on.
And it's in our opinion I think we it's a really good thing that we have brought this two together just like we do for our own products this [inaudible] of hardware and software.
And so, for the next few minutes I'm going to share with you game developers in the audience what you'll be able to expect from MFi game controllers.
So, to start off with, when we sat down I thought about the hardware specification controllers.
We had two goals in line.
First, we wanted to make sure that your users will be able to go out there and buy any MFi game controller with this badge on it what the behind me on this screen here.
And buy with confidence knowing that it will work with all your games and quite frankly all games on the App Store that work with the game controller framework.
They was we don't want there to be any ambiguity about this.
And in turn, what this does is it enables you the game developers to focus on making great games and not have to worry about dealing with all the differences between the controllers and how do I code to deal with idiosyncrasies of controller A from company A and controller B from company B.
We want this to be a benefit to you too.
And for those of you in the audience we have a closet full of controllers that you bought throughout the years to test with your games.
Well, you don't need that anymore.
You only need to buy one MFi controller, get your game working with it and go publish.
So, what will you be able to expect from MFi and game controllers?
Well, it all starts with consistent control layouts.
We've defined three which I'll be going into in the next couple of slides.
But these layouts are all the same.
You will not they have to worry about whether controls are missing a button that you need for a game to work.
The controllers will be transport agnostic.
So, they may use both wired and wireless creativity options but they will still report changes in control of state and button state to your game at a consistent and fast rates.
All the buttons on MFi game controllers will be pressure sensitive, every single one.
And because we have this ability in the through via the MFi program to set a standard for both mechanical, electrical and firmware requirements all the buttons will have a consistent mechanical feel and this maybe important to some of you in the audience as well.
That but that's not all, we also know that thumbsticks and D-pads have they're definitely been a topic that were has required a lot of time in the past when working on games mainly because not all of them are created equal.
Some of them drift, some of them have dead zones, varying sizes, some of them won't can't even let you actually use the entire area when you roll your finger around.
You won't need to worry that with MFi game controllers.
You can depend on and trust that the controllers that you see here on these controllers will work consistently in a game regardless of whatever code password you may take.
And but of course, we will still see a lot of variation in terms of industrial design and color choices and that sort of thing and that's perfectly fine we want to see that, we want I'm sure your users will appreciate having those options as well, but the core behavior and the way that this controllers work is something that you can trust and depend on to be consistent.
So, let's talk about the first controller type.
What you see here is a form-fitting standard gamepad.
So, let me explain the terminology a little bit.
By forfeiting what I mean is that the gamepad physically in cases the device.
So, forfeiting is a fancy word for case.
The key takeaway here though for our US game developer is that it means that the user can still touch the screen.
And there was API and the game controller framework for your game to check and know for certain that yes the user can't still touch the screen.
Therefore, you can take advantage of that if you like to create this hybrid experience of Multi-Touch and tackle buttons on controllers that Jacques just spoke about.
The standard gamepad has a one directional pad in the left, it will always be on the left 1 ABXY face button group that will always be on the right and will always have these color designs with.
And one row shoulder buttons L and R.
You also see a little pause button there which will be present in all three controller types but that will be spoken about in detail a little bit later in this session.
From the form-fitting standard gamepad we go to the form-fitting extended gamepad.
And that adds two Thumbsticks on either side and an extra set of triggers right below the left and right shoulder buttons.
And you can see there that the labeling changes as well from L and R to L1, L2 and R1, R2.
You can depend on that, all of them will be labeled this way.
So, as you point out that just because the extended gamepad exist does not mean that you have to take advantage of all the controls.
This is something that you as a game designer get to pick.
And we fully expect that there will be some games that when hooked up to an extended gamepad don't use the extra controls, that's perfectly OK.
Last but not least is the standalone extended gamepad.
And standalone means that it is not attached to the device.
That's it, it doesn't have to be complicated.
The important thing here is that all standalone gamepads are extended.
They will have the thumbsticks and they will all have the triggers.
So, remember that.
And also keep in mind that standalone gamepads will have the player ID indicators as you can see there are a little four dots in the middle.
And again, later in the session one of the colleagues will be explaining how to take advantage of those for your game.
So, let's recap.
There are three controller types for MFi game controllers starting with the standard, form-fitting gamepad, the extended form-fitting gamepad and the extended standalone gamepad.
So, some of you in the audience may actually be interested in making MFi game controllers.
And if so, this is the slide for you.
As Jacques explained earlier and as you heard during the state of the union address MFi game controllers will need manufacturers to join the MFi program.
It's very simple.
Go to the URL you see here on the slide, sign up here with your company information.
And, you know, and then you'll be hearing from our presenter fairly soon.
Access to the MFi program grants technical information such as the specification that we have put together concerning MFi game controllers.
Hardware components such as the lightning connector that some of you may choose to use in your game controller.
Test tools, technical support and last but not least certification procedures that you as a controller manufacturer will use when it comes time to get ready to bring your product to market.
Once your product passes certification then you will get to go to market and use those logos compatibility icons that all of the mutual customers know how to recognize.
So, now I'm pretty sure or I guess you can take a guess that the varying questions everyone in mind at this point in time is when will see MFi game controllers?
Well, I can help you answer that right now.
We have already been working with key partners.
You can see two of them on the slide Logitech and Moga and they let me assure you that they are working very diligently to bring controllers to market later this fall.
In fact, in the [inaudible] downstairs as what's previously mentioned you will find that there are some prototype Logitech controllers already out there for you for you game developers to start working with.
So, you can't say that we're slowing you down on this.
You know, get started they're right there.
And quite frankly we can't wait to see what all of you in the audience come up with.
We're' really excited and hope that you'll be willing to walk down this road with us.
And so at this point, I want to hand things over to my colleague JJ so he can talk to you about how to connect the controllers.
[ Applause ]
So, let's talk about the software and how you're going to be interacting with the game controller framework.
What I'm going to be talking to you about is an overview of a commonly used class in the game controller framework.
And then we're talking about how to handle controllers connecting and disconnecting from your devices.
Now, this is a reality players are going to connect and disconnect controllers in your game and you're going to want to handle those appropriately.
I'm also going to talk about how to read controller inputs.
So, once your game knows which controller or controllers it has to access how do you actually read what the thumbsitck position is?
How do you read what player is pushing as far as face buttons goes?
I'm also going to talk about other important controls on the controls like the pause button and the player indicator LEDs and what your responsibilities as game developers are with regards to these controls.
And lastly, we're going to wrap up by talking about best practices.
How to take all this technical information and think about all this new capabilities afforded to you so that you can integrate game controllers in a away that makes your games really special.
[ Pause ]
So, the central class you're going to be using a lot is called GCController.
You're going to be using this to connect to controllers and instances of this class represent a connected controller to your device.
Now, this is the same class for all three supported controller types.
GCController has a lot of capabilities.
It allows you to find controllers.
So, we have methods so that you can query which controllers are currently connected to my device.
Sometimes you might want to be notified as controllers are connected and disconnected and we have ways for you to know that.
And there's also ways for you to discover wireless controllers that haven't been used with this device before.
GCController also provides you ways to read the inputs off of the device.
So, again, how you know where the D-pad is being pressed, thumbsticks, triggers and so on.
And lastly, it gives you information about the controller whether or not it's a form-fitting controller.
The vendor who manufactured this controller perhaps to show in a player facing UI like in a team picker dialogue.
And also gives you the player index which is surfaced in the physical controller via the player indicator LEDs.
So, let's talk about connecting and disconnecting.
We have a class method called controllers on GCController and this gives you an array of the currently connected controllers.
The array instances or the array elements are instances of type GCController.
And if there are no currently connected controllers then this array will return empty.
Now, the beauty of this is that controllers as they're connected and disconnected this method automatically update that information for you.
So, you can be guaranteed that whenever you call this method you have a current idea of which controllers are connected.
Let's look at a code example.
A lot of games will choose to have a central method that's called throughout their game and it resolves new controllers that come in.
And in this example we're calling that method set up controllers.
The first thing we do at the top of set up controllers is we call the controllers class method.
And we take all the currently connected controllers and we cache them into our controller array property.
Then based on whether or not we have controllers we can take action.
Keep this method in mind set up controllers.
I'm going to be referring to it throughout the rest of the talk.
Sometimes you don't want to be sometimes you don't want to necessarily ask what controllers are currently connected right now rather you want to be notified when a controller connects and disconnects.
And we provide capabilities for you to get notified of that.
Using NSNotificationCenter you can add observers when called GCController did connect notification.
This is for obviously detecting when controllers connect.
Similarly, to be notified when a controller disconnects we have GCController did disconnect notification.
You'll notice in this example, the selector we've chosen is our set up controller's method that you saw on the previous screen.
So, as controllers are connected and disconnected we're going to be funneling back into that method.
Now, some controllers are going to be wireless and these types of controllers need to be discovered and paired before the first time they're used with a particular device.
These generally only needs to happen once.
Once the user has paired a wireless controller with the device then after that the controller will automatically be recognized and we don't need to go through this discovery paring process again.
So, as game developers you can afford a convenience to your players and allow them to do this rate within your game.
This is great for players who have just unboxed their brand new controller and go to your game first and don't have to or rather they can jump into the game without having to leave your game.
So, you can just initiate this discovery process with the method that we call start wireless controller discovery with completion handler.
When you call this wireless discovery kicks off asynchronously and it doesn't block you're able to go about your business and your app can remain responsive.
And whenever the discovery process finishes your supplied completion handler is called.
And it's called in one of three situations.
One, either all the controllers have been discovered.
Two, the discovery process has timed-out or three, you've explicitly told it to stop early, and if you decide to do that you can do so via the stop wireless controller discovery method.
Now, you're going to want to use this in conjunction with notifications.
So, as you kickoff the wireless discovery process the discovery is happening asynchronously in the background and while that's happening and controllers are being discovered and paired notifications fire.
And so, if you set up the notifications that I showed you on the previous slide that will be happened automatically.
So, you can see we're building this in layers.
Let's look at a code example.
In this example, we've arbitrarily chosen that the user we're going to allow the user the ability to start the wireless discovery themselves.
So, maybe the user hits a button in your interface say the first thing we do is start up a spinner so that the user knows that they're input action has been accepted and we kickoff the start wireless controller discovery with completion handler method.
Now, again, this happens asynchronously, and whenever it returns we can take action and the first thing we're doing in this case is we're stopping our spinner.
Since we're affording the users the ability to start this process themselves we should also provide them a way to cancel it.
And you do that again by calling stop wireless controller discovery.
You'll note that this method doesn't take a completion handler because when this is called the completion handler in the start method above is called for you.
And it's safe to call stop wireless controller discovery even if your start wireless controller discovery handler has already called.
Now, I have a few caveats to mention to you regarding connecting and disconnecting.
Controllers take time to be recognized on app start up.
Now, the framework does this for you asynchronously and automatically.
But one of the side effects is that the controllers class method is going to be empty inside of application did finish launching for options with options.
But this is OK, if you setup your notifications there for controllers connecting and disconnecting inside of application did finish launching with options you're guaranteed not to miss any connections and disconnections.
Now, we recognize there are some games out there who might have large engines or a lot of art assets to load.
And their not ready to start listening for controller notifications inside of application did finish launching with options.
And that's OK.
You can call you can setup your notifications whenever make sense for your game.
Just make sure right before that you call the controllers array so you capture any controllers which may have already been connected.
All right, so now we have controllers that are connected and we're ready to read the input off of those controllers.
Now, you recall we have three supported physical controller types.
And the way these are mapped in the software are via what we call profiles.
So, the standard gamepad has a standard gamepad profile.
And the two extended gamepads share a single profile that we call he extended gamepad profile.
Now, the standard gamepad profile that's why the standard gamepad has four face buttons, two shoulder buttons and a D-pad.
And the way these are mapped in the software are via properties on the gamepad.
So, you have button A, button B, button X, button Y.
Left shoulder, right shoulder and D-pad.
Now, the standard gamepad profile is a property called gamepad on controllers.
You can see that listed up in the subheading.
Moving on to the extended gamepads you will recall these add two thumbsticks and two triggers on top of the standard gamepad.
And here highlighted in yellow you can see the extra properties on the extended gamepad profile.
Now, the standard gamepad is going to be supported by all controllers regardless of whether it's a standard controller or an extended controller.
So, you as software developers are guaranteed that as long as your controller supports, as long as your code supports the standard gamepad all the controllers that are used with games will work.
With extended gamepads not every controller will support the extended gamepad profile namely the standard gamepad obliviously doesn't have thumbsticks.
It doesn't have triggers.
So, check this property, check the extended gamepad property on controllers.
If it's new hat means that extended gamepads are not supported.
I'd like to bring your attention to the fact that thumbsticks and D-pads while being two totally physically separate devices share a control type direction pad.
Similarly, the triggers and the face buttons and the shoulder buttons all share a button input type.
So, let's dive into these various element types.
Buttons are represented in our framework by a class called GCControllerButtonInput.
And they are treated in the classic digital sense whether they're pressed or not with a bullion in the framework called Pressed.
If this is true the button is pressed, if not its not pressed.
But since our buttons are also pressure sensitive you have the option of reading a value property which returns a float.
This tells you how much force that button is being pressed with at the current moment.
And this is a float normalized between zero and one.
All right, let's talk about GCControllerDirectionPad.
Again, this is shared across multiple physical inputs such as the D-pad and the thumbstick.
And we give you options as game developers to use these in a way that suits your game.
So, you can read them as four buttons up, down, left and right or you can read them as two axis, the xAxis and the yAxis.
If we look at the axis type GCControllerAxisInput you will note that it has a value property.
And this tracks the movement along that axis.
It's normalized from negative one on one end to positive one on the other end with zero in between.
Now, the hardware spec guarantees that any non-zero value is the player intentionally moving the D-pad or the thumbstick away from the neutral resting position.
So, for those of you in the audience who are used to programming your own dead zones for controllers don't do that here.
The hardware spec guarantees a consistent dead zone and if you add your own dead zone on top you're compromising the crispiness of the controls.
Now, let's talk about how do we actually read the values off of these controller inputs.
The first and probably most common way that you're going to be doing this is via Polling.
Polling allows you to find out what the current value of that controller input is right now.
Using conjunction with polling every game loop you can track the movement of various controller inputs across various frames of your game, things like thumbstick position.
Now, sometimes you don't want to know what the current value is right now.
You want to be notified when the value changes.
And to be notified of this you can use value change call backs.
So, you can use this in scenarios where you want to be notified when the player starts polling the right trigger for instance.
Setup a value change call back and you'll be notified when that happens.
Lastly you can take snapshots and snapshots are ways of capturing the entire controller state in one object.
You can use this for a lot of useful things like recording button input.
You can compare current controller state this frame to a previous frame.
You can record input to send across the wire to to record to a file.
Now, let's look at some examples.
For polling like I said you're typically going to be doing this each game loop iteration and it's really just a simple as reading the properties off of the profiles.
So, in this first example we have the standard gamepad profile on the controller and from there we're showing you two different ways to read the states of the Y button.
Next, we show an example from the extended gamepad profile three different ways on how to read the Y axis thumbstick value.
You can treat it as a Y axis or you can read it as the up button.
Now, here's a polling example in context of game code.
We've got our update method.
This is what's called one each game loop.
And within there we grab the profile off the controller, the extended gamepad in this case.
And all the while the right trigger is being pressed we're going to firing lasers.
While the left trigger is being pressed we're going to launch missiles.
And lastly, we're going to apply thrust to our spaceship based on the current value of the thumbsticks Y axis value.
Now, value change handlers are accomplished by passing in a block.
So, you choose which controller element you want to be notified when it changes.
And you also pass a block of code that runs whenever that value does happen to change.
The framework is constantly updating the profiles on the main thread at sixty hertz.
And we'll notify any value change handlers you have setup.
Now, handlers can be registered on specific elements such as individual buttons.
They can be registered on collections of elements such as the D-pad or thumbsticks or they can be registered on the entire controller profile itself.
So, you can be notified when anything on the controller changes.
Here's an example.
So, again we grab the profile off of the controller.
And this is an alternate way of firing our lasers whenever the right trigger is pressed.
So, we get a value value change handler which calls us whenever the right trigger's position changes.
When it does we check if the button is pressed and if so we fire our lasers.
Let's look at another example.
You can share a single handler among several several inputs.
So, in this case we're implementing a touch any button to continue.
We grab the profile.
We setup our handler which we're calling myFaceButtonsHandler.
And then we assign that handler to each of the four face buttons.
When any of them are pressed the code runs and we dismiss the UI in this case.
Lastly, an example on how to setup value change handlers on collections of elements.
In this case whenever the right thumbstick is moved we get notified.
This is good for situation where you might want to say move the right thumbstick to look around and be notified when that happens.
Now, value change handlers are called in a hierarchical order from individual elements through the collections and on, up into the controller itself.
So, example of a D-pad being pressed.
First the framework checks if there are any value change handlers on the four face buttons or sorry, the four buttons that represent the D-pad.
If so those are called.
Then it goes through the two axis on the D-pad.
If you have setup value change handlers for those they are called as well.
Then it calls the value change handler on the D-pad itself if you've assigned one and lastly on to the controller profile.
Let's talk about snapshots now.
Snapshots allow us to collect the entire current controller's state in one object.
And we allow you to move the data from to and from NSData Objects very easily via methods that I'll show you in a moment.
And once you have an NSData Representation of the snapshot you can do whatever you want with it.
You can start to file.
You can start to URL.
You can unpack it after that.
Snapshots are also mutable so in addition to recording a controller input you can retrieve controller input and assign it back into a snapshot.
Now, you're going to want to use snapshots in conjunction with polling or value change handlers.
So, in your main game loop as your polling you could be collecting snapshots each frame or inside your value change handlers you could be collecting snapshots as well.
This is great for recording controller input, for sending it over a network, for various debugging activities.
Let's look at us a controller or sorry, a snapshot example.
So, in this example we're going to take a snapshot and write it to a file.
To do that we call the save snapshot method on the gamepad profile.
This gives us our snapshot object GCGamepadSnapshot.
Then we use a method on GCGamepadSnapshot called or a property called snapshotData and that gives us the NSData representation of the snapshot and then using NSData we can go ahead and write that snapshot to a file.
Let's look at an example going to the other way.
So, in this case we provide a file and we use NSData to retrieve that file.
And then we go ahead and initialize a snapshot object with that using our initWithSnapshotData method.
And now I think its time for a demo.
So, I'd to call Jacques back up on stage and Tomash from Crytek.
[ Applause ]
This is a demo of integrating controllers based on all upcoming games called the Collectibles which will be released later this year.
The framework integration was easy.
There was no need to adjust to dead zones or drifting.
It just works.
So, today I would like to talk about design.
We have a great touch base navigation and cover bionics.
And it was a fun challenge to extend them to controllers.
Let's take the navigation first.
With touch controls the player can either move the characters individually by throwing a bat or as a squad by double tapping.
For controllers we take the solution to extend squad movement with D-pad based direct control.
To find the cover with touch controlled the player have to draw a path for controllers we created a slightly different dynamic.
The players can choose from four directions and the system automatically send the characters to the best possible cover in that area.
In complicated situations the player can still use the touch control and move individual characters to cover.
And I think we should call in the the gun ship.
Yup. This is a great example where the user can simultaneously use the controller and the touch control.
Use the D-pad to move the gun ship target and in the same time use the touch screen to navigate the characters.
In this demo the controller joins the touch control and they fit together naturally.
I hope you like that.
I have to know know that this was only a technical demonstration with some nice graphics and only with two game mechanics from all upcoming game, the Collectibles.
[ Applause ]
I want to take you through the the nitty-gritty details of what was actually happening under the hood here.
So, here we have a very simplistic view of a gamepad.
So, you see the D-pad on the left, the face buttons on the right with the correct colors and the two shoulder buttons.
So, as I press the D-pad you notice I can detect the four cardinal and the four inter cardinal directions.
I can also just take the pressure right now.
So, you I' pushing the left as hard as I can.
I can also push it less hard.
So, you there's a float value between zero and one for the direction I'm pushing.
This actually allows you to get 360 degrees of analog input on the D-pad.
The same applies to face buttons so as I press A you notice first it's pressed and I can press it harder enlarging the circle there is, B the same, X and Y and of course the shoulder buttons too, right and left.
And that's how easy that is.
[ Applause ]
All right, let's talk about a few additional controls, the pause button and the player indicator LED's.
Now, the hardware spec guarantees that every controller has a pause button.
And if your game supports game controllers you must support or you must handle the pause button being pressed.
And you're going to want to treat this as a toggle.
Go from pause to unpause and unpause back to paused.
Consider your UI state, some situations in your game it maybe appropriate to do nothing.
Let's look at an example.
So, were back inside of our setup controllers method and its really as simple as this, whenever you have a controller that your game is going to use, use the controller paused handler, set that up in this case whenever the controllers pause button is pressed.
This block is run and we toggle the pause state of the game.
Also controllers are going to have player indicator LED's on them.
And it's your job to assign these.
These communicates to your player that your game has recognized the controller and is using it.
And in the case of multi controller games we will give the player an indication as to which player they are in your game.
These LED's are persistent and so as a controller disconnects and reconnects its going to maintain the same player index.
Now, the player index property on a controller is what you use to set the player indicator LED's.
We have a constant called GCControllerPlayerIndexUnset.
And in this example were checking if the indexes indeed unset and if so assigning it to player one.
You'll notice we have a zero based index game.
In a multiple controller game you might check if any of the currently connected controllers are unset and if so display a UI to the player so that they can choose which players go on which teams for instance.
Now, that you have all the technical information let's take a step back and talk about best practices following these you're going to be able to integrate game controllers in a way that really makes sense and works with the player's intentions.
So, first of all just to reiterate games cannot require a controller.
Game controllers are optional for players.
You're going to want to focus your efforts on the native controls of the system.
So, that means touch and motion on iOS and keyboard and mouse on OS X.
And this is so that you can reach a hundred percent of the players who play your game.
For the players who buy a gamepad controller you can offer them the enhanced experience that you're going to create.
Also, follow standard gameplay conventions.
So, the face buttons A and B you can use those and we recommend that you use them as the A button being your action or confirmation button and the B button being your cancel button.
Now, when talking about connecting and disconnecting think of this from the player's perspective.
There's player intent behind each of these notifications that you get.
When you have a connected event the player has plugged in their controller into the game, or into your device and they want to play with the controller.
And so, in that case off load some of the native input on to the controller wherever appropriate.
Also eliminate the player indicator LED's so that the player knows that the game has recognized the controllers and is ready to use them.
And lastly, a lot of games have on screen overlays like a pause button.
This is entirely appropriate for a touch base game.
But with a controller connected the controller already has a pause button so you can offload that on screen element to the controller freeing up additional real estate on your screen.
Similarly when disconnecting the player is saying I don't want to use this controller any longer at the moment or maybe there is elements or maybe there's reasons out of their control why this controller happen to disconnect.
In either case, pause the gameplay if you're engaged in gameplay.
Also, return to regular controls 'cause the game has no guarantee that the player is going to return back with controller based controls.
And lastly, think through your input so as Jacques mentioned touch controls allow you amazing abilities to directly manipulate your onscreen objects.
And controllers are great for other tasks like precise inputs filling the tactile feedback of the buttons in the controllers against your fingers.
Repeatability of actions.
And there's real magic we think in marrying these two together.
And as game designers you have to think about what game mechanics make most sense with touch and motion and which ones makes most sense to use as physical controller inputs.
For more information please contact Allan Shaffer or any of the resources on the screen.
There's some upcoming sessions you're going to want to be aware of.
Sprite Kit is an amazing new framework for creating sprite based games.
We have two sessions tomorrow and there's also an OpenGL session on Thursday.
Thank you for your attention.
[ Applause ]