Graphics, Media, and Games • iOS • 49:54
iOS delivers an incredible collection of graphics, media, and integrated technologies for developing cutting-edge mobile games. Explore the frameworks and technologies that enable you to create the most imaginative games possible. Dive into expert techniques to harness the full capabilities of iOS and create rich gameplay experiences for your players. This is the first of two sessions covering the techniques for iOS game development.
Speaker: Nate Begeman
Unlisted on Apple Developer site
Downloads from Apple
Transcript
This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.
Good morning. I'm Nate Begemann. I'm here to talk to you today about iOS game technologies and some of the fantastic new things we have for you in iOS 5. It is a fantastic time to make games, and I'm thrilled to see so many people here in the room today.
We have seen you guys have such success already writing games for iOS, and we have some wonderful new things to share with you here today. And we're excited to see you guys adopt the things that we'll be unveiling and write even awesomer games. Today in Part 1, we'll be talking about four technologies.
First is Game Center. Game Center lets your games connect with your customers and helps them play with their friends and make gaming an awesome social experience. The second thing we're going to talk today about is the cloud and how cloud storage is like the most amazing thing for games ever. And I'm super excited to show some examples of how we're going to use that today.
The third thing we're going to talk about is GL Kit and how we're bringing the power of OpenGL ES 2.0 to your games, even if you're not an OpenGL ES expert. And God knows I'm not. And the last thing we're going to talk today about is AirPlay and how we can get your game on more displays and in front of more people.
In part two, the session after this, we're going to talk about game design, and some of the things you need to think about up front going into writing your game. We believe that everyone has a great idea for a game in their head, so even those of you who don't have a game on the store yet, you'll definitely want to stick around for that.
And you'll learn about great audio design in your games, how to handle game design for iOS devices in such a way that the input is natural and easy for people to use, the things you need to think about writing a quality game for iOS, and all the little details that go into that, and lots of other cool things that Graham will share with you then.
So let's talk about Game Center. As I mentioned, Game Center is like the hub of the social experience for games on iOS. And in iOS 5, we have a few cool new features that we've added directly to Game Center. The first is profile photos. And profile photos is actually, you know, it doesn't sound super exciting, but it's really cool because when you get that list of your friends up there and you see their photo, you immediately connect with that person and say, like, whoa, that's my friend Matt. He's right there. I'm going to play a game with him. Rather than dealing with everything through, like, gamer tags or that kind of thing.
As you saw yesterday, we've built game recommendations right into Game Center. So now more people can find the awesome games that you've written right in Game Center after they've played whatever game they're playing now. And we think that this is a great way to keep people coming back to games in Game Center and help them keep finding new great games that you're writing. And the final thing we've added is friend recommendations. You may not know that your friends are on Game Center. There's 50 million people, as you heard. And so we'll help you find players to match up with your customers.
So that they can keep having great experiences in your games. I know one of my favorite things about gaming is that it's competitive. And so I spend a lot of time looking at leaderboards in Game Center and trying to, you know, beat my friend's time in Tiny Wings and that kind of thing. And so we've added some great things to keep people interested in leaderboards in iOS 5. You can see the people in leaderboards. You can add them as a friend directly.
You can rate games. I know one of the things that you guys are super interested in is getting that awesome feedback for your games that you so, you know, excellently deserve. And so now users can rate your game right in Game Center. You don't need to pop up alerts saying, please rate my game. And so, you know, that's there. And finally, we've added custom category icons to the leaderboards themselves.
And this is a way to let you just sort of distinguish the categories for your app rather than use the defaults that every app uses.
[Transcript missing]
So we're really excited to see what you guys are going to do with turn-based gaming. But just to sort of refresh your memory, we're going to walk through word for word and show you how turn-based gaming works.
So here you can see we've got our iPad up and we've got the Match interface. And, you know, this is sort of the standard Game Center interface you can see. Here you can see right at the top, your game gets to specify how many players you want to support for the match.
Word for word supports two to four players. In the seed build you got, you support up to four players, but in the final iOS 5, we'll support up to 16 players in turn-based gaming. So you can really go nuts with this. And so down here, you can see we can either auto-match a player or you can invite some friends. So let's click that button.
And here you can see, you know, we've got a list of our friends with their profile photos. You can see, like, awesome. I want to invite those people because they look great. And so we'll click two of them and add them to our game. And then we'll hit the next button.
And so here you can see they've popped right up in our little match that we're about to start. And if someone wanted to, they could rate your game right here. So we'll go ahead and get started. So as you saw yesterday, you know, you've got your familiar game paradigm of letter tiles on a board. And we're going to place them down and, you know, score some points. This is where the tiles came from. There's the word. And we're going to hit our next button here. And we spelled Ruby for a bunch of points, which is awesome.
And so then, when I hit that next button, it's going to send a notification to someone else, and it's going to appear at the top of the screen with the new notification user interface, and of course, they're going to accept. And so then it's going to bring up Game Center, and it's going to say, hey, someone is trying to invite you to a game. And so all the pending matches that they have are going to show up here. And they're going to click it, and then they're going to play a word and hit next. And their word was worth fewer points than our word, which is awesome.
And so then the notification passes to the third player. So as you'll notice, the notification only shows up on the player whose turn it is. You do not get a notification when transfer controls between two players who are not you. So your apps can poll for that if you want to show some kind of notification as to whose turn it is currently, but you won't get a notification from Game Center for that. So the third player is going to take their turn and hit next. And now you can see instead of getting a game invite notification, we actually get that turn notification from Game Center a little differently, but that's what it looks like.
So now that you've, you know, had word for word refreshed in your memory, let's look at some code and, like, you know, the basics of turn-based gaming and what that looks like. Well, Game Center and turn-based gaming is all based on this turn-based match object. So you get a GK turn-based match, and just like any regular Cocoa object, you're going to, you know, alloc and init that, nothing special.
And most of the interaction through your app is based on this turn-based event handler. And so wherever you want to put the game logic for your app, you just have to, you know, find that class and set it as the delegate of the turn-based event handler. And then you'll handle three kinds of events.
You're going to handle invites from other people. You're going to handle turns, so making it become your turn. And you're going to handle the end of the match. So if the other person decided that, you know, they were scared because you had an awesome score and just declined your invitation, or if, you know, you won or they won, you would get an end-of-turn notification. So in order to transfer control to somebody, let's look at the basic steps you have to do. First, you have to decide whose turn it's going to be next.
And so, for instance, like the golf example I mentioned, you know, control would transfer to whoever's ball was farthest from the pin. And so you'd call some code to figure that out and get their player index, you know, zero-based, zero to however many players there are minus one.
In the word-for-word example we just threw up, you know, we're going to just, you know, we're going to just rotate through the players. So, you know, that's, like, super easy. And then you're going to take that index and you're going to ask Game Center for the Game Center participant, the GK turn-based participant, who is at that index in the array of players in the match. And that object is what you'll use to communicate with Game Center to say, hey, I want control to go to this person.
And let's see what that looks like. So in our game where we had that arrow that transferred control to the player, you're going to ask the Game Center for the Game Center participant, the GK turn-based participant, who is at that index in the array of players in the match.
And then you're going to ask Game Center for the Game Center participant, the GK turn-based participant, who is at that index in the array of players in the match. And let's see what that looks like. So, you know, we're going to ask Game Center for the Game Center participant, the GK turn-based participant, who is at that index in the array of players in the match.
And let's see what that looks like. So, you know, we're going to ask Game Center for the Game Center participant, the GK turn-based
[Transcript missing]
So now that we have this data, this NSData blob, it's 4K or less, basically what we're going to do is call that GKTurn-based match object that we've stored in our game class and say, end turn with next participant, and we're going to hand it that participant that we generated, the person whose turn it is next. We're going to hand it our game data that we calculated, and we're going to give it a block for a completion handler.
And just the important thing to recognize here is that this block runs asynchronously, and so you won't necessarily have this block run microseconds after you make this call. It may come back at some later point and say, hey, there was an error, I couldn't deliver this. Hey, there was an error, the other person actually resigned earlier on their turn, and you're just figuring this out now. Or there might be no error, in which case everything's cool.
You remember when we registered our game class as the delegate? This is one of those functions in that protocol that you need to implement. So when it's your turn, this function will get called. And again, you're just going to do whatever you need to unpack that turn data, and then update your game state to take that turn, and refresh your UI, showing that that turn has been taken. It's really simple. I mean, there's no sort of standard code in here. You know, it's going to vary based on your app. But it's really a pretty simple action.
So, like I said, you can send up to four kilobytes of turn data. And that doesn't sound like a lot, but it actually works for a lot of games. If it really can't work for your game, each match does have a unique ID. You can use it to index into some database or use it as a key for cloud storage or whatever you want to do. And again, you only get notifications when it is becoming your turn or someone is inviting you. So it will become your turn when you accept the match.
You have to poll Game Center if you want to find out that transfer has controlled between two players who aren't you. So if all this sounds like something that you can't wait to put in your app, we have four sessions coming up later in the week on Game Center and all the ways that you can incorporate it into your app and use turn-based gaming. We hope that you will go to those sessions because we think that Game Center is actually pretty amazing.
And not only makes your apps better, but I as a game player love playing Game Center games. It keeps me interested longer. So, you know, again, Game Center -- gaming is about not just playing games, but about playing games with your friends. And so Game Center really helps with that. You've seen the new leaderboard features because, you know, competitive gaming, keeps people interested.
Achievements help people get through and find all the content that you've spent so long putting in your game. And so by adopting achievements, you can make sure that they're driven to go find it and keep playing your game as long as possible. And you can see with turn-based match, we've added an interesting new way to add multiplayer experiences to gaming in a way that works for casual gaming and that I can just pick up my device, play a turn and put it down and not have to be -- you know, carve out time in my schedule to, like, have a match with somebody. And so, again, we are super excited to see what you guys are going to do with turn-based gaming.
My favorite part of this presentation is actually iCloud because it solves so many problems that are actually fairly specific to gaming. And, you know, I'd like to run through a few of those with you. But first, you know, just sort of an overview of iCloud. It does automatic syncing. You don't have to tell it, please push my data up to the cloud now or please go get some data. The storage is per user. So you saw the turn-based match data was 4 kilobytes, and that was between users.
Cloud Storage is for one user, but it can span multiple domains. And so you wouldn't use Cloud Storage to say, I want to send, you know, my friend some data, but you'll see why this is perfect for gaming in a second. You can store data between devices. So, for instance, if I have -- if I'm playing a game and I just, you know, got to a new point in the game, passed some hard boss on my iPhone on the bus, and I'm like, awesome, and I put that down, and I go to work and I pick up my iPad, and I'm like, oh, man, I would have to play that all over again.
Well, with the cloud, your game state can just be automatically updated between all your devices, so you can move from device to device and never lose your place in a game. You can also store data between different versions of the same app or even between two wholly separate apps.
So, for instance, if you have a free version of an app, you can And you -- and someone buys a paid version, all their data can go with them because you can use the same cloud storage identifiers for those two apps. And so, you know, this is something I think users will really love.
So when they buy an app or maybe you have a collection of games where you all want to share some shared state, cloud storage will allow you to do that. And it works between platforms. So the focus of this talk, you know, is primarily on iOS technologies. But this works on Lion, too.
And so you'll see how these classes can be adopted. You know, for instance, if you had some, you know, role-playing game on an iOS device and you wanted to write a, you know, my backpack organizer app for the Mac, and they could go in and arrange their items and buy potions and stuff like that.
And then when they picked up their iPad again, it could all just be there. And so, you know, really much like turn-based gaming, the only limit is your imagination on using this kind of stuff. So let's look at some code and just, like, how super simple this is to use.
Well, the first thing you're going to do is get a connection. And thank God for Xcode 4's auto-complete, because this class is kind of long. You've got NS ubiquitous key value store-- and just wait until you see the notification name-- and so basically, you're just going to ask for the default store, and you'll get a connection to the cloud. And you'll keep using this object to refer to your cloud connection throughout the lifetime of your app.
And so just sort of the most basic thing, the easiest way to use the cloud, are key value pairs. Yesterday, you saw a lot of cool examples about document-based use of the cloud. But I think key value pairs are really easy to use. And so if you just wanted to set some flag in your app, you could say, hey, the player has set true for my awesome bool key, or whatever you want that to represent. You know, it's a really simple API.
So let's talk about specifically how it might apply to games in the Game State example. Here you can see we're using NSKeyed Archiver to pack up Game State. And we'll talk about that in just a sec and why it's awesome and why you should adopt that probably for structured data like Game State. But here you can see we're just generating an NSData, so just some blob of bytes.
And unlike turn-based gaming, you know, there's no 4K limit here. You know, the user has some amount of free storage on the cloud, but, you know, really just take whatever space you need to upload that. And again, you just got a key value pair mechanism here. We're going to set that data for my red Game State and away to the cloud it goes.
So I mentioned, you know, this NSK archiver thing. Some of you may not be familiar with Cocoa. And so this is something that's come across from AppKit on Mac OS X. And basically it's a way for you to add a platform-agnostic data encoding scheme to basically any class you want.
And so whether you're transferring data between a 32 and 64-bit device, between an iOS device and Lion, it's not even Lion specific, but it is just really easy to use. Basically, your class, your Game State class, is going to subscribe to the NSCoding protocol, and you're going to implement two functions, encodeWithCoder and initWithCoder.
And basically, this is a way to turn your class into an NSData object and then inflate an NSData object back into... your game state. So what does this look like? Well, encode with coder is going to be called anytime someone calls, you know, archive data. And so you get an NSCoder object passed to you, and you can just basically enumerate down the member variables in your class using whatever the appropriate encode routine is, encode integer for a standard, you know, like C int type, encode data for NSData, encode dictionary for, you know, key value dictionary, that kind of thing. And you reference, you know, your member variable and then the key you want it looked up under.
And you know, the same, as you'll see, we're going to unarchive one of these things in a second when we come back from the cloud. Enit with coder is going to be called. Remember to initialize your super class and then go ahead and get your values back. It's just really easy to use. use.
So let's register for this cloud notification so that when I'm playing a game on my iPad and my iPhone is still awake or whatever, we can be told that, hey, the data changed and you should go update it. We're going to get our default notification center, which is just the standard Cocoa Touch way of registering for notifications. My app class is whatever app class you want to handle that notification.
Handle sync data changed is the function we're going to use to respond to the notification, and we'll see that in a second. And here's that great notification name. The NS ubiquitous key value store did change externally notification. So it's only 56 characters. And then we're going to pass that Cloud Store object to it in case we wanted to refer to it.
later when we're handling the notification. So this is what's going to get called. And you can see, again, you know, this NSNotification, you can pull that CloudStore object out of it, and then use it to go pull out the blob of data that was encoding my rad game state.
And so that's going to pull down that data out of the Cloud object that got synced. And then you're going to call NSKeyedUnarchiver, unarchive object with data, and that's going to call initWithCoder with that data and basically it will inflate back to your game state. And we think that this is just a really easy way for you to use the Cloud to solve a basic problem that a lot of people have with gaming.
And it will make sort of the casual gaming experience across multiple iOS devices or multiple apps, you know, a lot of people have. So this is just a really easy way to do that. And it's going to be really helpful to you. And I think that's a really good way to go about this. And I think this is going to be a really good way to go about this. So if you're interested in doing this, I'm sure you've seen a lot of these apps. So much better.
So you're probably interested in adopting this. And so there are three sessions later in the week. Two later today. And one on Wednesday. So hope to see you there. And again, you know, I covered, you know, the basic game state life cycle with the Cloud. But just like turn-based gaming, there are so many more ways that you can use this.
If you have app preferences, for example, you know, people have set some kind of gamma in your app. Or they want the Y axis inverted in some flight simulator. You can transfer those preferences through the Cloud to all the devices. You can handle app statistics. And, you know, we hear stories all the time of how statistics keep people super interested in games.
And it's a little different than achievements. But, you know, you can record anything. Like the number of times I have died in Minesweeper on the fourth mine. Or, you know, the number of times I have played poker. Or, you know, anything that may not actually be an achievement or a leaderboard. But, you know, you can make sure that those statistics get across to all devices. People love that kind of stuff. It makes that human connection between them and your game.
You can even do, like, some cool personalization stuff. So you could imagine, for instance, that you have some kind of doodling app or, you know, paint app on your iPhone. And you want to paint up some cool logo for a car and sync that to the cloud. And you can go play your racing game on an iPad.
That decal has already been applied to the car. And you can see the art that you drew right on the hood as you're racing. And, you know, so you can do so many cool things with this. And we're excited to see what you end up coming up with.
The third thing I'm going to talk today about is GL Kit and how OpenGL ES 2.0 can now be made super simple. For those of you who are already writing amazing shaders, that's great. Please keep doing that. We love it. It makes your games look awesome. But this is a way that a lot of you will finally be able to access the power of OpenGL ES without being experts. So it does a number of things.
There's UI Kit integration. So rather than needing to set up OpenGL content as an OpenGL layer in a core animation layer tree, there's now just a standard GL Kit view. You can throw in a view hierarchy like any other Cocoa Touch view, and it'll just take care of presenting the frame buffer, making sure that the performance is good, running the animation loop, all that great stuff. There's a fast math library.
I know we've been asking you for a couple of years now to get off OpenGL ES 1.1 and transition to OpenGL ES 2.0 so that you can untap the full power of the iPad 2 and other modern devices. One of the downsides of that is that OpenGL ES 1.1 actually had a lot of nice sort of matrix math built in, a lot of state that you didn't have to think about.
Well, we've recreated that in GL Kit so that you can just easily transition off OpenGL ES 1.1 to 2.0. Without having to worry, like, how do I write matrix multiplication that will actually perform well on an ARM processor? No, you don't need to know. We'll just take care of that.
[Transcript missing]
It seemed hard to do at the time, and so I went back to this example and thought, how would I look at this code and do some of those same things using GLKit, just so you can kind of see where we're going over the last couple years.
Well, the first thing I wanted to look at was texture loading and how that was actually not that easy to do. So we didn't have compressed textures in this app. We just had, you know, some little colored rectangles and a ball, you know, a PNG of the ball.
Or maybe, you know, a PNG of the earth you could use as the ball, that kind of thing. And so OpenGL doesn't really know anything about UIKit or the rest of Cocoa Touch. And so let's walk through what you had to do to get that image into an OpenGL texture.
Well, first you had to go dig it out of your bundle. So you had to say, "Hey, UI image, go find this resource," and then turn it into a CG image because we're going to need to get the bytes out. And so then we asked Core Graphics, "Hey, how big is this thing?" If I succeeded in getting it, we need to create some storage for it, because OpenGL sucks in all its texture data through arrays of bytes. So we're going to allocate some storage, knowing, of course, that the pixel values are one byte per component and that there are four of them. Then we're going to create a CG bitmap context, which tells Core Graphics how to reason about this data as a texture.
We're going to draw that CG image into it, hopefully doing the right thing. And then we're going to get into OpenGL and say, "Hey, generate me a texture name, bind it to this texture, and then render these bytes into that texture." This doesn't sound like a lot of fun. I didn't like doing it. And so this is one of the primary things that can be made really easy. So this is the entirety of the GL kit doing the same thing.
Basically, we're going to ask NSURL for that bundle resource. So you can say, hey, where is it? We're going to ask GL Kit, which has this texture loader helper class, to say, "Hey, given this URL, give me a texture info object." And that texture info object contains all sorts of stuff, but one of the things it contains is the OpenGL texture ID, referenced by the texture name accessor, so that it took care of generating that texture ID, binding the texture to it, getting your data into it, and you can just use that.
Other things in there would be like the width, the height, the color channel ordering, that kind of thing. You can query this texture info object for any one of those things. So here's sort of our one line of code example, space for readability. But you can see it's really actually pretty easy.
So you don't need to write your own helper class that knows how to do all this stuff and handle error cases. GL Kit will just do it for you. And one of the things I'd like to encourage you guys to do, here you can see in this example that we've been working with PingFile.
But GL Kit actually supports loading PVR to compress textures directly from a bundle resource. So if you have the means to go generate those textures, please do, because they will make the GPU perform better by using less memory bandwidth than a one byte per component texture like Ping. So the other thing you saw that we did was we had that nice kind of spotlight around the ball.
This was actually, you know, I mean, it was a little bit of a challenge to get the ball to work. But we had to load this background texture of bumps. And we had to set that as the input to the sampler so that we could actually, you know, lighten up a portion of it where the ball was. We had to tell GL to use the light program that we'd written, which comprised a vertex and fragment shader.
We had to set some variables in that program, for instance, for the position of the ball, what texture the sampler is referring to, the sampler being the OpenGL way that you sort of index into an image. And then we had to make the GL call to draw arrays to take that vertex data and run the program on it and do our per-pixel lighting.
So here's this lighting program that we wrote, which is so obviously drawing a, you know, 20-pixel light spotlight under a ball. And so, you know, I can walk you through this, but basically all we're doing is figuring out how far any pixel is from the center of the ball and attenuating a spotlight and then blending in that light color with the background. And so this is great.
If you want to do this stuff, you can do really powerful things that GLKit is not going to provide for you out of the box. But for something simple like a spotlight, we do have a solution for you. And so basically all our GLKit effects are referenced through this GLK base effect class. And what you can do is each GLK base effect can reference a couple textures and a couple of lights.
And so we're going to say we want per-pixel lighting. The default would be per-vertex lighting. But we want a nice spot on one texture. So we're going to set some light properties here. We're going to turn on the first light. We're going to position that light over where we want the ball to be. And we're going to say, hey, we want the cutoff to be 20 degrees. By default, the cutoff is 180 degrees, so you get sort of this general directional light. And here we're just sort of narrowing that down a little bit.
And so basically then we're going to put in our texture that we want lit. We're going to call prepareToDraw, which sets up all the shader variables inside the GLKitBaseEffect. And then we call our drawArrays call again. And here you can see it's, you know, a much more friendly -- you know, it's not any more powerful than what we did before, but it's just sort of much more friendly, cocoa-y way of getting the power of OpenGL ES 2.0 into your app for doing interesting drawing effects. The final thing I'd like to cover in GLKit is this render loop.
So as any of you who've tried to implement an OpenGL ES app before have probably noticed, the first thing you do is go to Xcode and say, I want the OpenGL ES 2.0 template. And what you get is a bunch of files with four or five pages of code that you are generally scared to touch because it looks like it does magical things. And so, for instance, it defines a core animation layer that implements some class that says, I am really a geo layer.
It knows how to unpack your view hierarchy out of the nib, but you have to say, "Hey, I really want this GL layer to be opaque so that you're not spending GPU resources blending that with whatever's behind it." You have to say, "Hey, I want this stuff to be a certain pixel format.
I want it to have the pixels in this order." I want to use the OpenGL ES2 API instead of 1. And then you have to set up a timer to tell the core animation display link, hey, I want to animate at this rate. And you can pick from a number of different ways, but maybe you don't know which one is best.
And not only that, so once you've set all that up, you haven't even started drawing, then you have to implement this draw view call where you run your game logic, and then you have to screw around with OpenGL frame buffers and make sure you get a new frame buffer, you get your content into it, you present it, and then you tear it down so that OpenGL can discard that frame buffer data and not have to actually page it off. Or do other expensive things with it. You have to do all this stuff just to do a basic OpenGL ES 2.0 app.
And while you only have to get it right once, we thought that there was probably a better way to do this. So in GL Kit, we now have this class called GLK View, and you can just add one of these to your view hierarchy, write an interface builder, and subclass it as you would any other view that you want to control. So when your app is done launching, basically, you're just going to say, hey, I want to set the delegate for this GLK view to whatever my game class is.
And I'm going to basically set then the frame rate that I want to target, and GLK view will take care of running the animation at that frame rate. And there's basically two functions that as a delegate of the GLK view, you have to handle. There's controller update, and so that's going to get called whenever your game logic needs to be updated.
So in our little pong example, we'd move the paddles up and down and hit detect the bricks and all that kind of stuff. And that's nicely separated from the drawing call, which is just where we would implement any of our custom drawing, just like we would in the previous example.
We've really made this much easier to reason about, and now OpenGL isn't a special case. It's just a first-class citizen in the UIKit view hierarchy, just like anyone else. So you've seen how OpenGLKit lets you adopt ES 2.0, even if you're not familiar with OpenGL. And the reason why it's important to do that is we are building awesome GPUs into recent iOS devices. The iPad 2 GPU is fantastically powerful. As you've seen in some of the demos already, you can run complicated shaders at full-screen resolution at 60 frames a second.
And you know, you can use GLKit to get some of those effects into your app pretty easily. And so that way, you can get the power of that hardware that's in all your customers' devices without having to be an OpenGL ES expert. And there is tons of other functionality in GLKit that I haven't covered today.
And just like the previous two sections, we have sessions for you to go to where you can find out more about that. So, Advances in OpenGL ES for iOS 5 is the main GL Kit session. That's tomorrow at 2:00 in this room. If you are interested in some of the GL Tools stuff that you might have seen in State of the Union, those sessions are coming up later on Wednesday as well.
The final thing I'd like to talk about today is AirPlay. And this is actually really amazing in that how many people out there own an HDTV? See, these are the people that you can target with AirPlay because everyone has a television and now we're giving you a way to get content, your game content, on it.
This is iPad 2 specific, but you can mirror your game content if you just want to share the same screen that's on the iPad on the TV. But the example we'll walk through today is using your TV as a second display, because we think that this enables some really cool use cases for games.
So I have prepared for you some excellent slideware of an example that we thought up and thought, man, we really hope someone writes this. So here you can see we have an iPad, and it's connected to an Apple TV, and it's asking me to draw an iPad. You may be familiar with this game from your childhood. And so it gives you an area to doodle on, and you doodle, and it appears on the television, and people have to wonder what it is you're drawing. So you can see how AirPlay lets you get game content.
in front of a group of people, and again, we're going for that social game experience where multiple people in a room can all be playing your game together and having a great time. So let's look at AirPlay code examples. There are some really easy ways that you can get content on there. UIKit has a new UI screen class.
So if you want to detect the second display when your app is launched, you can just say, "Hey, UIScreen, how many screens are there?" And the answer is going to be one or two. So you can say, "If there's more than one, I'm going to go ahead and get that last screen object and do whatever I need to do to get my content on it." If you wanted to detect a hot plug, for instance, someone putting that HDMI connection into an iPad 2 or an Apple TV coming online and... Becoming ready to accept second display.
You can register for a much shorter notification this time. The UI screen did connect notification. And so again, we're going to go get our default notification center and just say, hey, we want to get a call to screen did connect whenever a screen shows up. And then again, we're going to go to this prepare screen function.
And what does prepare screen look like? Well, we need to get a reference to the second screen so that we can create some content on it. The first thing we're going to do is we want to create a window on that screen, and to create a window, we have to know how big to make the window. So we ask the screen for its bounds, and as you'll see, this isn't a fixed thing. We can actually change the resolution a little bit later.
When we create a UI window with that size and So, when we set the screen property of that UI window, we switch from being mirrored display to being a secondary display. So, the important thing to recognize here is whenever you create a window on that second display, That is what tells the system, "Hey, this guy is actually trying to use this to display additional content. I'll switch out of mirroring and into second display." When that last window goes away, you drop back to mirroring.
So now that we have this window, we need to get a view in it and get some content. So you're just going to create whatever view controller object you have for the content that you want to put in there. You're going to set that Windows root controller as the view controller you just created.
And you're going to set that window's hidden property, which defaults to true, or yes, to no. And then that window will appear and your glorious content will fill that television. But say, you know, maybe you have some relatively, you know, expensive content to produce on a per-pixel basis.
UI Screen provides you a way to get access to the supported resolution list and then change the resolution. So many HD televisions support 1080i, 720p, 480p, you know, maybe you'll get 1024 by 768. So if you would rather be in one of those modes, you can get the list of available modes and use a UI screen method to go switch into that mode.
UI screen also provides you with access to the preferred mode, which is going to be whatever our best guess of what looks best on that screen is. And so, for instance, the 720p television, the preferred mode is going to be 720p. You can also do some pretty cool other little things here.
One of the properties I thought was neat in playing around with this was the screen brightness. So, for instance, if I'm doing something, if I'm bringing the player's attention back to the iPad, I can dim that exterior screen while I'm doing something iPad-centric. And when I'm done doing it, I can bring the screen brightness back up.
There are a few other properties, but I encourage you to check out uiscreen.h and go to the AirPlay session later today at 3:15. You'll see a whole bunch of ways that you can use this, some of which are not game-specific. So, in summary, we've talked today about four technologies. You've seen how Game Center can keep players interested in your game and make gaming an awesome social experience that is rewarding for your players.
For both your players and you as developers. You've seen how Cloud Storage can solve basic problems in gaming that a lot of people have now and will enable really cool new uses of multiple devices in your games. You've seen how GL Kit can solve a lot of the basic problems of adopting OpenGL ES 2.0 in your app and making the power of OpenGL and our GPUs accessible to those of you who are not OpenGL ES experts.
And you've seen how Air Display is really easy to use and can really provide some interesting collaborative game experiences, or just get your game on the HDTV that almost everybody already owns. If you have questions about any of this stuff, And you can't, for whatever reason, make it to one of the sessions that I showed you earlier.
You can contact Alan Schafer. He's our Game Technologies Evangelist in Developer Relations. You can find us up here at the stage between sessions. So part two will be starting about 15 minutes from now in the same convenient location you are already sitting. So we hope to see all of you back here. Graham will talk about the awesome fundamentals of game design on iOS. Thank you for spending your morning with me. It was wonderful to see you. I hope you go get some tea and coffee and danishes. So thank you very much.