Learn XNA: Useful Types

There are numerous useful types available in XNA that will significantly help you design and build your next game.  Here are two of the most useful (in my opinion) and how you can use them in your game (I will focus on mostly 2-dimensional uses).

Vectors

Vectors are amazing!  They are seriously, probably one of the coolest types on the block, especially when taking into account that they are used for almost everything in games.  The most common forms of Vectors used in XNA are the Vector2 and the Vector3, which are defined as:

    Vector2(float X, float Y)
    Vector3(float X, float Y, float Z)

Also useful, is Vector4 which is similar to a Vector3, but adds a float W parameter on the end.  Vector's are obviously useful anytime you need a small array of floats for any reason (movement speeds, health of 2-4 characters, etc...)  The most practical and useful application of Vectors however is all the mathematical properties they work with.  They are awesome for a quick matrix v. vector multiplication (primarily used in 3D), and are great in 2D for specifying a movement direction, position, and even a scale amount!

Rectangle

Rectangle's are an interesting type.  It took me years before I understood how to effectively utilize the Rectangle type.  There are lots of functions that take Rectangle's as parameters and the sooner you use them, the better your code will look.  There is a default empty definition for a Rectangle, but the most useful in my mind is:

    Rectangle(int X, int Y, int Width, int Height)

The X,Y coordinates are the X- and Y-coordinates for the left and the top edges of the rectangle, respectively.  This essentially defines the upper left corner of the rectangle.  The Width and Height obviously, determine the width and height.  Now that you have Rectangle's being used, you can use them to store global variables useful for determining screen size, specifying the source rectangle from a content file, or useful as a bounding box for collision detection.

Development Diary: Pong RPG

I have been hard at work recently porting Pong RPG from a PC-only XNA game to an Xbox 360 game in the hopes of potentially releasing it on the Xbox Indie Games Marketplace.  Pong RPG (PC) was a great success in my mind because even though it was flawed, it was a full game product that I created from scratch (almost all by myself) since my days in High School (which was when I first created a full game).  While it was great to finish the game, the code was extremely difficult to read and very static.  I learned a lot from finishing that game and have been applying the recently learned techniques to every project since then.  So now that I'm porting the game to Xbox, what exactly goes into porting bad code?

