Video Transcript
Welcome
Visual Studio for Gaming, Developing a 2D game. My name is Bill Lodin and the purpose of this session is to show you just easy it is to create a game using XNA Game Studio 3.0. So, we’ll be talking about the content pipeline and how to load content into your game. We’ll talk about the application model and basic game flow. We’ll talk about graphics, we’ll talk about textures, how to handle user input, how to do some collision detection and finally, how to add audio into your game.
Now, before we get any further, I just want to remind you that the goal of XNA Game Studio is to make it really, really easy for you to get started creating games. So of course, that’s my goal too, is to show you how to build a complete game in the space of less than an hour. Now, I’m going to assume that you already have XNA Game Studio 3.0 installed and that assumes that you already have Visual Studio or Visual C# 2008 Express Edition installed. The Express Edition of Visual C# 2008 is free, as is XNA Game Studio 3.0.
So, in a nutshell, what we’ll be going over, is how to create a game and the first step is to simply create a C# class that inherits from or derives from, the XNA Game class. You’re going to override two methods, initialize and load content, just sort of prep things. That’ll allow you to set your initial settings and to load your graphic and audio assets into the game. Then, you’re going override the update method, to implement game logic and override the draw methods, to actually put pixels on the strain and that’s it.
So, XNA Game Studio--just to sort of refresh your memory if you, or to introduce you if you haven’t seen this before--is a tool set that builds on top of Visual Studio and allows you to write managed code to implement games that run on either Windows, Xbox 360 or Zune.
Now the XNA Framework is a big part of allowing this and the XNA Framework has two high level components; the application model and the content pipeline and there’s a whole rich class library that consists of export for graphics, audio, math, input, networking and gamer services. Now, we’re not going to talk about each of these in any great detail, but just to point out that obviously, things like graphics and sound are kind of no brainers when it comes to building games. Math is really important specifically with 3-D gaming because of all the tremendous amount of mathematical calculations. So we won’t see that as much in this session. Of course, input that covers how to handle user input, whether it’s from a game pad or from a keyboard or a mouse. Networking in the XNA Framework is really quite powerful. It involves not only standard Windows networking that you could use for a Windows based game but also for an Xbox 360 game, the ability to create a multi-player game that runs on Xbox live. Gamer services allows you to get to things like the gamer profile and so forth.
So, XNA Game Studio sits on top of XNA Framework and again, it requires Visual Studio 2008. As part of the tool set, it includes tools that allow you to leverage different types of content and more on that in just a moment.
It also has something called the device manager that allows you to connect to external devices namely Zune players and Xbox 360 consoles and you can connect directly to them so you can debug on those target devices and step through your code when it’s running on the Xbox, for instance from within the Visual Studio environment.
The Content Pipeline and loading content
So, first off, we have the content pipeline and the content pipeline is designed to let game artists use just about any digital content creation tools. You think about all the graphical assets that you’re going to be using in a game, whether it’s background, art or sprites or textures or models that you would use in the 3-D game. Obviously, there’s also all the audio formats that you might be dealing with. So the content pipeline provides a mechanism that decouples the contents dependency on a particular game engine. It really just gives you a simple content built system that’s extensible and expandable. So even as new formats for storing game assets are invented and created and introduced, those can be brought in to your Visual Studio built games. It happens through importers and processors and XNA Game Studio ships with an number of built-in importers and processors. The importer part is what converts an asset into an object that content processor can consume and then, it’s the job of the content processor to compile that into a managed code object. Remember that at the end of the day, XNA Framework is about managed code to create games.
Now, how do you do it in real life? Well, you simply override the game classes load content method and you use the built in content manager to load and create managed objects from binary files. So, let’s go ahead and kick off with the first part of our demo where we’re going to load some assets into our game.
So, let’s start with opening Microsoft Visual C# 2008 Express Edition and we’ll go to file, new project. Now, you’ll notice right away there’s a number of templates that you can use, templates for Windows, Xbox and Zune development. There’s also a platform or starter kit which ships with XNA Game Studio and for building a two-dimensional platform-style game. This is a great place to start because it provides a nearly complete game that shows how to develop concurrently for Xbox 360, Windows PC and Zune. And all the source code is there, all the assets are there, the audio files, everything is right there that you can browse and learn from again, nearly complete game.
In this case, we’re going to create a game from scratch so I’m going to start with a Windows game 3.0 and we’re going to call it alphabet fairy because I have a two year old daughter and she likes the alphabet and she likes ferries so for her this is a marriage made in heaven and if I’m going to build a game in less than an hour, it’s got to be something pretty simple and so I thought, why not build something that she can actually play. Now, if I just run it right off the bat, you’ll notice that I actually get an application window with a title and some nice background color and there’s actually a little bit of functionality, not a whole lot but it does have the ability to close, not just through the standard Windows close button but I have a game pad, an Xbox 360 wired game pad connected to the computer and it already is wired up so that if I click or press the back button on the game pad, it’s going to exit out.
So, we wanted to load content and so obviously one of the first things that we need is some content to load so I’m going over to the content in the directory, in the solution and add an existing item and we’ll go out to pictures and find a little png. It’s a png not because that’s the only type of format that’s supported, far from it. It’s a png because that’s what I chose to use. It’s one of the many formats that is supported and png supports transparencies nicely. So, that’s why it was my choice but again, it’s the content pipeline that’s responsible for taking whatever format you have and then compiling it for the game so that XNA can understand it.
Now, there’s the way that I can develop in which everything goes in game.cs in the this game one class but that would quickly get a little bit messy so, just to keep things separate and a little bit under control, I’m going to create a new class that’s going to represent our player character and this class is going to be called fairy and right off the bat, let’s add some using statements. We don’t need all of these right now but just to save time, we’ll put them all in right now anyway. So, graphics, input and content.
Now, in this class, I’m going to define an object of type graphics device manager and I’m also going to define a type of texture 2D and we’ll be talking about that particular type a little bit later. I’m going to create an initialized method and it’s going to take an object of type graphics device manager and that way our game class can pass the graphics device manager to class and that way any time within the processing, if we need to get the graphics device manager, we’ve got a built in reference to it.
Okay, we’re also, of course going to load content, so let’s create a public void load content method and that’s going to take an object of type content manager which is another one of those objects that’s predefined in the game class but we need to carry it over by passing it into this method and then we can say texture=content.load. we want to load object of type texture to 2D and we’ll call it fairy. Why? Because if we look at the properties for fairy.png over in solution explorer, you’ll notice that it’s automatically given it an asset name that matches our file name.
Now, couple things that we need to do over in the game class, and that is, to call this load content, and we can’t call load content until we have an instance of the class, So over here, I’m going to go up into the game one class and define an object of type Fairy. And in the initialization method, we’ll say call the constructor and call initialize, that’s where we pass in the graphics. And then in load content, this is where we’re going to call fairy.load content and pass in the content property which again is one of those content managers that knows how to find and covert the content.
Okay, so this should build successfully and we can run it and at this point, we can see that we haven’t really changed anything because all we’ve done at this point is load content. That is what we were trying to demo and I didn’t really promise that loading content would be that exciting. If we’re going to make things interesting, we’re going to have to really go learn how to put some pixel on the screen through the draw methods.
The Application Model and Basic Game Flow
So before we get there, let’s talk a little bit about the application model. In gaming, you have this thing called the game loop. It’s sort of the fundamental truth of game development and one of the nice things about the game class and the XNA Framework is that it already implements a game loop for you. This loop is going to call the update method, then it’s going to call the draw method and then it’s going to repeat ad nauseum or until you decide to exit or it decides to exit for you.
The loop timing, the way it works is one of two ways, your game can be either a fixed step game loop which is the default and if you take that approach, then update is called each time a certain elapsed time is reached. So, it’s keeping track of real time behind the scenes and the default is 1/60 of a second to where every time that time is reached, it’s going to call the update method and once the update method is finished, provided it hasn’t taken a sixtieth of a second and we need to call update again, it’s then going to call draw and then, if we still have time before update, it is getting called, then we’re going to idle until the next time it updates.
So, in general you can assume that it’s going to call update, then draw, then update, then draw. In reality, there are times where because of maybe extended processing, and the update method, it might actually call it twice before draw is called, but you can actually check to see if that’s happening. There’s a property called ‘is-running-slowly’ on the game timing objects that you can check.
At any rate, the other alternative is a variable step game loop, and in that case, update and draw are simply just called in a continuous loop and if you choose to do it that way, you just have to do a little bit more work to make sure that the game play stays consistent. The only possible issue there is if you know, update takes a shorter amount of time sometimes and a longer amount of time, other times depending on what it’s doing, maybe depending on how many characters are on the screen or how many enemies are around and so forth, then the game has this tendency to speed up and slow down. And players really notice that and it’s something that you’d want to try to avoid but there are strategies that are discussed in the documentation as to how you can even avoid that even when using a variable step game loop. At any rate, the most important thing to remember there is update-draw-update-draw update-draw.
Graphics and Textures
At any rate, the most important thing to remember there is update-draw-update-draw update-draw. Okay, so graphics in the 2-D world, we call the sprites and sprites are simply two-dimensional bit maps that are drawn directly on the screen and you’re nearly always going to have sprites, even if you’re using models in your 3-D games, you’re still going to have to display the game over message, or the score or a power bar indicating life left or something so typically, you’re always going to have sprites. And therefore you’re always going to be using these textured 2-D classes in order to create sprites.
Textured 2-D is a managed object that can be rotated, scaled, it can be tented, it could even be applied to models and one of the approaches to create animation in a 2-D game, is to use a single textured 2-D object that has multiple images and then just move the source rectangle and it gives you the appearance of animation so if you wanted to have a character that looks like he or she is running or so forth, that is not within what we’re going to show today but I wanted to call that out. It’s shown in fairly straightforward fashion in the platform or starter kit. So, if you’re curious about that, it’s a good place to start and check that out.
Now, drawing a sprite is pretty straightforward. There’s an object called sprite batch that is automatically created for you in the draw method that’s available in the draw method and you simply have to call sprite batch.draw in between a call to sprite batch being and sprite batch end. So, really if you just look at the code, you’ll see an example of what that looks like. If we were to draw a simple texture on the screen, you can see that it’s pretty straightforward. We’ll look at an example in just a bit.
There’s often times in a game, you want to display the score, you want to display a message to the user, maybe you have characters that are talking to each other and you’re using cartoon bubbles with text, any number of reasons, put text on the screen. There’s a special way to do that, called draw string and instead of passing in a texture 2-D object, you pass in something called the sprite font but the approach is very similar, you pass in the text you want to draw, you pass in the font that you want to use and just as with the textured 2-D and draw, you have to supply the position in the tent.
So, let’s go ahead and add some graphics and text to our little game. Now back in the game one class, you’ll notice that the template has provided a number of properties out of the box, a graphics device manager which we’ve seen already and something called the sprite batch and both of which we’ll use here to be able to start putting pixels on the screen. So in our class, let’s go ahead and create a draw method and this is going to take an object of type sprite batch and it’s going to use that to draw the current texture. And it needs a place to put the current texture so let’s go ahead and calculate that by calling graphicsdevice.viewport.width – we divide that by two to get the center point of the screen from left to right and then, we define center Y as the center point from top to bottom and now we have the center of the screen.
We can store that in a Vector2 object which are used heavily throughout game programming. And then we have a location in which to draw our texture. Now to actually draw it, we call sprite batch.draw and we specify the texture, we specify the location which is the position and we specify the tint and even, according to the documentation there, you can see that you use color.white for a full color with no tinting which is what we want. So now we have texture, position and color.
Our content load content should have been called in the game class. And now we need to go back to the game class and find its draw method cause this is the one that’s actually getting called in the game loop. So if we find the draw method, you’ll notice that this is where that background color gets defined. And then, in order to actually be able to draw content we have to call begin and then once we’re done we call end.
So, I’m going to call sprite batch.begin and use sprite blend mode alpha blend. Aand then sprite batch.in . Ad in between let’s call fairy.draw and pass in sprite batch so the same object can be used within the class to put the art. Okay, so fairy.load content and I think we should be able to, at this point, go ahead and test out our application. And we can see that sure enough, we get a little fairy on the screen. And one thing you’ll notice is that it’s using the upper left corner of the texture as the center point or origin of the sprite.
Okay, now if we wanted to do any rotation on that, then it would rotate around the upper left which wouldn’t probably be what we want. So, I’m actually going to make a few changes here and add some member variables to the fairy class. So, let’s go ahead and add a Vector2 that represents the position and another Vector2 that represents the origin. We use something called sprite effect to represent the direction and that’ll make sense as we go along and finally, a floating value to represent the rotation and just to see what does, let’s initialize that to zero point five.
Okay, now because we’re defining the position here, we can initialize it when we load content to be at the center of the screen. The reason we want it out of the draw method is because the draw method is going to get called repeatedly and if I leave this code the way it is, then the fairy’s always going to end up in the middle of the screen and we’re not going to be able to move her anywhere. So, I’m going to take code an I’m going to move it up into load content. And I don’t need this to define Vector2 because now I’ve defined it as a member variable. I’m also going to set the origin, and the origin is going to be defined as a new Vector2. And just like we did with the graphics device, we’re going to divide by two for width and height. And that way, we get the center point of the texture and that way, when we rotate the texture, then it rotates in the right place.
Okay, so we’ve defined the origin, we’ve located the center point and now because when it paints the textures on to the screen, it’s going to use that origin as the position. So effectively now instead of being, you know, sort of off to the right and below the center point, our texture should be painted smack dab right in the middle of the screen.
We should also, while we’re at it, initialize direction and we’ll say sprite effects.flip horizontally just to show you what that does. Now, in the draw method, we need to use a overload for the draw method that’s a little bit more complicated. So instead of just texture position and tint we’re going to use texture, position and then we’re going to specify null because we’re not specifying that source rectangle, color. white as the tint, we specify – let’s move to the next line, the rotation, origin, a scale of 1.0 floating point, the direction and zero as the layer depth.
Okay, so once we’ve defined that, we’re going to need to see if that does anything for us, let’s go ahead and try the application now. We can see that now she’s been rotated and she’s been flipped horizontally from before so right away we can start to see what we can do with 2-D textures in terms of manipulation.
While we’re in this fairy class, let’s go ahead and add a method that is going to be empty for the time being but it’s going to really important later and it’s the update method and it’s going to take an object of type game time.
Now, I’ve saved this and I’m going to create a new class so let’s call add new class, this one is going to be called letter.cs to represent an alphabet letter and I’m going to copy everything from the fairy class and paste it in to the letter class, just to simplify things for us. I need to fix the letter name and a couple of things are going to be modified here. Instead of texture 2-D, we’re going to use sprite font. We’ll call this font. It still needs a position but we won’t care about the origins so much. We don’t need to worry about direction or rotation. We do, however, want to remember what letter we have. And most games involve some sort of randomness so we just use this good old system.random the same one that you use any time you need some randomness in any dot. application. Alright, so initialize method is good the way it is. We need to fix load content so that it’s loading the sprite font and that’s the only thing that load content needs to do. But we have an issue and that is, we don’t have any font in the game that we can use. Now, it’s really straightforward adding a font. I should sort of give you a quick warning that most fonts even if you have them installed on your system, that doesn’t mean you necessarily have a license to distribute them, especially when we’re talking about games that you’re building, maybe for deploying to the Xbox live market place and so forth. In that case, you’ll want to make sure that you have the right licensing to distribute fonts.
Fortunately, there’s a number of built-in fonts that XNA Game Studio installs on your system and those are in the documentation. You can use those and you can distribute them and so I think there’s like six or seven of those. We’ll add one of them to the content here and the way we’ll do it is we’ll go to content and we’ll add a new item and we’ll select sprite font and then we’ll call this Lindsey Big. Lindsey’is one the fonts that is installed with XNA and distributable. I need to change it from the Coutenay, that’s the default. That’s another one. And let’s make it nice and big. Let’s make it about size 48 and make it nice and bold. So, it’s this XML file that defines the font that we want to import and then the pipeline’s responsibility to take that, you know, basically Windows font and bring it in and make it usable in XNA.
So, now that we’ve got that there, we can go ahead load a sprite font called Lindsey Big. Once again the asset name matches the file name and the file name in this case is Lindsey Big.sprite font, so we’ve an asset name of Lindsey Big. Now we can load that into memory. And for our update--it’s finally time to do some sort of logic--so what we’re going to do here is we’re first going to pick a random number, a random letter, rather so we’ll say random.next. Obviously 26 to get all 26 letters plus 65 dot two strings, that just gives us string that represents an individual character.
We want to calculate the size of the string so that we can determine where to place it and make sure that we don’t put it off screen somewhere so we’ll call font. measure string, pass in letter. Now, we have a size that represents the height and width of what it’s going to be, take up on screen and then we can randomize the position. So, we’ll say new, Vector2 and random. next. We’ll take the graphics device viewport with and subtract the size and then we’ll do the same thing and let’s use the miracle of copy and paste, to do the same thing for height. So now we have a letter that is going to be positioned on the screen somewhere random top to bottom, left to right.
Of course, the draw method is going to need to be changed, cause if you recall form the slide, we said that instead of using draw, we used draw string and we specified the font the letter, the position and the color. In this case it’s not the tint, it’s the desired color of the text. Llet’s use your favorite and mine, papaya whip.
Now, game.cs is going to need to be aware of this class so we’ll go ahead and define a letter there. We’re also going to keep a Boolean value that remembers whether we need to create a new letter or not. Okay? Now, over here in initialize, we better do the same thing we did for letters as we did for fairy. So, letter equals new letter, letter. initialize. Remember in the method in letter we just wrote, we referenced graphics so we better initialize it. So that’s what we’re doing here and then we have to load the content too so, we’ll call letter. load content just as we did for the player character.
Now, back or still in the game one class in the update it’s time to actually do something with this update method but besides just check to see if the user wants to exit and so, what we’ll do there is we’ll say if we need a new letter, cause there’s no point if the letter hasn’t, we don’t have a reason to create a new letter, there’s no reason to call the update on the letter then we’ll call letter. Update. And set new letter equals to false and of course, we need to draw the letter as well so we’ll call letter.draw sprite batch.
Here, okay so at this point we should be a little bit further along. We should have some random letter somewhere on the screen displayed and if we were to stop and restart we should get a different letter unless we’re supremely unlucky. We should get a different letter in a different position and there we go.
So now we’ve seen a number of ways that we can draw text and draw graphics to the screen. But I think it’s about time that we made something happen so we’re going to have to deal with the user input to do that.
User Input
It should come as no surprise that handling user input is supported out of the box as well. Various forms of input are supported in XNA Games. Obviously, an Xbox 360 controller which can be used in addition to Xbox, it can be used on a Windows PC. If you’re using the wired version of the controller. You can also use keyboard, mouse each input device is simply represented by a strongly named type in XNA and each of them provides a static get state method that retrieves the current status so whether you want a particular button, you want a particular thumb stick or what have you , there’s typically going to have either analog input--something like thumb stick that’s going to between negative one and one for X and negative one and one for Y, for instance--or it’s a digital feedback where it’s either pressed or not as in the case of most buttons.
So, let’s take a quick look at adding user input to our game. Now typically, you’ll use the update method in order to pull for any sort user feedback. And we can do it in the update method that gets called directly from game or we can do it in a drive class or another class so long as we create an update method there. And if you remember in the class, we define an update method even though we hadn’t actually implemented anything in it. We’re going to go ahead and add some movement now. So we’ll create a Vector2 called movement and we’ll use the game pad.get state player index player one. So for the game pads, it supports up to four that can be simultaneously connected, thumb sticks.left is what we want and so now, we’re going to take that movement and we’re going to modify the rotation slightly based on what the Y axis is doing. So we’re going to say rotation equals and it’s a float so we take movement.Y times -0.5.
We also want to change the direction that the player is facing and remember we have that sprite effect object that we used so here we’ll take and say if movement.X is less than zero, then we’ll say that direction is equal to sprite effects.flip horizontal. Actually we want it to be none because by default it’s facing that way and another Y’s direction is equal the sprite effects.flip horizontally. And because of the way that the rotation works, we’re also going to have to invoke the rotation so a rotation equals negative rotation. Okay, so that handles some of the sort of the direction that the sprite, the texture is facing and whether it’s rotated or not.
Now we need to determine where it is on the screen and you know, possibly adjust for to prevent the player from going off screen, etc. So, first we’ll need some sort of helper variables. We’ll define one called maxm and that’s going to be equal to graphics.graphics device.viewport.width. And as far as position of the sprite, we can have it go as close as the width of the texture divided by two because remember the origin is in the center of the texture. It’s not at the far left so we don’t want it to go all the way to zero, because if it goes all the way to zero, then half of the texture is going to fall off the screen. Now, minimum X, that’s pretty easy because that’s just the texture.width divided by two.
And then we do the same thing for max and min Y. That should be max X to keep us sane. And the only difference here is these are calls to texture and viewport height instead of width. Now you might ask, okay, well why not define these in one place and not have to invoke them every single time we call update. And the reason I’m doing it here is simply because if I were to later make this game so that you could resize the window or if you know, resolution changes or something else happens, then these values could be wrong if we set them once and then we reuse them. This way, we’re always checking to make sure that we’re in the correct balance. And now we’re going to take our movement.Y and we’re going to turn it around. The reason for that is because as you move the thumb stick down, towards you, if you’re holding the typical game pad, then, the value will go smaller and in the XY coordinate of the graphics, that would make the sprite actually go up so we need to flip that Y axis.
Okay, we’re also going to adjust the position based on movement and if we don’t multiply it by something it’s going to be really, really slow so we’ll multiply it by six.
Okay, now next up we’re going check for out of bounds because what happens if the user moves the character off screen? Well, we want to prevent that from happening so that’s really easy to do. We just call position X and we check to see if it’s greater than our max x and if it is, then we set it to max x and otherwise we check to see if position.x is less than min x and again, if it is, we set it to min x. Okay, now we’re not going to use else if here because it’s possible that somebody could be on the corner so that they’re trying to go off screen in two directions at once so we need to repeat all of these for Y and a lot of games will need this sort of code to make sure that you stay within bounds. Alright, so that is the update method, that’s the only thing that we did in fairy.CS is where we made all this code changes. We should double check and make sure that over and update, that we’re actually calling that and in that case, we aren’t so we’re going to make sure we add a call to fairy.update and specify game time in there as well.
Okay, so at this point, we should now be able to run, and we have our little fairy and she’s going to be able to move all over the place and notice that she rotates and she move she flips the right direction and all of this is based on handling the input form the Xbox 360 controller that left thumb stick.
Collision Detection
Now it’s time to talk about collision detection and as it turns out, XNA provides some built in methods and types to assist with collision detection and so there’s types called bounding box and boundings sphere and those primarily used for collision detection in 3-D space and it kind of possible to use them in 2-D spaces well but because they’re built for 3-D, you always have to be using a third axis, a Z axis and in actual practice, for 2-D games, the simplest approach sometimes work pretty well and that is just to use the bounding box approach where you just use regular rectangles in dot net to determine intersection and if you have two textures and you calculate their bounds as a rectangle and you just determine whether those rectangle intersect, then you say that a collision occurs. Now, if you look at the picture here, you can see that in some cases, you might say, well those aren’t actually colliding, because the orange and the orange ball on the left and the orange ball on the right aren’t actually touching but in the case of the simple approach using the bounding box, this would register as a collision cause the rectangles are overlapping. There are more complicated ways whether you’re calculating vertices or checking to see whether pixels are being blended and you can use those methods to detect collisions as well and there’s articles on line that go into those in more detail but for our simple approach and for our simple game, we’re going to use the bounding box approach.
Let’s go ahead and take a look at that. So, the texture 2-D doesn’t offer an out of the box bounds but we can easily calculate what the bounds would be. So, I’m going to add a property that of type rectangle called bounds to our fairy class and it will return a new rectangle and we’re going to use the position.X minus texture.width divided by two as the starting point and because remember over the position is the center of the sprite so unless we do that, then the collision detection is going to be off. Position.Y minus texture.height divided by two and then the width and the height are going to be simply the textures width and height so texture.width texture.height and that’s the bounds to the rectangle that represents, you know, the bounding box around our fairy character. Okay, we want to do the same thing over here in letter so we’ll add down at the bottom of that class a similar code that returns a new rectangle but in this case, we need to first measure well how big is the letter cause we don’t know until we’ve determined that and then we did it over here so we’ll just copy that we’ll say that the size is equal to font.measure string of letter and then we use the position cause we’re not using an offset and we’re not using an origin that’s different than zero zero so XY followed by and here’s where the size comes into play and that’s the bounds for our letter, okay? So to determine collision, we just go in to the update code here and we say, did the fairy collide with the letter and we say if she did, we say bounds doesn’t intersect with letter.bounds and if so, then we’ll say new letters equal to true, which of course, will cause the old letters to disappear to not be drawn again. We’ll pick a new letter and a new random location on the screen so let’s go ahead and play that.
Now, we’ve got the character can go round collecting letters and every time she gets one, a new one appears somewhere else on the screen. So now we’re getting the point where we have something that’s sort of playable but of course, having a game is really made when you have audio and some sound effects so let’s go ahead and talk about that.
Audio
So, audio is one of the things that has been really improved in XNA Game Studio 3.0. In 2.0 you had to use this Exact tool and it was a little bit complicated and that tool still exists, but the game street of 3.0 ships with content pipeline support for a lot of common audio formats that allow you to just import them directly into your game and the content pipeline will convert your various audio formats into managed objects such as song and sound affect and then you just use a media player.play or sound effect.play and it’ll allows you to play background music and sound effects. So you could see the code here but why don’t’ we go ahead and look at that same code NR demo game. Let’s first add the appropriate content so we’re going to add a couple of files here existing items, one of them is the background music and we’ll just grab it to make sure that we don’t run afoul of any copyright infringement and we’ll just use a WMA file right from sample music from Vista and so that again gives it automatically an asset name called Amanda and then we’ll go over to content and I had an existing item and this time we’ll go out to the Windows media directory and there’s a little wav file called Chimes.wav so we’ve got a chimes file and a WMA file or a wav file on the WMA file. Now, those are a part of the content, now we can load them using VContent manager over in the game class.
Let’s define a sound effect object called collected sound for when we collect the letter and then in load content, I’m going to go ahead and call collected sounds equal content.load and again we see this again. This time it’s the sound effect that is called chimes. We’re also going to use media player and specify is repeating equals true, that way as long as we play the game the music’s going to be happening. As it happens, it’s a little loud for my taste so we’re going to say volume equals 0.2 and then simply call media player.play content.load song and the asset name again is Amanda. All that’s left is to actually play the sound itself which should happen when we collide because that’s when we’re considering the collection tick occurs so we’ll say if the intersect happens then collected sound.play. Really, could hardly be any easier to be able to add audio to your application.
Let’s run this and we pretty much have a complete game. You’d hear a background music as well as noise whenever we interact or come across a letter. And that’s our game.
So hopefully, you’re seeing that XNA Game Studio makes game development really, really easy for you. We talked about the content pipeline how that makes it easy to use assets of various types. And how the application model makes things easier for you by handling all the heavy lifting, alright. All the stuff that needs to happen in the background, it just does it and you just have to worry about and understand and update and draw. The XNA Framework, on top of which XNA Game Studio is built, provides a rich class library where you’ve got these types and classes that are really easy to use. You’ve got types called the game and texture and sprite font and sound effect game pad. These are straightforward classes and the process of game creation has been, you know, simplified immensely, thanks to this.
Now the game is finished from before as far as my daughter’s concerned. She doesn’t care about score or time remaining. But most games are going to want to have some sense of that. And so even though only uses pretty much elements that we’ve already seen, I thought I’d show you what the code looks like to kind of finish this out. And so, I’m not going to type any code here, everything is already done for me but what I’ve essentially done is add another texture and a second font. I’ve created some additions in the game one class to store that game over texture as well as the score font. I have a score value that gets initialized to zero and a score position. I’ve also have a time remaining so that it can use the good old system.time span to keep track of the amount of time that is left. And just for our purposes, let’s change this from seconds and make it only take 15 seconds, that way we won’t have to wait around to see what happens.
So we’ve got a number of member variables and then as you can probably suspect by this point, you know that we need to load the content from the content directory in the load content methods so that’s where we load our texture and our font, just as we did before. We also have a code that allows the game to restart once it ends and so that will reset the score to zero, reset the time remaining to – we’ll make it from seconds 20, again and we’re checking for the A button here to see if it’s pressed, alright. We just checked buttons A dot is equal to buttons stay pressed and we only checked to see if the game is over and then we have an update time where the update time or the time remaining gets updated based on the elapsed game time. We checked to see if it’s less than zero and then we say that the game is over at that point. And finally, every time the intersection occurs, we add 10 points to the score. We also update the time remaining during the call to update.
Down in draw, we have to make sure that we draw two strings, one for the score and one for time remaining. And that’s it. So, one last time, here is the “finished product” of our simple game. You can see score and time remaining in the corners and when we run out of time, we’re going to get a little message and everything is going to freeze and then as soon as we press A, we start again.
Now here’s a couple of links that if you don’t already know about them, you should commit them to memory if you’re going to be doing any game development with XNA; the Creators Club Online at http://creators.xna.com. And then, of course, for all the documentation, you can find it at the XNA Developers Center http://msdn.microsoft.com/xna. Thanks very much as always and we hope to see you during another online session.
[End of Audio]