Monday, August 31, 2009

Learning XNA 3.0 by Aaron Reed (Chpters 1 and 2, Book Summary)


Chapter 1 - Getting Started
In order to use XNA you'll need to have installed Windows XP(SP2/SP3)/Vista) and Visual C# 2008 or Visual Studio 2008. After that you'll need to download XNA Game Studio 3.1.

Almost all types of code you write for PC using XNA 3.0 can be directly ported to both Zune and Xbox 360.

The program.cs file is pretty straightforward. Your Main method, which creates a new object of Game1 type and executes its Run method, is located in this file.

The real guts of your game lie in the Game1.cs file.

Chapter 2 - Fun With Sprites

  • GraphicsDeviceManager;
  • Acts as a conduit between XNA and GPU
  • Require for every action taken to the screen
  • SpriteBatch
  • Generate core object to draw sprites
  • 2D or 3D images integrated into a larger scene.
  • Initialize Method
  • Initialize variables and other objects associated with Game1 object.
  • GraphicsDeviceManager object is instantiated at this point.
  • LoadContent
  • Instantiates spriteBatch
  • Called whenever new content is in need to be loaded.
  • After it’s called, Game1 object enters in a state known as game loop.
  • Game Loop
  • Update
  • The logic calculations should take place here
  • Draw
  • It's better to be used only to draw
  • Game Development Versus Polling
  • Polling
  • The applications is alwasys performing actions regardless of user input
  • You have to account for a bunch of user inputs and the implications of such inputs to the game.
  • Registering Events
  • The application awaits user input to resume its actions.
  • Game States
  • Defines some changes in the game behavior
  • Change of state must take place in the Update Method
  • Drawing implications of that should be implemented in the Draw method


Basic Lifecycle of an XNA game.

  • Unload Content
  • Allows special handling of memory for objects.
  • Garbage collection is taken care of by XNA.
  • Modifying Your Game
  • The gameTime variable
  • Used to gauge things such as framerate, animations, sounds, and other effects.
  • GraphicsDevice objects' clear method
  • Erases everything on the screen, and covers it with the specified color.
  • Adding a Sprite to Your Project
  • All graphics, sounds, effects, and other items are loaded in XNA through something called the content pipeline.
  • content pipeline
  • convert loaded files, if necessary
  • You can view if the added items were accepted by right-clicking the item in Solution Explorer and selecting Properties
  • Uses an asset name to access content resources
  • File's name without the file extension, by default.
  • Asset names only need to be unique within each content folder.
  • A texture refers to a 2D image that will typically be applied to a surface of some object.
  • Loading and Drawing Your Sprite
  • Before you have access to content from the inside of the code, you need to load them from the content pipeline into variables.
  • Texture2D type variables.
  • To access data from the content pipeline, you use the Content (ContentManager type) property of the Game class.
  • Provides access to all objects loaded in the content pipeline.
  • ContentManager
  • Load method.
  • Content.Load(@"path_to_file");
  • The path starts with the Content node in Solution Explorer.

----------------------------------------------------------------------------------
spriteBatch.Begin( );
spriteBatch.Draw(texture, Vector2.Zero, Color.White);
spriteBatch.End( );
----------------------------------------------------------------------------------



  • In 2D XNA games, the X, Y screen coordinate (0,0) is the top-left corner of the screen; coordinates move in positive X to the right and positive Y downward.
  • Window.ClientBounds
  • When a game is run in Windows, Window.ClientBounds.X and Window.ClientBounds.Y correspond to the upper-left coordinate of the game window, while the Width and Height properties of Window.ClientBounds are always equal to the width and height of the window.
  • On the Xbox 360 and the Zune, Window.ClientBounds.X and Y are always 0, while the Width and Height properties of Window.ClientBounds are always equal to the width and height of the display (because both Zune and Xbox 360 games are always run in full-screen mode).
  • Texture2 variables have Width and Height properties that hold the size of the image.
Transparency and Other Options

  • Mainly for performance reasons, you should draw as many sprites as you can in a single SpriteBatch Begin and End block.
  • XNA Automatically renders solid magenta (255,0,255) portions of images trasnparent.
  • Certains types of file format such as .png make use of an alpha channel - each pixel has an additional alpha channel that determines the transparency of the pixel.
  • SpriteBatch.Draw(Texture, Position, SourceRectangle, Color, Rotation, Origin, Scale, Effects, LayerDepth)