I have been fully re-designing all the code from scratch, essentially rewriting the whole game.  The nice thing though is all the time I spent painfully positioning each sprite on the screen is already done since I'm using the old code as a reference (all my screen positions, rotations, scalings, etc... are there for me).  At home I currently have a 32" plasma HDTV.  When I first created Pong, I built the entire game using a square window and now that I'm in HD, I need to update my old artwork that was built for that screen size (for example, a 1024x768 piece of art with a 1.0 scaling factor won't fill a 1280x720.  Thankfully most of the artwork is finished and only requires updates to shape it correctly and to swap out PC-specific art with Xbox-specific art.

How has the code been cleaned up?  Almost all of the Sprite loading, storing, and rendering is handled by generic classes allowing me to re-use them in future projects.  Here's the setup (class names may differ from my real code):  there is a ContentProcessor class that parses '.LFI' files (simple .TXT files with a different extension standing for 'Load FIle').  Each line of the Load File defines either a SpriteSheet or a Sprite.  A SpriteSheet is a single PNG file containing one or multiple pieces of artwork within.  In Pong RPG (PC) every single sprite had it's own file and required a Content.Load<Texture2D>() call.  The SpriteSheet load file commands simply specify a load file to process. 

The Content Processor then takes the PNG file defined by the Sprite Sheet command and loads it into a TexturePool.  A TexturePool is a class that inherits from List<Asset>.  Asset is a custom struct that only holds two properties about a specific game asset: the Texture (Texture2D), and the Name (String).  Here is the definition for the Load() function of the ContentProcessor class:

    public void ContentProcessor.Load(String fileToLoad, ref TexturePool textures, ref SpritePool sprites)

Obviously the first defines which LoadFile to load.  The second parameter, textures, defines where to store the Assets loaded by the ContentProcessor.  We'll talk about the SpritePool stuff in a little while.  As a side note, ContentProcessor is defined as a static class so we pass the TexturePool and SpritePool variables by reference to avoid requiring the programmer to create an instance of this class.

So ContentProcessor begins parsing the Load File and hits a SpriteSheet command (which should always be first since it's impossible to load a sprite without a related PNG file).  Let's assume we're loading MainMenu.lfi (the Load File for the main menu) and there are 2 PNG's we need to load.  We would have 2 load commands similar to the following:

    SpriteSheet, Sprites\MainMenu\MenuBG
    SpriteSheet, Sprites\MainMenu\MenuItems

In our case, MenuBG is a PNG with artwork that takes up the entire file, and MenuItems is a collection of pieces of art placed around in the file.  After ContentProcessor parses these lines, our TexturePool variable should be populated with 2 items named MenuBG, and MenuItems (the name defaults to the filename). 

Unfortunately that won't be entirely helpful since that only defines the textures and not which parts of them to draw.  This is where Sprites come in and are extremely handy.  After the first SpriteSheet command to load the MenuBG PNG file, we will call a Sprite command to tell the processor to load a sprite and place it in the supplied SpritePool.  SpritePool is similar to TexturePool in that it inherits from the List class, however SpritePool inherits from List<Sprite>.  Sprite is a custom class that holds information about the positioning, rotation, scale, boundingbox, and the source rectangle we use to pull from the SpriteSheets previously loaded.  Here's an example of a Sprite ContentProcessor command:

    Sprite, MenuBG, M-BG, CENTER, CENTER, 0, 1.0, 1.0, 0.1, true, 0, 0, WIDTH, HEIGHT

This looks very cryptic but is really easy to understand.  All it does is define what the ContentProcessor should load, how it should load, and where it should place it.  Here is the definition of this command:

    Type, SpriteSheet Name, Sprite Name, Screen X-Position, Screen Y-Position, Rotation, ScaleX, ScaleY, Layer, Visible, SourceX, SourceY, Source Width, Source Height

The only commands there that may throw you off are the last four containing Source ____.  When you create a new Rectangle in XNA it requires 4 parameters: the left side X-coord, the top Y-coord, the width, and the height.  Essentially, the first two parameters define the upper left corner of the Rectangle.  In our load command, things like CENTER, CENTER, WIDTH, HEIGHT, etc... are simply built in commands that define certain things about how to load it.

We will see more of this in a future code example with a more detailed tutorial!

Learn XNA: Starting Development

Game development is a great career but we all can't be the next John Carmack.  And let's be honest, even though you've got a great resume and a smashing portfolio, the odds are slim you'll get that coveted game programmer job.  To sharpen your skills and expand your portfolio why not take a look at Microsoft's XNA Game Studio?

XNA Game Studio is a library built on top of the DirectX framework to ease game development for students and hobbyists while still providing enough flexibility to create games with the quality of some AAA-titles.  As an added 'bonus', XNA developers can build games for the Xbox 360, distribute the game via the Xbox Live Marketplace, and even profit from their creations.  All in due time young padawan, first you must crawl before you walk....

To get started, you'll need some software on your PC.  The first is Microsoft's Visual Studio.  Preferably 2008, XNA used to run in Visual Studio 2005 and will probably support 2010 in the near future.  Now of course buying Visual Studio would be the best bet considering the quality of the product, but for a whopping $620 (Amazon.com) a lot of us can't afford it.  Luckily, there are a few (legal) alternative methods of acquiring the software.  If you are a student, you may be able to score a free ISO copy of Visual Studio 2008 Professional from Microsoft's Dreamspark Website.  Dreamspark is a resource to provide free Microsoft technologies and software to students.  For the rest of us, Microsoft has generously released slimmed-down versions of the Visual Studio products at their Express products website.  XNA utilizes C# so for the Express products you should grab Visual C# 2008 Express Edition.  Make sure, after you get your respective (legal) copy of the Visual Studio C# editor, that you also make sure you have the latest Service Packs and updates installed.

Next, you need to download and install XNA Game Studio 3.1 (the latest release of the XNA framework).  You can find the download link for XNA GS 3.1 and the aforementioned Visual C# 2008 Express Edition at the Creator's Club website.  Creator's Club is the definitive website for XNA development and your first (and best, in my opinion) resource for XNA development.  The website features tutorials, examples, and starter kits (pre-built games for you to modify), and I can't reccomend it enough!  Check the Resources at the end of this article for some other great websites for you to check out.

As for required software, this is generally all you need to start developing XNA games.  However, if you want to develop for the Xbox 360 console, you'll need to sign-up for a premium membership which costs $49 for 3 months or $99 for a year.  If you are a lucky Dreamspark student, you can grab a free trial membership from Dreamspark.  While the trial will allow you to develop and deploy games to your Xbox console, you will need to purchase a paid membership before you are allowed to submit games for sale on the Xbox Marketplace.  We will go into the process for submitting a game for sale in a future article.

If you are planning on providing all the artwork for your game as well, you will need some kind of image software.  While Photoshop is one amazing program, it can cost between $200-$700 for the latest version.  There is, however, a free program online called Gimp which should be a bit better than your old MSPaint.

By this point you should have stopped reading and started tinkering with all your new software.  The best part?  We have a quality programming environment, a library that supports easy game development, and a full fledged art program for FREE.  You have all the tools to get you started, and this is exactly what Microsoft wanted.  Oh no, we've fallen into a Microsoft trap!!!  Don't fret, this was Microsoft's intention with XNA and it works to our benefit.

I've held your hand a bit during this first article, handing you links and fancy instructions on everything you need.  While the instructions (and maybe the links) will continue in the future, I'm going to go forward assuming you have a familiarity with the C# language.  There are tons of resources online for C# development, and hundreds of books on the subject.  I will be focusing more on techniques used for game development and the XNA framework rather than introducing you to programming.  Now go experiment with XNA you little John Carmack you!

Web Resources:

Microsoft Visual 2008 Express Editions
Microsoft Dreamspark
XNA Creator's Club
Gimp Image Editor

XNA Resources:

Ziggyware
XNA Development
XNA Development Tutorials (my old tutorials)
XNA Resources

Twin Cities Code Camp 7 Reminder

Hopefully you haven't forgotten, but the Twin Cities Code Camp 7 is happening this next weekend!  I will be giving a talk about effectively storing game assets like sprites and models.  This will be my first time writing code during a talk and think it should go pretty well (should take more time compared to my other talks).

There have been some changes this year to the lunch situations so if you haven't yet checked it out, head over to TwinCitiesCodeCamp.com and get all the details.  And if you haven't ever gone to TCCC, I'd highly suggest checking out the site and going next year!

Intro to SVN: Trunk, Tags, and Branches

Subversion (SVN) is a popular tool used by many development teams as their primary way of versioning their code.  Here are some of the basics to SVN.

Possibly one of SVN's best aspects is the ability to work on a shared code base.  This shared code base is called the Trunk.  This is typically where the full, buildable code resides.  It may depend on your team, but this code may be the code you work on daily and commit to.

This leads into the idea of commits and updates.  To illustrate this, let's imagine that you started a small project and had a decent amount of code developed by yourself.  Recently, you've added members to your team and need to provide that code as the shared base (the Trunk).  You've got yourself a server and through the advances in technology have SVN pre-installed and waiting to grab your code.  After opening up your IDE of choice, you would create a Trunk based of the code you have on your machine.  The code you have on your harddrive that is not shared is called your Local Version, or Working Version.  SVN happily creates a Trunk and is ready to give your team the base code.  Now, your team will perform an Update to grab the latest version of the code.  An Update will bring the latest code from the repository to your Local Version.  After that point, your team is able to work on their code on their own machines and work on different parts of the project.  Each person will work on different files and have to submit their changes to the Trunk to create a new, updated version of the code base.  To Commit, is the process of uploading your local changes to the code base to use the newly written code.  When you created the trunk, you Commited your local 'changes' (the change was from nothing to your project) to the Trunk.

Commits and Updates are wonderful, but lead to a major issue.  Let's assume two team members are working on the same file, HelloWorld.txt.  Both team members come into work and grab the latest copy of that file within minutes and begin working on it.  Team Member 1 types the words 'I Love SVN!' into the file and Commits the file.  Meanwhile, Team Member 2 types the words, 'SVN Rules!' into the file and tries to Commit the file.  Suddenly we've hit a snag because Team Member 2 wants to put his changes into the base code but hasn't Updated since Team Member 1 commited his file.  This problem of being 'out-of-sync' is resolved via a process known as a Merge.  A Merge is when a developer looks at the changes to his/her Local Version of a file and the changes made to a Trunk file that hasn't been Updated on the Local Version, and fixes the synchronization issue by ammending the code to include both updates or one of the updates.  Here are Team Member 2's possible merge solutions:

  • Override and Update: In this case, the Local Version of the file is discarded and the Trunk code overwrites everything.  HelloWorld.txt would contain the text 'I Love SVN!' from Team Member 1, but not the text 'SVN Rules!' from Team Member 2.
  • Override and Commit: This is similar to Override and Update, but the Trunk code is overwritten with the Local Version.  HelloWorld.txt would not contain the text 'I Love SVN!' from Team Member 1, but would contain the text 'SVN Rules!' from Team Member 2.
  • Merge Changes: In this solution, both changes are merged into Team Member 2's Local Version and (s)he is able to commit the file and overwrite the Trunk file.  HelloWorld.txt would contain both pieces of text from Team Member 1 and Team Member 2.

During the process of Commiting, Updating, and Merging, the code base can change quite drastically.  As they teach in most computer classes, backing up your data is key to continuing a project without major losses.  SVN handily provides a way to backup your code via Tags.  A Tag is a snapshot of your code at a given time.  It is similar to a Trunk but it is assumed a Tag will not change in the future.  This is useful if a situation arises where it is necessary to revert your code base to a prior state.  In larger environments, Tags are created with each build.

Many projects typically require temporary code written during development in order to test specific issues without a fully functioning product.  Here's an example, assume that project we talked about earlier needs to test a function that calculates the amount of times a number can be divided by 2.  In the final product, that value will be provided by an external system, but currently this system is not implemented.  The plan is to develop a temporary text field that will accept a value and run the function.  In the final product, there will be only a label with the value in it, not a text box.  From what we've been told about SVN up to this point, we would go into the base code, insert our temporary field, and test the function.  This is somewhat practical with a single field, but now let's assume there are 100 fields like this.  Obviously, it would be a massive headache to Update, write the changes, Commit, and in the future have to Update, revert the changes, and Commit.  Sure you could use a Tag, but why create a backup of code that is temporary? 

Introducing Branches, a seperate Trunk-style project used for work on a project similar to this.    If this team hires a new developer and wants to slowly introduce him to the project but doesn't want him developing on the Trunk, what can they do?  Create a Branch for him/her to work on!  Branches can be created from existing code bases, including the Trunk and Tags.  Even better, you can Merge between a Branch and the Trunk to bring in changes from the temporary project that need to be implemented into the code base.

This is a lot of information, and is really basic when talking about SVN, but very helpful when someone asks you, "Are we going to make a Tag of the Branch before Merging into the Trunk?"  Now, go say that to everyone you meet and see if they know their SVN.

XNA: What do you want to learn?

I'm thinking about either re-writing my old XNA tutorials or starting a whole new series.  XNA is now in v3.1 and when I wrote the tutorials we had just jumped from the 1.0 refresh into 2.0.  I want to know what you want to learn about XNA.  Send me an email or post a reply and I'll try to structure it to include what you've asked (hopefully I can teach what you want to learn).

So...

what do YOU want to learn?!

Ping Pong RPG for Xbox

Lately I've been working on bringing my game Pong RPG to the Xbox.  I've slightly changed the title to Ping Pong RPG to make it less like the Atari version and more like my own.  The most exciting part though is the new code!  Here are some of the details of the new code...

In the PC version of Pong RPG, every image/sprite had it's own file.  This means every time I loaded a menu I had to load each menu item, the background, and any other pieces that weren't part of the already loaded images.  To make matters worse, since all my menu items are custom text images, I needed a way to show the user was 'hovering over' (remember, on PC they have a mouse to use) the image.  This means not only did every menu item have it's own file, but the outlined, 'hovered' version also had it's own file that needed to be loaded.  This obviously led to unintentional lag and memory usage.  To fix this issue, I've started creating Sprite Sheets that have all the different textures needed for a screen in 1-3 larger files.  My sprite objects then have Source rectangles that pull the correct image from the sprite sheet.  I haven't worked on the menu items that have hovered versions, but I'm considering simply making a background image to go behind the menu item to signify it's hovered.  Also since it's on Xbox, there will be a little 'A' button image next to the highlighted item.

But wait, it gets worse.  The code written for the PC version of Pong had hundreds upon hundreds of lines of code per class.  For Pong RPG PC, I created functions that essentially create a sprite for me, taking the parameters Name, Scale, Position, Rotation, FILE, etc...  What ended up happening was I needed to write a line or two of code PER image I wanted to load.  Remember, I had tons of images including menu items and their hovered counterparts.  This led to very, very long load statements.  In Pong RPG for Xbox I've simplified the code somewhat by introduing 'LoadFiles'.  A LoadFile is a simple text file filled with statements used to load sprite and image data.  Here is a sample:

'Comment Line - Not Read
SpriteSheet, Sprites\Common\MainMenu
Sprite, MainMenu, CreditsButton, CENTER, CENTER, 0, 1.0, 1.0, 0.1, true, 0, 0, 100, 100

Obviously this is somewhat cryptic to those who don't know the format, but essentially it defines all the parts of the sprite; texture file, sprite name, screenX, screenY, rotation, scaleX, scaleY, layer, visible, sourceX, sourceY, sourceWidth, sourceHeight.  Now, using a text file may be somewhat of a performance hit but I think it really simplifies the code and makes it much easier to read.  Towards the end of Pong RPG PC development was becoming unbearable due to the size of the files, this alleviates my issue.

A final little side note, since I'm running the game on a 1280x720 resolution rather than a 1024x768, all my images are in 'HD' and look pretty cool when plastered upon my plasma TV.

All in all the conversion of Pong RPG PC to Xbox is going pretty well.  A lot of the work is technical and the end user won't ever see and even though the development time may increased slightly due to my work on the updates, the code is much more managable and easier for future work.  I'd like to work on another series of XNA tutorials detailing some of the implementation strategies I've done but I'll have to see how much time I have.

Updates Abound

I have not had a second to update this blog!  Shame on me...

What's new with me you ask?  Most recently I've moved into an apartment!  I'm still getting used to it and since I don't have internet access I'm quite limited with what I do in my spare time.  Lately I've taken to modding Left 4 Dead by creating my own levels.  It's pretty easy and I'm hoping to put a few tutorials up once I understand the Hammer development tool a bit more.

That's all for now, catch ya later.

Twin Cities Code Camp 7

October 24th is the date for the next Twin Cities Code Camp and registration is open.  TCCC is an awesome, free event that everyone that can make it should attend!

For those who don't know, the code camp is a free event held on a Saturday that focuses on many aspects of programming (definitely not only Windows stuff!).  The day is packed with multiple rooms all featuring presentations by great developers so you're bound to learn something.

After every TCCC I'm always pumped to look into something I just learned that day and it's always something new and useful. 

Go register at the site and if you're interested in speaking there are details there as well.  The TCCC site is TwinCitiesCodeCamp.com

Twin Cites Code Camp

Geekdom Strategy Comparison

Last night a few buddies and I geeked out by sitting around for 5 hours and playing the strategy board-game Descent.  It was my first time playing and although we lost, I feel I got a decent 'welcome' into Descent.  And, other than Dungeons & Dragons, was the first strategy game I've ever played (yes, I have never played Risk).

While I understand the appeal of the game, I didn't enjoy it as much as I do when I play D&D.  Though, it's really apples and oranges considering in Descent I was a Hero and in D&D I am typically the DM.  Our play session seemed unnaturally slow for a game.  Each player spent loads of time saying "I could do this, or should I do this?"  That's great you're thinking up a strategy, but what were you doing when it wasn't your turn?  This could be the players I was with, but they had a pretty good understanding of the core system and were still taking hours of time debating the proper way to go down a hall.

The last few D&D sessions I hosted we played with miniatures but no play mats or visible indicators of walls, simply obstacles, enemies, and players.  We still had a great deal of strategy involved regarding placement of characters and such and the game wasn't slowed to a halt by long spurts of indecision.

In comparison, either one of two things generally happened.  Either I overly deluded the strategy in D&D by removing most (not all) walls (the players were outside for the most part), or the Descent guys were over-strategizing (or I suppose regular strategizing).  To me, the game of D&D where strategy was involved but the game kept moving along is a preferred situation compared to a game that stalls on possibilities.

Although, maybe I'm just a strategy noob with 'strategy ADD'.