3.8 Adding an Additional Scene
Next we will add a new scene that will appear at the end of the game to show the user whether or not he/she has won the game.
1.Introduction3 lessons, 07:37
2.Introducing SpriteKit7 lessons, 54:48
3.Building a Game11 lessons, 1:30:25
4.Conclusion1 lesson, 01:49
3.8 Adding an Additional Scene
Now it's time to get a little bit more sophisticated with the end of our game. So sure, we could just print things off. We won, we lost, and all sorts of things like that. But ultimately, we wanna give a visual cue because odds are the person that's playing your game isn't going to be running it through Xcode and see these little output bursts of knowledge that you're giving them. So let's go ahead and do that via a new scene. So, what we're gonna wanna do here is we're gonna want to come into our application, we want to create a new file. And in this case, we wanna make sure that we have selected iOS and Resource. And what we're looking for here is a SpriteKit Scene. So then we'll hit Next and we should think about this for a minute. Now we could definitely create two separate scenes, one for winning, one for losing. But ultimately, what are we trying to do? We just wanna give some information to the user, whether they lost or whether they won. So in my mind, that's all really the same thing. We're just changing the text that's displayed. And if that's the case, and we can get away with just creating a single scene, that's maybe gonna represent the state of the game being over. So we want to create this as a GameOverScene, [SOUND] like that. And we wanna put it in our BreakoutClone and Create. So as you can see, that's gonna give us our game over scene. And you can see in our designer here, we're gonna see something very similar to what we worked with at the very beginning. So we're gonna do a little bit of change to this just like we did early on. So we're gonna make sure that our scene is selected, we're gonna make sure that it's still black. We're gonna give it the same dimensions, 1136 by 640 just to be consistent. And then what we ultimately are going to need to do is have something out here that's gonna allow us to put some text out there. Well we probably have a little bit of experience with that using a label, so let's do that again. So let's slap a label out here. And let's make sure that we actually give this label a little bit of size. So we're going to wanna change the font of this to be a little bit bigger and let's go ahead and stick with the Chalkboard, I like the Chalkboard. And we'll leave it regular, but we're gonna wanna make sure we make this probably substantially bigger than what we're seeing here, 144. Yeah, sure why not. Let's be a little obnoxious. And we wanna make sure that this is going to say what happened. It'll say something like, you win or maybe it'll say something like, you lose, or you lost, or something like that. So that's kind of the end goal that we're looking for. And then even, we might want to say, something to the, to the effect of later on, putting underneath this, say, you know, tap to play again type of a deal, if we wanna continue to play or advance on in the game. But for now, we're just gonna present this screen to the user, so we'll go ahead and save that. Now, what we're gonna wanna do is change this text at some point. So we're gonna wanna grab that text and give it a name. And this is going to be, we'll call this result. And we'll save that. So now our, our label has a name, so we can get at it in code. So now, we need to be able to do some things with this in code. But as you can see here, when we created this scene, it only gave us one file. Not like we have up here where we have a GameScene.sks and a GameScene.swift. So you have to do that manually when it comes to creating this, these scenes, and it's quite simple to do that. So we're gonna come in here once again, we're going to add a new file. And in this case, we're gonna go up to iOS. And this is gonna be a Cocoa Touch Class, and we'll select Next. And in this case, this is going to be, we wanna name it the same way just to keep them together. So this is gonna be GameOverScene, and this is going to be a subclass of SKScene. And we'll make sure that this says Swift, and we'll select Next. And we wanna make sure that this is in the BreakoutClone group as well as folder. We'll select OK. And there you have it. So now, we have a very similar structure at least, to how we had the original game scene set up. As you can see, out of the box when you create it this way, it doesn't know what SKScene is and that's because we haven't imported SpriteKit. We're gonna come up to the top and we're merely going to import SpriteKit. And go ahead and save that. So now we're looking pretty good, but now we wanna be able to get ahold of the things that are going on within our scene and how are we gonna do that. Well the way you would typically think about doing something like this maybe would be to say all right, I have this scene and I need to tell it whether or not we won, or we lost. Or maybe just make that kind of a, a binary operation, or, or a Boolean operation of did I win, or maybe something like did win. So what we would typically think about doing for something like that is saying, well we can create a property called didWin that's going to be a Boolean. So that's good. So now I have a way of keeping track of the fact that I either did win or did lose. But how am I gonna check that? Am I, should I have to call another method? I guess we could do that, and the reason that this is squawking at me is because I haven't initialized this to anything yet. So now we are, we had this didWin property. And how, so we can create some sort of function here maybe. Say function, maybe evaluateWin or something which, you know, kinda starts to feel a little awkward. Because now we're gonna have to create this, set this property, call this method. And those things, you could definitely do. And we could say, you know, if didWin. And if that's the case, then we can show the value, or we can present that text that we wanna show to the user via that label. And we would simply say something like var label equal to childNodeWithName, and we call that result, and that is as an SKLabelNode. And then I could set the label.text equal to, You Win. Something like that. Which is all fine, and we can definitely do that, but this becomes a little bit cumbersome when you have to do multiple steps to get there. Well, there's a very interesting mechanism in Swift that's called a property observer. So what's that mean? Well, a property observer is kind of a way to inject some code into this property here that's going to know when you have actually set this value, or changed the value of this property, and be able to do some sort of action at that point in time. Not set it, and then maybe call some function to evaluate that variable. Cuz you could, like I said, if you could definitely do this but it gets a little cumbersome. So the way that we're gonna do that is actually, you just come on here and you append an open and close parenthesis off of here. And then we can start to use some property observers, and there's a couple different ones. The one that we care about at this point is actually didSet. So if we did set this property to something, in our case, if we set it to true then we can check in here if it was set to true and we can set the appropriate text. If we set it to false then we can set the appropriate text for that situation as well. So let's do that once again by getting our label. So we'll say var label is going to be equal to childNodeWithName, and that's gonna be result as an SKLabelNode. And then we can say our label.text is going to be equal to, and then we'll use a little bit of binary comparison instead of saying a big if else, we can simply concatenate and shorten that down a little bit to say, and you have access to your variable within this observer as well. So I can say, didWin. If it's true, then I want to, using the question mark by deno, is going to denote true, then I want the text to be You Win, or something along those lines. Else, which is the colon, it's going to say You Lose. And we'll go ahead and save that. And that is pretty much the extent of what you're gonna want to do from this particular game scene. Now, we need to wire up this scene to show up when one of those actions happens back within our GameScene.Swift. Instead of doing these little print lines here, we actually want to show that screen. So how are we gonna do that? So, what we're ultimately gonna wanna do here is during this process of did contacting something. What we wanna do when we have reached these points here, we're gonna want to create a new instance of that game over scene. And then set that property, that didWin property, and then present that scene to the user. So we can get rid of these print lines. And we'll say, let scene be equal to our GameOverScene. Now, there's an interesting method on here called unarchiveFromFile, and we can give it the name of the file that contains our scene that we created before. Which just so happens to be GameOverScene. [SOUND] And we are going to cast this to a GameOverScene. And then in this case, when we've hit this point, this means we've actually won. So now I can say, scene.didWin equal to true. And then, we're gonna need a way to kick off this new scene, and the way that we do that is we're actually gonna have to get a hold of the current scene that we're in to initiate that transition. So, we'll say let our main scene, [SOUND] equal to view, and this is going to be a little trickery here that we can use to get ahold of our current scene, or our current view. Let's just say if, let if mainScene is equal to view, then we want to do this little creation of a scene. Sorry, I did this backwards. If let, if the mainScene is equal to the view, then we're going to get a new scene. We are going to set its didWin property to true and then we're gonna say mainScene.presentScene, which is going to be scene. We'll go ahead and save that. Now, we can do the same exact thing down here as opposed to what we had done before. I think we have one, too many curly braces here. [SOUND] And now we can see that we're gonna do the same exact thing here, only in this case, we're gonna set this to false. So go ahead and say false, and let's see if we can build that if we've set everything up successfully. Do a little bit of crossing of our fingers and see what actually happens when we run our game. So we're just gonna run along our merry way. And we're going to bounce around a little bit here and hopefully we'll win first. And as you see here, we have this little bit of a strange error that's kinda come up here. So let, let's try to run this a little bit further. There we go. You win. So, we had a little bit of an issue there, but we did get through over to, you win. And after doing a little bit of research around, this is I can admit that this was a little bit cryptic to me in the beginning, as well as it really has nothing to do with the code that we've setup, but has a little bit to do with how the boilerplate code is setup. So if you actually come over into GameViewController.swift, here is our unarchiveFromFile method that we were using on the scenes before. And what's actually happening here is it's going through and it's running through this code and it's stumbling on this line here a little bit where we let the scene equal to archiver.decodeObjectForKey and cast that as a GameScene. And for some reason, it's being very specific as to try to cast this as a GameScene and not necessarily as an SKScene. And if you come back and look over here at our particular scene, we're actually trying to run an SKScene. So if we just simply come into the GameViewController, if you've run into this issue. This was an issue in this particular version of Xcode. It may change by the time you see this video, or it may not. But, let's simply change this to SKScene and we'll go ahead and save that. And now if we run our application, we're gonna go ahead and start it up again. And this time, once we hit a point where we win or lose, and because I'm not gonna do anything, we're actually gonna lose first. You'll see it did a nice smooth transition and we didn't hit any sort of errors or breakpoint errors along the way. So if you do run into that issue, take a look at your GameViewController in your unarchiveFromFile function. And just change this line here to cast it as an SKScene, to be very generic as opposed to the GameScene. So that's pretty nice, so now we have our game working. But now, we've, we're kind of quitting our game, maybe before we necessarily want to. So, like I said, let's probably try to put something underneath here that's going to say, tap to play again or something along those lines so you can continue to play this game.