2013 • 54:16
Tap into essential technologies to enhance the gameplay experience. Discover new techniques for managing players and tracking scores through Game Center, and get expert advice about the best practices to follow in your titles. Learn about the Game Controller framework and see how to take advantage of exciting new modes of input by adding support for physical game controllers.
Speaker: Allan Schaffer
Unlisted on Apple Developer site
Downloads from Apple
Transcript
This transcript was generated using Whisper, it may have transcription errors.
Hello again, everyone. Welcome back. Again, my name is Alan Schaefer. I'm the Game Technologies Evangelist at Apple. And this next session is really picking up where Paul and Paul just left off. So they talked about the system technologies, things like multitasking, security, and so on. And now I just want to keep on going with that and talk about some of the game technologies.
So for the next hour, I'm really just going to take this and split it right down the middle. So I'll talk about Game Center for the first half and then Game Controllers for the second half of the session. Now, I think as many of you are already familiar with, Game Center is Apple's social gaming network. We introduced it back in iOS 4.1 several years ago. And, you know, it's really there to implement a lot of the features that you all use to drive engagement in your games. You know, being able to play games along with friends and track leaderboards, post scores, track achievements that players earn in your game. We recently added challenges to let you challenge another person to beat your score or to earn an achievement. Then there's multiplayer. We have synchronous multiplayer for real-time gameplay and churn-based asynchronous multiplayer as well.
But so typically in a session like this, you might expect that I would stand up and talk a lot about the new features in Game Center and about adopting them. But I want to do something actually a little different with this part of the session today. Because really, as for part of my job, I look at a lot of different games. And, you know, just as we saw here in the room, a lot of you are already using Game Center. You're using the features. And ultimately, it's a pretty simple API for you to adopt. And honestly, most developers are just, they're doing the right thing with the API itself. So instead of talking about just adopting the API and kind of the features of it, what I want to do is give you some strategies that you can use Game Center to help really drive increased engagement among your players with your game.
And I think these are going to be some relatively simple things, simple ideas, but the intention is really so that I can demonstrate some things that you can do with Game Center that go beyond really just kind of the simple use of scores for leaderboards and tracking achievements and so on.
So three strategies. Here is number one. Think about ways that you can tie the scores and achievements from your players from GameCenter right back into the core of your gameplay. And so what do I really mean by this? Let's say that you have this example. You have an awesome tank game up on the App Store. It's single player. You play against the computer. And typically when you're playing the game, okay, here we are. The game ends. You won, of course, and the game under the hood is going to post that score up to GameCenter. Now, from the player's perspective, though, posting that score was invisible to them. So if they want to sort of see how they're doing, how they rank against their friends, you know, they're going to need to go and tap this bottom that's down here at the bottom, for example, and bring up the leaderboard UI. And okay, this is all fine, and they can see their score compared to how their friends are doing. And of course, this is exactly what many, most games that are using Game Center are doing today, and it's perfectly fine.
But the observation is this. It's that there isn't really anything built in yet that you see here that's going to draw the player into that leaderboard. And the reason why you might want something that would do that is because that leaderboard and being able to compare my score against my friend's scores, you know, it just does something to increase the engagement in the game. So without that, the game isn't really as engaging as it could be. And the insight that I had as I was putting this together was to kind of realize, you know, this data flow here is very unidirectional. Everything is kind of flowing from left to right. And that leaderboard UI, in a way, ends up being kind of a dead end in the UI. You have to have some motivation for going there. But once you're there, you're kind of done. And you just come back out of it. And, you know, you leave it to the player to go there and find their scores and compare their rankings. So what should you do? Well, is to find ways of bringing that score data back to the player right into the gameplay itself. And so here's some ideas of things that I mean for that, things that you can do. And as I said, this is a single-player game. Okay? But, you know, with the leaderboard, I can see how I rank compared to my friends, and there's all kinds of different things I can accomplish. So how can I bring the scores kind of back into the gameplay while I'm playing? Well, let's think of a few things. So if this was the game that I played and this was the time that I beat one of my friend's scores, well, something could happen. It could show my rank compared to that friend or my rank improving. If it were a timed game or a platformer, maybe it would know how far my friend got and show me as I pass by that spot.
And, you know, doing things like this, the intention is to really bring the friend's network that that player has set up and kind of get them engaged back into it while they're playing the game, rather than just sort of leaving it off as a dead end in the user interface. and really kind of bringing it in is going to create a stronger sense of competition right as, you know, right as you're playing the game. You're going to know how you are doing versus your friends, how far they've gotten, and how I compare to all of that. Now, here's some examples that I bet a lot of you have seen, you know, some great examples of games that are doing this today. So in Temple Run, for example, as I run down the lane in Temple Run, my game center friends are shown right in the path, you know, showing me how far they got before they fell off or got caught by the demons. And so, and it's great. So, you know, because here, for example, is how far my friend Derek has gone in Game Center. And the thing is this. It's just, it is so satisfying in a way that every time that I play Temple Run, I run right past Derek. And every time I walk by Derek's office at work, I can point that out to him again. And, you know, it's just it brings something more into the gameplay. Now, Doodle Jump, same idea. Okay, so as Doodle is bouncing up the pads as you go up, over on the right-hand side, you can see markers with names of, you know, my friends or even in Doodle Jump, you can have it show people from a global leaderboard.
And it's showing how high those people have jumped. And in fact, this time you can see that I just happen to be right next to my own previous high jump location, because I'm funnest over there. Right? And so now I know, oh, like I'm making a better score than I've ever gotten before. before.
Okay, so that's just, that's the nugget of the idea, is to bring those things back into the gameplay itself and think of ways to kind of show that to the user. But now, here are the ingredients that you'll use to pull that off. So, of course, you want to get the data out of the leaderboard and not just have it show up in the UI. So, you can actually use the GK leaderboard class to download the scores directly from the game center service. And so it'll give you the score data for the players or all of their friends, or you can even get the global leaderboard data as well. So once you have these scores, you can see the player ID. You can get the value of the score itself. You can get their rank on that leaderboard, the date when they posted that score, and so on. And then once you have the player ID, you could take that even further if you wanted to. You know, you could load the player's nickname and their photo and have that show up in the game if they've provided Game Center with a photo to display. So there's a lot that's there. And really, this provides all of that raw data that you need to be able to do something that's a little more interesting with their scores. So here's a quick code example of doing exactly that. So let's say that I want to download out of Game Center the top 50 scores for my friends on a particular leaderboard. So I'm going to create a GKE Leaderboard object.
And then here I configure it. So configure the request. So I'm saying, okay, this particular leaderboard, tank game, tanks blasted. I'm going to set the time scope to all time in this case, set the player scope to just my friend's network, and then set a range saying I want the top 50 scores. And now that that's set up, I can just make this call and fetch those scores out of the game center leaderboard. So, I'm calling load scores with completion handler and passing in just -- and I'll get back an array of scores and maybe an error if one occurs. And so, now, this array is going to have those top 50 scores of my friends, and I can walk through that array and put that into the gameplay itself and process those.
Okay. Now, a few ways that you could go even further with this same idea. So, we recently introduced a new style of leaderboard called the most recent score leaderboard. So, instead of holding your all-time best score or fastest time or whatever, it holds your most recent score or your most recent time. Now, essentially, this is a leaderboard that's intended for scores where where your current state will go up and down kind of as you're playing the game multiple times. You know, things like, this may not be the best example locally here, but batting averages in baseball or win-loss ratios or poker chips in a tournament, that sort of thing. And those things can be really compelling to your players.
The second one. So you, the developer, the game knows what my all-time best score was. Obviously, it posted it to Game Center. You have that information from the leaderboard as well. And just think, if I pass that score, the game could do something more special, present a banner, or show something that says, OK, you've got a new high score and tie that in somewhere.
And then just to note also, you know, the examples that I've been citing so far are all dealing to do with scores, but you could do the exact same thing with achievements as well. So rather than having, you know, achievements be kind of passive, just something that the player learns later that they got an achievement for something, you know, instead of that, before the player starts the game or before they go into the next level, model, you could prime them with whatever objective they have to accomplish to get a particular achievement. And it's just, again, it's going to just give them that added little bit of engagement rather than having these things just hidden off in a UI somewhere that they have to go search to find.
But, okay, so that is number one. Tie your scores and achievements back into your gameplay. It's a really simple idea, of course, but something that actually not very many games are doing right now, and the ones that are doing it, it's really interesting what they've done. Okay, here is item number two. Elevate challenges up into your game UI as well.
So it's a real similar idea to what I was just talking about. But let's do a quick recap of challenges before I go. So within Game Center, you can challenge a friend to beat your score or to earn a particular achievement. And the idea is to bring kind of an additional competitive element into the game, and particularly into single-player games, right? Because it's going to drive competition if I send you a challenge, for example. So, you know, let's say that, well, there's two kinds of challenges. The first is a score challenge. And let's say that you and I are friends in Game Center, and I challenge you to beat my score that I got in a particular game.
So you'll get a push notification that I've challenged you. And then when you run the game, you know, you can try and beat the score that I got. But then, okay, that's simple enough. But then it actually gets a little more interesting. Because if you beat the score that I challenged you to beat, then actually Game Center will automatically re-challenge me back. And then I get a push notification saying that, you know, you beat my score. And I pull my phone out. I play the game. I try to beat your score. And this will keep on ping-ponging back and forth between us for as long as we play the game.
and kind of keep us both engaged in the game, competing with each other. Amen. So, and achievement challenges are very, very similar. I can challenge you to earn a particular achievement. It all works just in the same way. So what's the issue? Well, you know, let's say that I wanted to send you a challenge.
So I have to tap the button and bring up the leaderboard UI. And then I can tap myself here and it would bring up more detail. And then I can hit this button here, this bubble that says challenge friends. And then from there, it's going to bring up a UI where I would pick the friends I want to challenge with this particular score. And that's just how it works. It's fine. And again, that's kind of the way that most games work today. But the issue is really just the exact same thing that I said in the last section. You want to try and find ways that you can bring this flow up closer to the user in the gameplay itself. So here's some ideas for how you can do this. You know, the first idea is actually very simple. If the game is over and I've just for the first time beat one of my friend's scores, that's an ideal person to send a challenge to. So the game could recognize that that's the case, that this has happened, and then offer a UI just to send a challenge to that one person right then and there, right? And the second idea, let's say that I've received challenges.
Well, of course, you know, the game should really provide some indication of that when I launch, you know, some indicator as I come into the game saying that there's challenges that are pending for you. And then third, let's say that I'm playing the game and I've beat, I'm trying to beat a particular challenge that I've received. Well, you know, really think hard about how you could show that challenge to the player during the gameplay as some kind of a, like as a time marker or some kind of a pace marker as the player is in the game.
And the specific thing I mean there, or the idea that I have in mind, is like when you're watching swimming during the Olympics, or downhill skiing in the Olympics, and you see, for example, the world record pace as a graphic that's overlaid as the swimmers are going. And, you know, you can see as you're watching on television, of course, you're getting the feet of the swimmers, but then the, you know, somebody has overlaid this pace marker that's coming along with them. And that really adds this tension to watching, you know, to watching the event. But the same thing could be done in your game as well. If you have a time-based game or something where, you know, a racing game or something, and somebody has sent the player a challenge, let's say it's a road racing game.
you could show a stripe moving along the bottom of the road that is the pace of that challenge. And then the player is going to be really motivated to try and beat that. So those are some of the ideas here. Now, the ingredients of doing this are actually very similar to what I just showed you a minute ago. We have the GK leaderboard, which can download score data for the local player and the friends, just as I showed you a couple of minutes ago. This is what you would use if you want to issue a challenge. You would be keeping track of where the player is relative to their friends. You can use GK score and GK achievement.
Of course, that's how you post scores and achievements into your leaderboards or into the achievement system, but you also use those same objects to issue challenges to the player's friends. So there's a built-in UI that you bring up with challenge-composed controller with players, a list of players, and a message, and a completion handler. And then on the -- that's to send challenges. To receive them back, there's these objects, the GK challenge and its subclasses, score challenge and achievement challenges. That's how you track the ones that you've received. And there's a class method, load receive challenges with completion handler. That's stuff that you should do when the game starts up to see if there's anything that's out there.
But now, so here's a quick example of this. Let's say that I want to just find out, like I finished the game, and I want to find players that have a lower score than what I just earned. So I can do that here. So I'm going to start out. I'm going to go get the leaderboard data, just as I showed you a couple slides ago. I create the leaderboard. I would set it up. That's the dot, dot, dot.
I would go and fetch those scores. So, so far, it's the exact same code. Now, once I have that array of scores, it's pretty simple for me to go through the array and find the scores that are lower than mine, than the one I just did. You know, one real easy way to do it is to set up an NS predicate. So here, an NS predicate with format. I specify that the value is less than what I pass in, which is the score I just earned. And I can then use an S array method, filtered array using predicate, you know, to give me back a new array just with the scores that are lower than mine. And probably the first element in that array is gonna be the one that's closest to mine, and that might be who I would issue a challenge to, right?
And so then I could have some code that's gonna go off and pull that apart and send off the challenge to that player. But so that's number two. Think of ways that you can bring challenges up into the primary UI of your game, either for sending challenges or for challenges that that player has received.
Okay, and here now is number three, which is to manage your leaderboards. You know, I'm sure that you guys have all seen something kind of like this. Here is the all-time top leaderboard for my awesome tanks game with a lot of players. But, you know, if you take kind of a closer look, you see a lot of this. You know, what is this? Well, 9 quintillion, 223 quadrillion, 372 trillion, et cetera, right? So what is this number? This is int64 max. It's the largest signed 64-bit integer. And so which is, of course, the biggest score that can be submitted to Game Center. So it's kind of doubtful that people are really earning this score. Instead, they're probably finding some way of just injecting this into your games. So this is a problem.
And what it goes to is that you really want your -- your goal here is actually to be able to use your leader board to drive player engagement. But people are cheating and posting fake scores to your leader board, which kind of breaks that flow. So we need ways to get rid of that. And actually now we have three great different ways that you can do that. So the first is something that already existed. I know that not many people are using it, because any time I see nine quintillion, et cetera, I know they're not doing this. And what it is is this. In iTunes Connect, when you go and you look at one of your leaderboards that you've set up, there's an item there called the score range that you can set. And this, you enter a low value and a high value. And any scores that are posted to that leaderboard outside of that range aren't going to show up.
And it's even better than just, they're not just like thrown away. They actually get stored by the service and act, if they're outside of the range, and act in a way as a honey trap, trapping that user with a high score that is outside of the visible range for your game. So in a way, you're kind of like defining the range of visible light in your, you know, the bandwidths of visible light in your game.
And if somebody posts something in the ultraviolet, they're cheating, but nobody will ever see it. Right? That's how this works. And it's very powerful, and you can set this up for every leaderboard. The second thing is that now in iOS 7, we are signing score submissions as they travel between the Game Center daemon running on your device and the Game Center service. So here's our tank game again. You know, if it's -- if it is posting a legitimate score here, that's going to go up, and the game center server will check the signature, and of course it's valid in this case, so it will go through. But if somebody is a man in the middle, and they end up hijacking that and posting a bogus score, the signature is not going to match, and we will just not accept that submission.
So that's the second thing. It's something on our side. Now, the third one is something that was just added and is actually really powerful. So we are now providing a way for you, the developer, to manage your scores, manage your leaderboards from within iTunes Connect. So you can go into iTunes Connect today and look at the top 100 scores that are on your leaderboard, and you can delete them. if any are invalid, and you can even block the user that posted them. So, let's go and this is available to you already.
And actually, a lot of you probably got an email from iTunes Connect just in the past week or two talking about this. So, let's talk in a little more detail. If you delete a score, you know, you're just basically going and kind of cleaning up your leaderboard. There's just a button that you can hit.
Delete the score. Okay. Confirm. And it's gone. So, if you do that, it's going to remove that score from just that one leaderboard. And of course, that player could come back the next day, play again, and post, you know, that same score or whatever to the leaderboard, and that's going to show up just like normal. And it's only affecting this one leaderboard in your game. So, you know, if there's any others that need to be cleaned up, you would have to go and do those as well. But that's still very powerful. You know, you're able to just go in and clean up those leaderboards. Now, the second part, though, is blocking a user. So, if you have somebody who is repeatedly, you know, repeatedly posting bogus scores to your leaderboards, well, now you can go and you can block them from submitting anymore. So, once you do that, once you block a user, it's going to remove their scores from all of your leaderboards for this game, and it will prevent them from posting any new scores into any of your leaderboards from that point forward. And note that it also applies to game groups. So if you have your app grouped between, for example, iOS and OS X, or you've set up a free version of your game and a paid version of the game in the same game group, then if you block a user, it's going to be across that entire group. But so this is very powerful, and it's, you know, something that we expect that you can use now to eliminate a lot of the abuse that can be happening with leaderboards.
But just bear in mind, you know, this is a big power to have. It's a pretty big hammer. And, you know, use this wisely. We're giving this capability to you, the developer. It's your game. But of course, you want to only use this in cases where you're certain that you know that somebody is abusing your scoring system.
But so that is it. That is number three. Manage your leaderboards. Okay. And that takes me to the end of Game Center. Just some great ways for you to drive some increased engagement in your game and to, you know, kind of go beyond what people are doing right now with Game Center. But so next, I want to just completely change topics. We're done with Game Center, and now let's move on with game controllers.
Okay. So game controllers. You know, so we announced back at WWDC that we'd be adding support for physical game controllers into iOS 7. And I mean, this is very exciting, I think. Now, I want to go into a lot of the detail that's involved with this. So what we are delivering is really coming in two parts. The first part is a spec that we're providing to the manufacturers of game controllers who are in the MFI program. So this provides them with the spec defines a standard way for third-party accessory developers to build controllers as part of our made-for-iPhone MFI program. You know, the spec is going to define all the physical and technological requirements of the controllers, you know, how the controls are laid out, how they behave, the data transport between the controller and iOS, and so on.
And the real goal of the spec is very specific. It's to ensure that when customers are in a retail store and they see that MFI label, that they can be very confident that they're looking at the box and they see that with a controller inside. They can be confident that that controller is going to work with games that's on the App Store that are supporting game controllers.
But so that is the first piece, you know, a spec to get consistency among the different device manufacturers. The second piece is for you guys, probably. It is a framework for developers like you to be able to add support for game controllers into your games. Right? So it's a pretty simple API. It lets you detect the controllers, connect with them, and then just go and sample the inputs that are coming off them. And, you know, the goal of this framework actually is, well, it's consistency. You know, we want for developers to be able to take advantage of one consistent central API for all of the controllers, regardless of vendor, so that you can all just kind of focus on making great games instead of dealing with vendor-specific differences in the controllers.
But so now, let's go into a little detail. There's three different kinds of or three different classes of controllers that are supported by the API. And here's the first one. So this is called the form-fitting standard gamepad. So form-fitting means that the controller itself physically encases your device. Your phone just snaps into the controller. So, while you're playing, you can be mashing the buttons, but then it's also very easy for you to touch the screen with your fingers or use device motion to control the game as well at the same time. Now, that's form fitting. Standard game pad, what that refers to is the buttons, the control layout. So, a standard gamepad has a D-pad on the left, the A, B, X, and Y buttons over on the right with those colors and that pattern, and then two shoulder buttons that are on the front.
Okay, here's the next one. This is called the form-fitting extended gamepad. So, again, this is form-fitting. The device physically snaps into the controller, just like the first one, but what's different here is that instead of standard gamepad, it's extended gamepad. So it adds a couple more controls -- two thumbsticks, one on the left and one on the right, and two triggers down below the shoulder buttons.
Okay? And then here is the third class of controllers. This is called a standalone extended gamepad. So, here the difference is that it is standalone. It is not physically attached to your device. It could be connected over a wire, but more often it will be connected wirelessly over Bluetooth. And the expectation with, you know, with a standalone controller, then is that all of the game input is only being taken from the controller itself. You're typically not also interacting with the device or using, you know, the gyroscope and so on. Now, standalone extended gamepad. So, the controls are all the same as the form-fitting extended gamepad you just saw.
Okay, so those are the three kinds. Now, as far as the controllers themselves, you know, we mentioned back in June that we're working very closely with a number of manufacturers in our MFI program who are building controllers, like Logitech and Mocha, and, you know, now that work has been paying off, and there are several controllers that are now available in retail. I have a couple of them with me here today, but so now let me look at how, you know, just how to integrate these controllers into your games. So the main class that you'll use for this is called GC controller. This represents a controller that is connected with your device. And, you know, you use the same class for all of the different controllers regardless of vendor.
So what a GC controller is going to provide, well, kind of at a high level, these three things. Methods for finding controllers. So it can give you the controllers that are currently connected. It'll give you notifications for a live connect and disconnect. And there's methods there to help you discover any wireless controllers. Then it'll give you access to all of the input data off the D-pad, the buttons, the thumbsticks, triggers. And also some information about the controller itself. We'll tell you its profile, meaning whether it is standard or extended gamepad. We'll tell you whether it's attached or standalone. We'll tell you the vendor. We'll tell you a player index for some lights on the front, pause button state, that kind of thing. Okay? So that's what the class provides. Let me just kind of show you how you get connected to one of these. Really, just there's a class, an array on the class called controllers, and that's the main entry point to using this class. It'll be empty at first, and then it gets updated, whenever controllers are connected with your game. So let me describe visually kind of the process you typically go through to set this up. So, you know, it's expected probably that you will have a method in your app called setup controllers or something like that that you'll use as the central location for any time there's a controller change. You just figure it out from there. And within that method, That's where you can go and look at the controller's array, see what's there, and then act accordingly. Okay? But then probably in your application did finish launching with options, there's a few things you probably want to kick off from that point. This is where you can set up notifications for connections being disconnected or connected or disconnected to calling to set up controllers. And it's also where you will kick off discovery of any wireless controllers. And so you can kind of see this flow from left to right. We start wireless discovery. And then whatever controllers are found, be they wireless or connected, form-fitting, will get a connect notification. The connect notification will call your setup controllers method. And then within that method, you can go and look at the array and see what's there and then react from that.
So here that is in a bit of code. We're in application did finish launching with options. We start out just, you know, here's some code first to check whether the controller class exists on the OS version we're running, like Dave was showing you earlier today. And then assuming it does, here is where we're setting up those two notifications for connect and disconnect. And then here I start, kick off the search for any wireless controllers. And really, setup is just kind of that easy. You know, here's our setup controllers method. All I'm doing in here, this is fake code, right? It's just going and looking at that array, and then I would-- the game would respond accordingly, maybe moving input over onto the controllers and so on. But really, in a way, that's the majority of all you have to do for-- to support a controller.
But so now the assumption, okay, we have a controller connected. I wanna show you how you read its inputs. And so again, here are the three classes of different controllers, just kind of drawn schematically. And so to read the inputs, you have to understand the concept of the controller profile because profiles define the controls that are gonna be on the actual buttons that are on the devices. So let's recall from earlier, We have the standard gamepads and extended gamepads. Okay, so now let me take a closer look, standard gamepad first.
Okay, so a standard gamepad has these four buttons, A, B, X, and Y, and their type, which I'll go into in a second, is GC button input. The left and right shoulders that are on the front of the gamepad are also GC button input. And then over here on the left, you have the D pad, and that's a different type, GC direction pad. Okay, so hold that thought. Here's the other kind of controller.
Looking at the extended gamepad profile now. Okay, so this has all of the same controls as the standard gamepad. It is a pure superset, always. So it has A, B, X, and Y, left and right shoulder, and a D-pad, always. And then it adds the left and right thumbstick, which is of type GC direction pad, and left and right triggers on the front, which are back to buttons, button inputs again. Okay. So, just to have run through that now, we see there's really just two types of inputs. We have button inputs and we have direction pads.
So, looking at button inputs, we have So this is used, again, for the face buttons, the shoulder buttons, and the triggers. And this type is sort of overloaded. There's two different ways that you can get values out of one button, for example. We can provide a Boolean value for whether the button is pressed, kind of its classic button state. Just coming back as a Boolean. But also, all of our controls are analog, including the buttons, including the triggers, and so on.
They are all pressure sensitive. And so we can get a float value out of any of these buttons normalized from zero to one. Okay? And you choose depending on the needs of your game. Now, again, they are all pressure sensitive. regardless of whether it's a standard gamepad or extended gamepad. All of the controls are pressure-sensitive.
So that was a button. Now, that other type was a direction pad. Again, this is used for the D-pad and the thumbsticks. And again, this is another type that is kind of overloaded. It can be treated in two different ways. The D-pad can either be treated, and the joysticks, as four separate buttons, up, down, left, and right, of type button input, or they can be treated as two axes with a new type controller axis input. you know, either the X and the Y axis there.
Now, if they are button input, then they are treated the exact same way as what I just showed you. You know, all pressure sensitive, et cetera, et cetera. Or you can just get the classic button state as a Boolean for each of those. But if you're treating them as axes, then let's look at this type. Controller axis input. So this is very similar, but it's just measuring the movement along an axis and reporting values back to you from negative one to positive one.
Okay? And what we guarantee, like for the thumbsticks and so on, is a guaranteed range of, maximum range of a unit circle within a square. So very simple. And note that the framework also automatically handles calibration. And the spec, we handle calibration, you know, kind of at the vendor level, so to speak. So your application, if you're moving code from another, from an application where you had to code to controllers manually yourself, you may have added code to deal with calibration and dead zone and so on. You no longer need any of that when you're running on iOS. All of that control is just built directly into the framework. Now, if you don't know what this is, it's just when you are using a joystick, you kind of want to make sure that the values at the center are really reported as zero and not just barely off zero. And so that when the user is just kind of resting their, you know, their thumb or whatever on the joystick itself, that it's not-- and not moving, that it's not just barely kind of inching the character along or something. So there's a little realm right around zero where we keep reporting zero and then start reporting after that. So we handle that within the framework.
Okay, so now let's talk about reading the values. So now you know the types, you kind of know how the buttons work. There's three different ways that you can actually read the inputs when somebody hits a button. First is that you can just read them. They're properties on a class, and you can just go and get the value and pull it directly. The second way that you can read those values is that you can register a callback that will be, And you'll be called any time the particular value that you're observing is changes. Or the third way is that you can take a snapshot, you can ask the controller for a snapshot of all of its values, and then just read them from the snapshot. So here's an example of that first technique. It's probably what you'll use most often, so that's why I'm showing it here. So the assumption here is that I'm already connected to the controller, and I already know that it's an extended gamepad, so I'm just going and getting the handle to that profile. And then here is where I just start reading the values. So I'm saying, okay, the profile, if the left trigger is pressed, launch missiles for my ship. If the right trigger is pressed, then read the analog value of how hard the pressure on that trigger and use that as a rate that we will fire the lasers. at. Right? And then just in the same way down here, apply thrust. Okay. So I'm going to read the left thumb stick the value of the Y axis from negative one to positive one. And that's going to determine my thrust. Okay? For my spaceship. Now, I want to digress for one second, though. Because there's a few games that have started to come out that are using controllers. And I want to relay a best practice that we're starting to see and make sure that you follow this as well. It has to do with is pressed. So, you know, we calculate within the framework itself as, you know, there's a particular threshold of pressure that has to take place before we will say, okay, that button is pressed. Now, I don't know offhand what that value is, but here's the point is that some people who have written games that are using controllers and had manually supported other controllers in the past, maybe they're porting that code over onto iOS now, a lot of them had manual code that would figure out whether the button is pressed. And some of them set the threshold at 50%, some of them at 40%, you know, 0.4, some at 70. It's very inconsistent. And so what I want to say is if you have code like that or you're in that situation, use our built-in is pressed as the Boolean logic that you need there so that we can get consistency across games for how much pressure it takes to pull the trigger on a controller. Okay. Now, let me come back off the digression. So that's how you read the element values. Now, there's just a couple more controls that I want to cover. Here's the first one. So every controller has a pause button. button. Okay? And so in handling the pause button is required if your game supports controllers. Now, most of the time you should just treat the pause button as a toggle. You know, if assuming that the game has kind of an active state and a paused state, well, then the pause button should just toggle between, you know, whatever is current and whatever the other option is. But, of course, you also need to consider the current state of the user playing in your UI. Like, if they're just looking around at an option screen or other places like that, then probably in those situations, the pause button should not have any effect. And in particular, the pause button should not suddenly, like, leap them back into the game from some unrelated screen.
Okay. So, that's the pause button. Here's a quick example. If you go back and you think of that setup controllers method that I was talking about earlier, here's where you would add the pause handler. It's very simple just on the controller that's connected, you can set up a controller paused handler. It takes a block and then within that block, you just do whatever you're going to do to handle the pause button being toggled.
Okay, so that's the first. The other one is the player indicators. So on extended controllers, these are mandatory, and on standard, they're optional. I'm sure you can all see up here, there's four little lights up on the face of the controller that show the player index. And we provide you with an API to get and set those lights. And they'll be persistent for your game. And we actually recommend that you set them. So the reason is set the lights, for one thing, so that the user immediately recognizes or knows that your game is recognizing the controller and the control input is going to be moved over onto the physical controller. But then also, if you have a game that supports multiple controllers, you know, like, because they could -- you could have multiple wireless controllers connected to your game if your game supports that, then you can use this and, you know, you would have something in your game that would let the players decide I'm player one, I'm player two, et cetera, and then you would set those indices accordingly on the controllers themselves through this API.
But OK, so that is the player indicators. So now, where are we? I've shown you how to connect to controllers, how to read their inputs, and a few extra things that you need to handle. So now I want to wrap up this session just with some advice and some best practices, essentially, for really ways to think about how you can use controllers within your game and make it work with controllers.
And the first piece of advice is really just to really think through your controls. You know, and comparing to the controls that you have today already. You know, touch and motion are really, they're ideal for games that support direct interaction, like John was talking about this morning. You know, taps, gestures, and swipes. And think about controllers as a way to augment that.
especially in games that need tactile feedback for an indirect interaction model, right? So games that need really precise timing to do really tight moves or perform different actions. And think about the case of a form-fitting controller. Having touch along with form-fitting put together can really kind of provide you with ideal circumstances for both situations. You know, really precise physical controls for indirect manipulation, plus, you know, being able to still do direct manipulation just with your, you know, with the user's hand or with device motion right on screen.
Now, the second piece of advice, some best practices. Something to remember is that your game cannot require a controller. Controllers are always optional. Every game on the App Store must be able to work without a controller being attached. And your game should support both profiles, both standard gamepad profile and extended gamepad. And you really have to think about how maybe the game will behave differently with the existence of thumbsticks versus without, when you only have a D-pad and buttons and the shoulders. But be sure that you support both of those cases so that players can go and they can know, no matter which device they buy, it's going to work if you say that you support controllers.
And, you know, also think you should support both form factors, both the form fitting, which is both of these up here, but also the standalone controller, which I haven't shown you one of, but we have one over in the lab to look at. You know, think about how your game should behave differently depending on whether the user can touch the screen or not. And then last is don't forget to include support for the pause button. You know, in most cases, you should just treat it as a toggle. You know, pause if you're active and go active if you're paused.
Two more things. So, you know, another thing to think about is just how your game should react to controllers being connected and disconnected, right? So, if you detect that a controller has been connected, meaning you set up a notification and there, boom, there's a controller. Well, you should treat that as an expression of the user's intent. So, enable the controller, move your input, you know, move to controller-based input. And perhaps think about changes that happen in the game. You may have a control overlay that you put on, you know, that you put on screen. Maybe that should be moved aside or maybe off screen entirely when the player is connected with a controller. And also light up that player indicator LED so the player knows that, ah, I'm using the controller buttons now. Now, when a player disconnects, also that may be an expression of intent or it could be unintentional. So in case it was unintentional, an unintentional disconnection, that's someplace where you should always pause the gameplay on disconnect. And then of course, move the controls back to your regular on screen or device motion controls.
Okay. So that's those. And now just a couple of closing thoughts. One more time. Again, really think it through how you would support these different profiles and different form factors. You know, the standard gamepad adds 10 new buttons to your game. And the extended gamepad adds 14. So you need to be really clear about how you will design your game to those inputs, or whether you will even.
But make sure that you have a really solid gameplay experience worked out if you're planning to support controllers. Because I would say it this way. This is your UI. It is the thing that matters most in terms of your gameplay. So it's got to be fantastic. Really go and test with the controllers. Get them from the retail stores. And keep working on with it until you are so happy with the way the controls work that you know that you are ready to ship. But so I think the opportunity is there. I think that players are going to have a great time with controllers. And hopefully they'll pick them up from the retail stores and we'll see a lot of your games supporting them. I'm really excited about it. But so that takes me to the end of the session. For more information, you're welcome to contact me. my email address or come find us in the developer forums. So thank you very much.