Layer Depth
  • XNA lets you specify a layer depth for each individual image, which allows you to always place images in the right Z order. In order to do that you must make use of the last presented overloaded Draw method.
  • The layer depth parameter is represented by a float value that must be between 0 and 1. The valye 0 corresponds to what XNA calls the front of the Z order; the value 1 represents the back of the Z order.
  • In order to use layer depth values to sort your images, you need to use an overload of Begin that takes a parameter of type SpriteSortMode. One of these overloaded methods is: SpriteBegin(SpriteBlendMode,SpriteSortMode,SavestateMode);
  • In order to animate sprites along the screen, you'll need to update their positions in the Update method. For that, you'll may find useful to create Vector2 and float type variables.
  • The vector type variables, will be used to determine the object's location on the plane when you draw;
  • The float type variables can be used to update the sprites' coordinates, accounting as a speed factor.
Animation
  • Animations are made up of standalone images, and flipping through the images in a cycle causes them to appear animated.
  • Sprite animations are laid out in a single sheet, and you pull out individual images from that sheet and draw them on the screen in a specific order. These sheets are referred to as sprite sheets.
  • In order to draw only a specific portion of the sprite sheet, you'll need to make use of the third parameter of the overriden Draw method shown above of the green table just up at this page.
  • There are few things you need to know in order to build an algorithm that will cycle through each image encompassed into each sub-rectangle:
  1. The height and width of each individual image (or frame) in the sprite sheet;
  2. The total number of rows and columns in the sprite sheet;
  3. An index indicating the current row and column of the image in the sprite sheet that should be drawn next.
With these parameters in hand, you can build a source rectangle to pass to the Draw method;

To make things easier, you may find useful the use of Point object to store these values: Point(int x, int y);

To animate sprites using a sprite sheet you'll also be using the Rectangle object: Rectangle(int init_x, int init_y, int width, int height), which will be passed in the draw method;

Adjusting the Framerate

  • As mentioned before, framerate generally refers to how many times per second a game redraws the entire scene. In XNA, the default is 60 fps.
  • There's a type of framerate related to individual animations. This framerate (often referred to as animation speed) reflects the rate at which a given animation cycles through images in the sprite sheet.
  • XNA's Game class has a property called TargetElapsedTime, of the TimeSpan type, which tells XNA how long to wait between calls to the Game.Update method.
  • The GameTime object, which is passed in as a parameter in both the Update and Draw methods, has a Boolean property called IsRunningSlowly. If its value is true, XNA isn't able to keep up with the framerate. In this case XNA will skip Draw calls in a effort to keep up with your intended speed.
  • The speed of the graphics card GPU, the speed of the computer's processor, the number of resources you consume, and the speed of your code, go a long way toward determining whether your game will have that peak performance.

Adjusting the Animation Speed

If you wanted one image to animate at 60 fps and another to animate at 30 fps, you wouldn't be able to accomplish that by adjusting the overall game's framerate.

To adjust the frame animation individually for an object you may use two variables of the int data type to keep track of the last time you changes frames and to only change frames every X number of milliseconds:

int timeSinceLastFrame = 0;
int millisecondsPerFrame = 50;

timeSinceLastFrame => registers how much time has passed since the last frame skip
millisecondsPerFrame => determines the frame skip rate.

These variables would be used in the Update method to determine the framerate of a given object probably like this:



As you can see here, you use the gameTime.ElapsedGameTime property to determine how much time has passed since the previous frame change. This property indicates how much of time has passed since the previous call to Update. You add the Milliseconds property of that object to your TimeSinceLastFrame variable. When the value of that variable is greater than the number of milliseconds you want to wait between frame changes, you enter the if statement, adjust the TimeSinceLastFrame variable by subtracting the value in MillisecondsPerFrame, and then change the animation frame.

Conclusion: While the dafault framerate in XNA draws a new frame every 16 milliseconds, that is nothing compared to the default framerate of Chuck Norris' fists. On average, Chuck's fists punch and mortally wound enemies every 4 milliseconds! O.O