XNA 101 .Net

Learn how to program in C# while writing games in XNA Game Studio 3.0!
Our upcoming Silverlight book for beginners (includes a great chapter on game development in Silverlight!) Hello! Silverlight 2 with Dave Campbell, available online now!



Pages

Recent posts

Navigation

Archive

Blogroll

    Tampa Divorce Lawyer

    North of Tampa in Lutz, Florida. A Tampa Divorce Lawyer focusing on family, divorce, and real estate law.

    Disclaimer

    The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

    Dr. Popper updated on Xbox Live Community Games

    I'm pleased to announce that a new version of Dr. Popper has passed peer review.

    There was an intermittent crashing bug on startup with Dr. Popper, basically if you pressed A repeatedly on startup it could crash. I also enabled high scores in trial mode so that trial users could get a better idea about how that works.

    Note that it seems that there's not currently an auto-update for community games so if you want this new version you'll have to download again.

    One comment on the peer review process. When you submit a game for peer review, a new post gets added to the forum thread to discuss it, but email notifications don't go out to the people that have previously peer reviewed your game and commented on it. So when resubmitting for peer review, you should probably post to your peer review forum and specifically talk about what has changed.

    Remember that peer review is for completed games and abusing the peer review process doesn't benefit anyone. Blatant abuse of the peer review process can cause a ban of the developer.

    Posted: Jan 05 2009, 00:01 by Bill Reiss | Comments (0) RSS comment feed |
    • Currently 0/5 Stars.
    • 1
    • 2
    • 3
    • 4
    • 5
    Filed under:
    Lessons learned getting a game on Xbox Live Community Games

    So it's been a couple of weeks now since Dr. Popper was approved for Xbox Live Community games. I?m pleased to announce that it made the top 10 for sales last week (ok barely, it was number 10). Before you ask, I don?t know what that means yet, I don't think that actual sales numbers are being shared yet, so it might be less than 10 sales, or a thousand, no idea yet.

    When bringing Dr. Popper to Xbox, there were two major efforts. One was since it was a mouse-based windows game, I had to implement a gamepad based interface. This also included having to create a menu system. I plan on releasing my gamepad classes soon which I found very helpful to give the gamepad an easier interface. I also created a keyboard version of these so that you can test on Windows without a gamepad. If you're interested drop me a note and I can get these to you sooner.

    It's critical that you're able to test your Xbox game on Windows since you won't want to have to deploy your game each time you want to test. This means you need an Xbox Gamepad to use on your PC. You have two options, my preferred one is using an Xbox 360 Wireless Controller with an Xbox 360 Wireless Gaming Receiver for Windows. This is the cheapest way to go if you already have a wireless controller. Your other option is to get a wired Xbox 360 Controller which will plug directly into your USB port and off you go.

    All you need to do to get your Xbox game to compile for windows is to right click on the project in the Solution Explorer and say "Create a Copy of Project for Windows".

    Play some other Xbox games and pay attention to button presses especially in the menu system. When you?re playing a game on Xbox, the button presses become second nature and you may not even think about them. Make sure that your game follows these conventions.

    Play other Xbox Live Community Games, preferably the more popular ones. Pay attention to game flow and how they implement their trial mode.

    The other major effort was to implement storage properly and gamer services. This can be pretty involved just because there are so many combinations. The player can be not logged in, logged in but not logged into Live, logged in to Live but not allowed to purchase, and someone could sign in or sign out at any time during the game. As for storage, someone may have a hard drive, or a memory unit, or both, and may remove or insert the memory unit while the game is in progress.

    Check out Spyn Doctor's Evil Checklist for stress testing. It contains many things to look out for and suggestions on how to avoid these pitfalls.

    Most importantly, submit your game for Playtest before release. Even if you think the game is solid, playtest will probably flush out a few bugs that may even be missed in peer review, and then you would have a buggy game going out to the public. You only have one chance to make a good first impression.

    Speaking of this, one issue I ran into was that since storage doesn't carry over from Trial mode to Full Game mode, I disabled high scores in Trial mode. This led players to believe that the game didn't have high scores support and this cost me some sales. The next release will have high scores enabled in Trial mode but tells users that they won't carry over. So it's very important to make sure that in trial mode the user knows exactly what's in the full version and you represent all of its features.

    Posted: Dec 31 2008, 01:26 by Bill Reiss | Comments (1) RSS comment feed |
    • Currently 0/5 Stars.
    • 1
    • 2
    • 3
    • 4
    • 5
    Filed under:
    Dr. Popper now on Xbox Live Community Games

    I?m thrilled to announce that Dr. Popper has passed peer review and is now available through Xbox Live Community Games for only 200 points. It has all of the game modes from the Silverlight version plus improved graphics, background music, and a free trial mode. Here is the link to the game on xbox.com:

    http://marketplace.xbox.com/en-US/games/media/66acd000-77fe-1000-9115-d80258550147/

    and a screenshot of Extreme mode:

    screenshot2

    I?m also pleased to announce that it?s currently #2 in popularity for puzzle games in Xbox Live Community Games and #8 overall. So give it a try, tell your friends, and thanks for your support!

    http://marketplace.xbox.com/en-US/games/media/66acd000-77fe-1000-9115-d80258550147/

    Posted: Dec 22 2008, 04:01 by Bill Reiss | Comments (1) RSS comment feed |
    • Currently 0/5 Stars.
    • 1
    • 2
    • 3
    • 4
    • 5
    Filed under:
    75 percent through peer review for Dr. Popper

    Almost there... if anyone who follows my blog is a Creators Club Premium member with and Xbox who hasn't peer reviewed Dr. Popper yet, please do. So close and yet so far.

    Thanks!

    Posted: Dec 18 2008, 07:01 by Bill Reiss | Comments (0) RSS comment feed |
    • Currently 0/5 Stars.
    • 1
    • 2
    • 3
    • 4
    • 5
    Filed under:
    Dr. Popper now in Peer Review for Xbox Live Community Games

    I'm pleased to announce that I've submitted the Xbox version of Dr. Popper for release on Xbox Live Community Games. So now once enough people have peer reviewed it successfully, it will move to the marketplace.

    So I ask that anyone who has a creators club membership and has benefitted from these tutorials or just doesn't mind doing me a favor to please go ahead and peer review the game here:

    http://catalog.xna.com/en-US/GameDetails.aspx?catalogEntryId=d06298ba-da3b-45fd-8432-0a54b1ff34e8&type=1

    It's been an interesting experience getting a game ready for XLCG, and it?s taken more effort than the original game took, I'll share the experiences in a post mortem here soon.

    Posted: Dec 16 2008, 13:40 by Bill Reiss | Comments (1) RSS comment feed |
    • Currently 0/5 Stars.
    • 1
    • 2
    • 3
    • 4
    • 5
    Filed under:
    Dr. Popper for Zune written with XNA 3.0

    I'm pleased to announce that I have successfully got my Dr. Popper game running on Zune. Here is a screenshot:

    drpopperzune

    If you're reading this blog, hopefully you already have XNA 3.0 installed. If not, you'have to install it to play this game.

    More here: http://www.bluerosegames.com/xna101/page/Dr-Popper-for-Zune.aspx

    Posted: Nov 16 2008, 15:10 by Bill Reiss | Comments (2) RSS comment feed |
    • Currently 0/5 Stars.
    • 1
    • 2
    • 3
    • 4
    • 5
    Filed under:
    Lesson 15: Arrays and Loops

    This lesson introduces the concepts of arrays and loops and how their use can simplify your code, especially when dealing with larger numbers of objects.

    This lesson picks up where Lesson 14 left off.

    Source code for Lesson 15 Completed: http://www.bluerosegames.com/xna101/lessons/XnaLesson15.zip

    When it came time to add a second ball to our game, it became clear that just copying and pasting the code and changing the variable names was going to be a problem. So by encapsulating the bouncing ball logic in a BouncingBall class, we were able to reduce dramatically the complexity and the lines of code of our game.

    Now what if we want to have 3 balls, or 10, or 100? Should we declare 100 separate BouncingBall objects in the Game1 class initialize them in the Game1 constructor, and have 100 Update and Draw statements? Again, this would get out of control pretty quickly. Fortunately C# provides an alternative.

    An array is a fixed size list of objects or primitives of the same data type. Items in the array are accesed via an index. An index is a value that "points" to an element in the array. Typically array indexes are integers. In C# array indexes start at 0, so the first element has an index of 0.

    Often when writing code, you get to a point where the code in unmanageable and it's necessary to add classes, move code into new methods, or make other changes. The term refactoring refers to a restructuring of the code while preserving all or most of the current functionality. Ideally after a refactoring, the program should work exactly the same as it did before. In the "Double Trouble" lessons, we refactored the code by creating a BouncingBall class and moving the bouncing ball logic and data into that class. In this lesson, we will refactor the code to use an array to store the BouncingBall information.

    The format for declaring an array is as follows:

    datatype [] fieldName;

    Where the data type can be a primitive, such as float, or a class, such as BouncingBall. In our case, in the Game1 class, replace the ball1 and ball2 declarations in the Game1 class with the following:

    BouncingBall [] balls; 
    int ballCount = 2;

    The ballCount Field will help us later when we want to change how many elements are in our array. This is a best practice, try not to use constant values all over your code because it makes changes harder later.

    The next step for an array is to initialize the array. At the top of the Game1.Initialize() method, add the following:

    balls = new BouncingBall[ballCount];

    This initializes the array to a size of 2 (since ballCount is 2). Now that the array itself is initialized, we need to initialize each object in the array. We can, as we had before, have a single "new" statement for each object we want to create, but again this can be an issue if you have a lot of objects. So in order to reduce the amount of code, we can use something called a loop. A loop is a block of code that is run multiple times based on conditions. In this case, we will use a "for" loop. Typically a "for" loop is used when you want to start at one number and end at another number. Our loop will start at the smallest index in our array, and end at the largest index. Replace all of the rest of the the ball1 and ball2 code which initializes the objects and sets values in the Game1.Initialize() method with the following:

    for (int index = 0; index < ballCount; index++) 
    { 
       balls[index] = new BouncingBall(); 
       balls[index].Velocity = 
           new Vector2(rand.Next(2, 11), rand.Next(2, 11)); 
       byte r = (byte)rand.Next(64, 256); // Red value 
       byte g = (byte)rand.Next(64, 256); // Green value 
       byte b = (byte)rand.Next(64, 256); // Blue value 
       byte a = (byte)rand.Next(64, 256); // Alpha value 
       balls[index].DrawingColor = new Color(r, g, b, a); 
    } 

    The structure of a for statement has 3 semicolon delimited satements inside the parentheses. The first is executed the first time through the loop and typically initializes the loop index. The second statement is a condition that once false, program execution continues with the next statement after the loop block. The condition is checked every time through the loop, including the first time. If the condition is false on the first time through the loop, the code inside the loop block will not get executed at all. The third statement updates the loop index and is executed at the end of each time through the loop, before the condition is checked again.

    Notice the index++ syntax. The "++" operator is a more efficient way of adding 1 to the value in the variable. It is very common in C# and C++ programming (which incidentally is how C++ got its name) and is the preferred way to increment a variable. There is a corresponding "--" operator which subtracts 1 from a variable.

    So this loop set index to 0, adding 1 each time through the loop, and will execute as long as index is less than 2. Why less than 2? Because as stated above, arrays in C# start at 0, so an array with 2 elements in it has indexes of 0 and 1. Again this is a boundary condition and as discussed in a previous lesson, you need to be very careful around boundary conditions and it's very easy to get them wrong if you're not careful.

    Another type of loop is the "foreach" loop. The "foreach" loop is specifically for looping through an array or list of objects. Though not as flexible as a "for" loop, it is easier to use. For our Update and Draw method changes, let's use the "foreach" loop. First in the Game1.Update() method, remove the ball1 and ball2 Update calls and replace them with the following:

    foreach (BouncingBall ball in balls) 
    { 
       ball.Update(); 
    } 

    As you can see, you don't have to access the array element by index, or do the initialization of the loop variable or checking a condition, that's all handled for you. Similarly in the Game1.Draw() method, replace the ball1 and ball2 calls with this:

    foreach (BouncingBall ball in balls) 
    { 
       ball.Draw(spriteBatch); 
    } 

    Run the program again. You should see 2 balls of random color, opacity, and velocity bouncing around. Run it again, and you will see other combinations of colors and velocities.

    Now for the fun part. Change the ballCount initializer to set ballCount to 10. Run it again. Now set it to 50. As you can see, arrays and loops are very powerful and a key concept in programming.

    50bals

    Posted: Nov 14 2008, 11:07 by Bill Reiss | Comments (3) RSS comment feed |
    • Currently 5/5 Stars.
    • 1
    • 2
    • 3
    • 4
    • 5
    Filed under:
    Lesson 14: Random Thoughts

    Random numbers are very important to game development. This lesson introduces how to use random numbers in your program.

    As usual, we start where the last lesson left off.

    Complete source code for lesson 14: http://www.bluerosegames.com/xna101/lessons/XnaLesson14.zip 

    In most games, the way the game behaves depends on a few factors. Of course one of these is the input from the user who is playing the game via the keyboard, mouse, joystick or game pad. Another is some standard patterns that enemies or other game elements follow based on the situation. However if a game only relied on these factors, the game would get boring quickly since it would always behave in a similar way. A third factor to how a game behaves is randomness. Whether it's the shape of the next piece in a tetris game, or the little unpredictable behaviors of a boss at the end of a Super Mario level, randomness is an important factor in most games.

    The .Net Framework provides a class to C# which generates pseudo random numbers. These numbers are not true random numbers, since the numbers still follow a pattern, but the pattern is so huge and varied that the numbers appear to be random and are uniformly distributed across a range if run through enough iterations. This class, appropriately, is the Random class.

    In our MyFirstGame program, let's use the Random class to control the initial velocity of the bouncing balls.

    First we need to create an object of type Random. Let's do this in the Game1 class, so that it is available to all members of the Game1 class. We don't want to create an instance of the Random class each time we need a random number, both for speed reasons and it could impact how random our numbers are.

    So at the top of the Game1 class definition block with the rest of our Game1 Field definitions, add the following:

    Random rand = new Random();

    Now this statement is a bit different than what we've done in the past. As an alternative to instantiating the Field in the constructor, you can do what is called Field Initialization. In C#, Field Initialization occurs before the constructor is executed. It is simpler to initialize an object this way if certain conditions are met:

    • The Field's constructor must not require any data from any other Fields or any non-constant data.
    • The Field's constructor must not be able to throw an error. This is because there is no way to handle that error properly. If the constructor can throw an error, it is better to instantiate the object in the constructor.

    One of the key parts of the Random class is what is referred to as a seed value. If you initialize a Random object with the same seed value, you will get the same sequence of random numbers every time. If a seed value is not passed in to Random's constructor, the seed value is generated from the system clock, giving a seed value that is going to be different each time unless 2 Random objects are created in the same clock cycle. This can happen on high performance equipment, but since we are only creating one Random object we don't really need to worry about this.

    So now to generate the random numbers. The Random.Next() method has 3 overloads, or 3 different sets of arguments that it can accept. Overloaded methods have the same method name but have different arguments that are passed into the method. They must differ by data type, number of arguments, or both.

    • If Random.Next() is called with no arguments, the result is a non-negative random number greater than or equal to zero, and less than 2,147,483,647.
    • If one argument is passed in, the result is a non-negative random number greater than or equal to 0, and less than the value in the argument.
    • If two arguments are passed in, the result is a random number greater than or equal to the first number, and less than the second.

    Note that for the Random.Next() methods, in the case of the lower bound, or the minimum value returned, the call is inclusive, meaning the value returned can be equal to the lower bound, and in the case of the upper bound, the call is exclusive. The number returned will always be less than, but not equal to, the upper bound. When dealing with ranges, I will often refer to the lower bound and the upper bound. The values equal to and near (slightly larger or smaller than) the lower and upper bounds are called boundary conditions, and are the source of a large percentage of bugs in programs. When building test cases for applications, special attention should be placed on creating test cases for all of the boundary conditions.

    In this particular case, we will use the third overload of Random.Next() with a minimum value of 2, and a maximum value of 11, which will generate numbers between 2 and 10.

    In the Game1.Initialize() method, change the following statement:

    ball2.Velocity = new Vector2(10f, 5f); 

    to:

    ball1.Velocity = new Vector2(rand.Next(2, 11), rand.Next(2, 11)); 
    ball2.Velocity = new Vector2(rand.Next(2, 11), rand.Next(2, 11)); 

    As part of each call to rand.Next(), the seed is updated automatically inside the rand.Next() call so that the next value generated (on the next call to rand.Next()) will be based on that seed. Run the program again a few times and see that each time the balls move at different speeds.

    Posted: Nov 14 2008, 10:52 by Bill Reiss | Comments (0) RSS comment feed |
    • Currently 5/5 Stars.
    • 1
    • 2
    • 3
    • 4
    • 5
    Filed under:
    Lesson 13: The Delicate Sound of Thunder

    Sounds are something that got a lot easier in XNA 3.0. You used to have to create an XACT project, add your sounds to that, and then add your XACT project to your XNA project. Then there were a couple of hoops you had to jump through in your code to make it work. You can still do sounds the old way, and in some cases especially when doing sound mixing, you may need to, but for simple sound effects the technique shown in the sample is quick and easy.

    This lesson begins where Lesson 12 leaves off.

    Lesson 13 Completed Source Code: http://www.bluerosegames.com/xna101/lessons/XnaLesson13.zip

    Sound effects are so important to game development. You can do a great sprite animation for an explosion, but without the KABOOM! it loses a lot of its impact.

    For this sample, we?re going to use a free sound from Flashkit.com, a great resource for free sounds. Another great place is A1 Free Sound Effects: http://www.a1freesoundeffects.com/noflash.htm

    From Flashkit.com, download the following:

    http://www.flashkit.com/downloads/soundfx/wav/7730/Boing.zip

    Extract the sound file Boing-Sith_Mas-479.wav and add it to your Content folder.

    XNA 3.0 provides the SoundEffect class to make it easy to play sound effects. This class is located in the Microsoft.Xna.Framework.Audio namespace, so make sure your BouncingBall.cs and Game1.cs files have the following using statement at the top:

    using Microsoft.Xna.Framework.Audio;  

    Let?s declare a static field in the BouncingBall class to hold the sound effect:

    static public SoundEffect Boing;

    Then like we did previously for textures, we?ll do a Content.Load in the Game1.LoadContent method:

    BouncingBall.Boing = Content.Load<SoundEffect>("Boing-Sith_Mas-479");

    Now that the sound effect is loaded, it?s time to figure out when to play the sound. In the BouncingBall.Update() method, add this declaration to the beginning of the method:

    bool bounced = false;

    This declares a boolean, or true and false value, that we can use as a flag to determine whether a bounce took place. As part of the declaration, we are setting its initial value to false. It will keep that value until the end of the method unless it is changed.

    So now inside the both of the two conditional "if" blocks, add the following statement:

    bounced = true;

    and lastly, at the end of the method, if bounced is true, meaning we hit a wall, we want to play the sound. So add the following lines:

       1: if (bounced == true) 
       2: { 
       3:    Boing.Play(); 
       4: } 

    In C#, the double equals sign in the "if" conditional statement means we are doing a comparison, not an assignment. If we used a single equals sign there, the code would think we wanted to set bounced to true instead of checking to see if it was true, and so the conditional would always be true, and the sound would always play.

    That?s all there is to it. Run the program again. If all went well, you should get a boing sound every time a ball hits a wall.

    Posted: Nov 11 2008, 13:27 by Bill Reiss | Comments (4) RSS comment feed |
    • Currently 5/5 Stars.
    • 1
    • 2
    • 3
    • 4
    • 5
    Filed under:
    Lesson 12: Transparent Sprites

    This lesson focuses on how to draw a sprite in XNA where some of the background or sprites behind it shows through.

    We pick up where Lesson 11 left off.

    Source code for Lesson 12 completed: http://www.bluerosegames.com/xna101/lessons/XnaLesson12.zip

    When I first started digging into XNA, I had a hard time figuring out how to draw a sprite so that some of the background shows through. Some reasons you may want to draw a sprite that you can see through is for fog effects, making a character glow, or for a drop shadow on an object. It turns out that it's very simple, and that could be one of the reasons I had trouble finding information on the topic.

    When we draw the sprite, we can draw it with less than 100% opacity. 100% opacity means the object cannot be seen through whatsoever, and 0% opacity means the object is completely transparent.

    The Color object that we used in lesson 10 to tint the sprite can also be used to control the opacity. The Color object has a fourth parameter besides Red, Green, and Blue. This parameter is called Alpha and controls the amount of opacity to draw with. This value, like the Red, Green, and Blue values has a range of 0 to 255, with 255 being completely opaque, and 0 being completely transparent.

    So all we have to do to is pass a color to the Draw() method which specifies a value less than 255 for the Alpha value. The Color object has another constructor which takes four arguments with the fourth being the Alpha value.

    In the Game1.Initialize() method, change the statement that sets ball2's drawing color to the following:

    ball2.DrawingColor = new Color(255, 0, 255, 128); 

    128 is halfway between 0 and 255, so ball2 will be drawn at 50% opacity.

    Run the program again and see that the background now shows through the purple ball.

    trans

    In the game I'm currently working on, I use transparency to draw a drop shadow. This is fairly straightforward to add to the BouncingBall class.  To draw a drop shadow, draw the same texture as the sprite itself, but offset, with a black tint, and with a lower opacity value than the sprite itself. To do this, let's add a new private Color field to the BouncingBall class called _dropShadowColor. In this case, we won't expose a public property to set the _dropShadowColor, instead it will be set inside the class.

    Add the following line to the BouncingBall class to declare _dropShadowColor

    private Color _dropShadowColor; 

    Then in the constructor, let's give it a default value.

    _dropShadowColor = new Color(0, 0, 0, 128); 

    The drop shadow color, by default, will be black with 50% opacity.

    However, if we set the drawing color to something other than 100% opacity, we need to adjust the drop shadow opacity accordingly. So in the BouncingBall.DrawingColor Property's set method, add the following:

    _dropShadowColor = new Color(0, 0, 0, (byte)(_drawingColor.A / 2)); 

    "A" is the Alpha value of the color, so this sets the Alpha of the drop shadow to half of the value of the drawing color's Alpha value. The "/" character performs division, and the "(byte)" casts the value into a value of type byte. The byte data type is what the constructor expects to be passed in for the Alpha value, and has a value of 0 to 255. When one data type is converted to another it is called casting. The division causes an implicit cast to type int, so it needs to be cast back to a byte or you'll get an error when you build the program. More about casting in a later lesson.

    So this is a good example of how properties can be useful. Just by setting the DrawingColor property, we actually set the value of two fields.

    So all that's left is to Draw the drop shadow. It needs to be drawn before the actual sprite, for the same reason we had to draw the background first. So at the beginning of the BouncingBall.Draw() method add the following:

    spriteBatch.Draw(Texture, _position + 
        new Vector2(10f, 10f), _dropShadowColor); 

    which will draw the drop shadow using the drop shadow color at a position 20 pixels to the right and below the sprite. Run the program again and it should look like this:

    shadow

    Posted: Nov 11 2008, 04:59 by Bill Reiss | Comments (2) RSS comment feed |
    • Currently 5/5 Stars.
    • 1
    • 2
    • 3
    • 4
    • 5
    Filed under: