Developing Programming Assignments on the XBOX 360
Console
Section
II: The XnaAssignmentBase Library
a. The library SDK
This is a wrapper class over the XNA framework. This class is designed to be simple and easy to use. As such, only drawings of circles and rectangles in 2D space are supported. Except for input from the Gamepad, programmers working with the XnaAssignmentBase class do not need to know anything about the XNA framework. If you are interested (and only if you are interested) here is the source code to the XnaAssignmentBase library. Note that you do not need to look at the source code implementation to learn how to work with the library. You should be able to read through this entire tutorial without looking at the source code of the XnaAssignmentBase library.
This document uses a simple working program (download the TemplateAssignment.zip) to explain how to work with the XnaAssignmentBase class.
The Sample Template Application:
Unzip TemplateAssignment.zip and you will see a folder named TemplateAssignment, inside this folder are two items:
|
Folders/Files |
Purposes |
|
Assignment_PC.csproj |
XNA GS project description
file. This file is necessary but we will not work with this file. |
|
Assignment.cs |
This is the one file that
contains the interesting source code of our project. This document will only
refer to source code from this file. |
|
Program.cs |
A dummy container. We do
not need to be concerned with the contents of this file. |
|
Game.ico GameThumbnail.png |
Image on the top-left
corner of the title bar of the application window and when the application
window is iconized. |
|
SupportFiles/XnaAssignmentBase_PC.dll |
The DLL library file that
contains the XnaAssignmentBase. |
|
Properties/AssemblyInfo.cs |
Contains miscellaneous
information on the application. We will not work with this file. |
|
Content/Content.contentproj |
XNA GS content project
description file. This file is necessary but we will not work with this file. |
|
Content/Resources/Fonts/Arial.spritefont |
The font used by our application. This
folder and the font that must exist
for all XnaAssignmentBase projects! |
|
Content/Resources/Textures/bgTexture.jpg Content/Resoruces/Textures/uwb_logo.jpg |
Images that are used as
textures in our drawings. We will discuss the use of these images when
discussing drawing of circles and rectangles. |
|
Content/Resoruces/Audio/GameAudio.xap |
This is a project file
created by the Microsoft Cross-Platform
Audio Creation Tool. We will discuss this file in details at the very
last of this tutorial guide. |
|
Table 1: Folders and Files of the sample template project |
|
Now, start the XNA GS, build and run the program. Figure 1 shows what you will see when running this application.
|
|
You should observe an application
window with light pink background color; four circles one at each corner of the
window; a small rectangle in the center; and two rather large rectangles
connecting top and bottom right to the center. To interact with this example:
Left/Right Triggers: press and hold the left or right trigger on the controller, the center rectangle and bottom right circle will rotate and the controller will vibrate (no vibration effects on the keyboard).
The rest of this document explains, in detailed, how to accomplish all these functionality.
To work with the XnaAssignmentBase class to implement
the sample template application, we only need to pay attention to Assignment.cs
file. Please refer to Assignment.cs file for the following
discussion.
There are 6 important aspects to using the XnaAssignmentBase
class:
The very first few lines of source code in Assignment.cs
file are the C# using statements:
|
using System; // System libraries using System.Text; // Text using
System.Collections.Generic; // Collections using
Microsoft.Xna.Framework; // XNA libraries using
Microsoft.Xna.Framework.Graphics; // Utilities
(e.g.,Vector2) using
Microsoft.Xna.Framework.Input; // For GamePad object using XnaAssignments; //
Our own library |
Notice that besides using typical system libraries, we
must also use the XNA libraries. The XnaAssignments is referring to the XnaAssignmentBase library.
|
|
To ensure
proper linking, the XnaAssignmentBase must
be properly referenced from the References folder. As shown in Table
1, the library file, XnaAssignmentBase_PC.dll, is located
in the SupportFiles folder of the
project.
The XnaAssignmentBase library assumes
that the Resources folders to be part of the uapplication project. The
following figure shows the Resources folders.
|
|
Notice that the Audio, Fonts and Textures
subfolders must be present:
This is a project file created by the Microsoft Cross-Platform Audio Creation Tool. This tool is part of the XNA Game Studio distribution. You should be able to double click this file and start the audio creation tool. If this file is missing, your application will still run. However, without this file your application cannot generate any audio effects. We will discuss audio support at the very last of this tutorial.
This is the font used by the library in displaying
status to the application window. This Font must
be present in this folder, otherwise, the application will fail!
These are jpg images referenced by our drawing
routines. Notice that these images are in jpg format. Any images referenced by
drawing must be stored into this
folder, otherwise, the application will fail.
The main class for the application (in this case the Assignment class) must be a sub-class of
the XnaAssignmentBase
class. The following code shows the declaration of the Assignment class.
|
public class Assignment
: XnaAssignmentBase { private const float WORLD_MIN_X = 5.0f; // min corner is
(5, 10) private const float WORLD_MIN_Y = 10.0f; private const float WORLD_WIDTH = 20.0f; //
width is 20.0 // Notice we must call
the base constructor! public Assignment() : base(new Vector2(WORLD_MIN_X, WORLD_MIN_Y), WORLD_WIDTH) { // Notice: memory
allocation and initialization should be performed // in InitializedWorld().
The constructor should be empty. } |
Notice that we must
call the base class constructor when constructing the Assignment class. In this case, we are defining a drawing area where
the bottom-left corner is defined to be (5,10) with the width of the drawing
area being 20. Since the graphics device
is created and initialized after the constructor, to avoid
potential bugs, it is recommended that all memory allocation and initialization
be performed in the InitializedWorld() function.
The constructor should be left empty.
When calling the base class constructor, we as the
programmer, we can define the coordinate
range for drawing in the application window. Noice that this range is
independent from the hardware pixel units. In this case, for illustration
purposes, we have chosen the lower left corner to be cooridnate position
. This
is to say, if we draw a circle with radius of 1 at position (6,11), the circle
will show up at the lower left corner with left and bottom of the circle
touching the left and bottom edges of the application window. The light gray circle at the lower left
corner of Figure 1 is such a circle. We will examine the details
of drawing this circle later.
Due to the aspect ratio limitation of HDTV, the height
and width of the drawing area are always related with a fixed aspect ratio:
![]()
In this case, with a
width of 20, the height of the drawing area is:
![]()
This means, the
center of the drawing area is:

As highlighted at the
bottom of Figure 1 and as will be discussed later, when running the sample
template application, the computed center position is indeed (15, 15.625). We
will examine the computation of these values later.
As a programmer using the XnaAssignmentBase class,
we must override three functions:
|
protected override void
InitializeWorld() { // BackgroundTexture = @"bgTexture"; // texture
image name BackgroundColor = Color.LightPink; } protected override void UpdateWorld()
{ … // Input values from the Gamepad // Details
shown in the last section. m_Rotation += rotR
- rotL; if (rotR > 0) XnaAssignmentBase.PlayACue(1.0f, "Right"); //
right audio effect … } protected override void
DrawWorld() { … // Draws all the circles and rectangles // Details
shown in next section. } |
This function is called exactly once at the beginning
of the application. We should allocate memory and initialize variables in this routine.
In the above case, we initialize the background color to be light pink. The
commented out code sets the background to be an textured image. You are
encouraged to un-comment the line and re-compile/re-run the application to
observe the differences. We will discuss about BackgroundColor and BackgroundTexture later.
NOTE: The commented out line
assigns bgTexture to be the
background texture image. Notice that “beTexture”
is the name of the “bgTexture.jpg” file
located in the Content/Resources/Textures
folder. Notice that the image file must exist in the texture folder. In
addition, notice that the image file
is referred to without the “.jpg” extension.
This function is called once about every 25
milliseconds. Notice that this is frequent enough for real time animations. As an application programmer, we should
udpate the values of the instance variables according to the logics of our
application. In this case, rotR and rotL are values from the gamepad
triggers: when the user press the gamepad triggers, rotR and rotL will become
non-zero. We increase/decrease the m_Rotation
value accordingly. The m_Rotation value
will be used in DrawWorld() to rotate
the center rectangle and bottom right circle. The PlayACue()
function plays a short snipet of audio effect. In this case, a pre-recorded
wave file that contains a cue namde “right” is played. We will discuss audio
effect at the very last of this tutorial.
NOTE: It is very important to never issue
any drawing commands from the UpdateWorld()
function. DrawWorld() should be
the only function that issues drawing commands.
This function is also called once about every 25 milliseconds. This function complements the UpdateWorld() function, where after the
application state is updated, this function will be responsible for drawing
everything. The details of drawing is left until next section.
NOTE: It is very important to never change any application state (i.e.,
instance variables) in this function. UpdateWorld()
is the function that is responsible for updating the instance variables.
This function should only issue drawing commands.
The XnaAssignmentBase class supports a
total of 3 2D drawing routines, and two different status echo functions. In
addition, an application program can inquire about the drawing dimension and
set the background color/texture. No other functions are supported. The
simplicity and restriction are results of concious design decisions. We want to
keep the library simple such that people with no gaming or graphics background
can begin programming with minimal overhead.
As we have already seen (in InitializeWorld()):
Color BackgroundColor – A write-only variable for
setting the background of the drawing area (application window).
String BackgroundTexture – A write-only variable for
setting an image to be the background of the drawing area (application window).
Notice that when BackgroundTexture
is pointing to a valid image, the image will be displayed in the application
window and BackgroundColor is
ignored.
At any point in our application, when we need to find
out about the dimension of the drawing area, we can access:
Vector2 WorldMin – A read-only variable that
returns the coordinate position at lower left corner.
Vector2 WorldMax – A read-only variable that
returns the cooridnate position at the upper right corner.
Notice that these variables are read-only. This means,
once the cooridnate range is defined (during the base contructor call), it cannot be changed during run-time.
Please refer to Figure 1, the top and bottom left of the application window include text displays of the application status.
|
void EchoToTopStatus(String msg) void
EchoToBottomStatus(string msg) |
Each of the above two functions is capable of echoing
status to the corresponding area of the application window.
The DrawCircle()
function draws a circle based on a center and radius:
|
|
The first DrawRectangle()
function draws a rectangle based on the center and dimension of the
rectangle:
|
|
The second DrawRectangle()
function draws a rectangle based on end positions and length of the
rectangle:
|
|
In all three draw functions, texName can refer to a
image texture file, or a null pointer. When present, the image will be pasted over the circle or rectangle.
DrwaWorld()
function re-visit:
With the above discussion, we can now examine the
details of the DrawWorld() function.
The followings are the content of the DrawWorld()
function:
|
// Label A: float radius = 1.0f; // set width and length to some
constant values // Label B: Vector2
bottomLeft = new Vector2(WorldMin.X
+ 1, WorldMin.Y + 1); Vector2
topLeft = new Vector2(WorldMin.X
+ 1, WorldMax.Y - 1); Vector2
topRight = new Vector2(WorldMax.X
- 1, WorldMax.Y - 1); Vector2
bottomRight = new Vector2(WorldMax.X
- 1, WorldMin.Y + 1); Vector2
center = new Vector2(WorldMin.X
+ (WorldMax.X - WorldMin.X) / 2,
WorldMin.Y + (WorldMax.Y - WorldMin.Y) / 2); // Label C: draws rectangle with two end points (white center) DrawRectangle(bottomRight, center, radius, Color.Red,
Color.White, null); // Label D: draws the four corner circles DrawCircle(bottomLeft, …, Color.LightGray,
Color.LightGray, null); DrawCircle(topLeft, …, Color.LightGray,
Color.White, null); DrawCircle(topRight, …, Color.LightGray,
Color.Red, null); DrawCircle(bottomRight, …, Color.LightGray,
Color.Blue, @"uwb_logo"); // Label E: draws the center rectangle with image texture DrawRectangle(center, length, width, …, @"uwb_logo"); // Label F: draws rectangle with two end points (Cyan) DrawRectangle(topRight, center, radius, Color.Cyan, Color.Cyan,
null); // Label G: echo the status EchoToTopStatus(@"…:"
+ topRight); EchoToBottomStatus(@"…:" + bottomLeft + "
Center:" + center); |
We see that:
· Label A: variables are initialized. In particular, the radius variable for all the circles is set to 1.0.
· Label B: bottomLeft, topLeft, topRight, and bottomRight are four corners each one unit away from the boundaries of the drawing area.
· Label C: draws a rectangle with two end points. Notice the color settings, this is drawing the long rectangle on the right side of Figure 1, where the center of the rectangle is in white.
· Label D: draws the four circles, each with radius of 1 and with center being distance of 1.0 away from the boundaries of the drawing area. Notice the four circles in Figure 1, each touching the boundaries of the drawing area. The important lesson to be learned here is that, we as programmer, we can define the drawing coordinate (when calling the base constructor) and we do not need to be concerned with the underlying pixel units.
· Label E: draws a rectangle with a center and dimension. Notice we specify the “uwb_logo” as texture image for the rectangle. Once again, please refer to our earlier discussion, “uwb_logo” refers to the “uwb_logo.jpg” file, and this file must be located in the Resources/Textures folder.
· Label F: draws a rectangle with both inside and boundary colors set to cyan. This will draw a solid cyan-color rectangle.
· Label G: echo interesting coordinate information to the top and bottom echo areas. Notice that the center position is printed out to the bottom status area. Recall the discussion regarding coordinate definition; we can now verify these values.
Drawing
Order:
Lastly, observe the drawing order of the rectangles. The Cyan rectangle is on top of (covers) the center rectangle, which is on top of the first drawn rectangle with white center. This observation tells us that later drawn objects override the color of the earlier drawn objects. If you want an object to be on top of all other objects, draw it the last.
For simplicity, the XnaAssignmentBase class simply
duplicates and presents the GamePadState. Please refer to the
xna.Framework.Input library, our input class works in exact the same way as the
Gamepad (controller) device. At anywhere in our application, we can access the
gamepad by:
|
XnaAssignmentBase.GamePad.
… |
Where
GamePad: works identical to xna.Framework.Input.GamePadState.
The following code segment is from UpdateWorld():
|
// Label A: float rotL = XnaAssignmentBase.GamePad.Triggers.Left; float rotR = XnaAssignmentBase.GamePad.Triggers.Right; // Label B: XnaAssignmentBase.SetGamePadVibration(PlayerIndex.One, rotL, rotR); m_Rotation += rotR - rotL; // Label C: if (XnaAssignmentBase.GamePad.ButtonBackClicked()) this.Exit(); |
We see that:
· Label A: set rotL, and rotR variables using the left and right triggers of the controller.
· Label B: use the rotL and rotR values to vibrate the controller. When the triggers are not pressed, these variables will be zero, and the controller will not vibrate.
· Label C: detect if the Back button has been clicked, if so quits the application.
NOTE: A Word
about ButtonClick vs. ButtonState :
The GamePad structure reflects the state of the controller device. For example, it is possible to inquire if a button is pressed, e.g.:
|
If XnaAssignmentBase.GamePad.Buttons.A == ButtonState.Pressed) |
Notice that a button pressed state is different from a button click action. The button state faithfully records the current condition of the button (released or pressed), while the click action records the button transition from released state to pressed state. XnaAssignmentBase library records button click actions for the following buttons:
|
A Button clicked: GamePad.ButtonAClicked() B Button clicked: GamePad.ButtonBClicked() X Button clicked: GamePad.ButtonXClicked() Y Button clicked: GamePad.ButtonYClicked() Start Button clicked: GamePad.ButtonStartClicked() Back Button clicked: GamePad.ButtonBackClicked() |
The following diagram illustrate the names of the input
devices on the controller:
|
|
For more detailed information on the gamepad, please
refer to:http://msdn2.microsoft.com/en-us/library/microsoft.xna.framework.input.aspx
In the absence of a dedicate XBOX 360 controller, the
keyboard is automatically polled. Here is the supported keyboard mapping.
1. Single controller support: Currently this library only supports one game pad. At this point, there is no way to program with other game pads connected to the XBOX 360 unit. On a PC with keyboard, one can creatively map the left/right thumb sticks of the single game pad for two players.
2. Vibration: Notice that the game pad vibration (SetGamePadVibration()) is set by a function and not through the GamePad object interface like the rest of input functionality. We will try to fix this problem in the future releases.
The only supported audio effect function is:
|
void
XnaAssignmentBase.PlayACue(float length, String cueName) |
Where
length: is how long (in seconds) to play the cue. For example,
length of 0.8f will play the cue for 0.8 seconds.
cueName: is the name of the cue to be played.
Recall that:
Content/Resources/Audio/GameAudio.xap
is the file that contains the audio effects. If you
double on this file, you will see:

1.
Wave Bank: XnaAssignmentBase assumes only one wave bank by the name of GameWaves.
Notice that if GameWaves is missing, it will be a run time error and your
application will crash. GameWaves should contain all the
sound waves (in .wav format) you wish to use in your application. In this case,
we use the SoundRecorder program and
recorded us saying “Left” and “Right”. Store the two short snippets as
“Left.wav” and “Right.wav” files. These two files are then loaded into the GamesWave wave bank. Warning:
As illustrated in the following figure, with GameWaves selected, you
should double to check under Windows
Properties and Xbox 360 Properties and
make sure the BuildNames are set to GameWaves.xbs (you can simply
click-in and rename the fields).

2.
Sound Banks. XnaAssignmentBase assumes only one sund bank by the name of GameSounds.
Notice that if GameSounds is missing, it will be a run time error and your
application will crash. GameSounds should contain all the
sounds you will to use in your program. In this case, we created the sounds
from the corresponding wave files in the wave bank (by simply dragging the files from GameWaves over to GameSounds). Warning:
As illustrated in the following figure, similar to the GameWave’s case,
with GameSoundss
selected, you should double to check under Windows Properties and Xbox
360 Properties and make sure the BuildNames are set to GameSounds.xsb
(you can simply click-in and rename the fields).

3.
Cues: in the XnaAssignmentBase.PlayACue(float length, String
cueName) function,
the cueName is referring to names of
these cues. In our case, we simple drag the
corresponding sounds from GameSounds into
the Cue window to create the “Left” and
“Right” cues.
Notice that unlike the texture image files, where each texture image is presented as a
separate file to our project. In the case of audio effects, our project only
work with one single file: GameAudio.xap.
For audio effects to operate properly, this file must be present in the Audio
subfolder under Resources. All your wave files and
cue snippets should be maintained by the GameAudio.xap
file. Plesae refer to the following reference to find out more about how to
work with the Microsoft Cross-Platform
Audio Creation Tool. You may wish to consider copying the GameAudio.xap file from this project to
your own project. You can then edit the file, remove/replace the wave files,
and create appropriate sounds and cues from your own wave files.
1. Single bank support: Notice the extremely simple single bank audio effect support. This means, you cannot play more than one audio effects at a time! For example, the XnaAssignmentBase library does not support a background music going while overlaying foreground effects.
2. Dropping of Cues: If you made multiple PlayACue() function calls in a short interval, chances are some of the cues will simply be dropped! Only one cue is played at anytime, during this time, the rests of the cues wait. As time elapsed, all cues’ requested play time are updated (even for the waiting ones). When a cue’s requested play time expired, it is removed. For example, during UpdateWorld() you issue two PlayACue() function calls, both with requests of one second. In this case, only one of the two cues will play (the first issued), while both cues will expired at the end of one second elapsed time. The second issued cue effect will simply be dropped.
1. Use it as a hint to events: Use audio cues to inform students something has happened (e.g., the net has touched an insect), and do not attempt to use audio effect as any kind of background on-going music.
2. Use one cue at a time: Since only one cue can be played at anytime, it is really useless to issue more than one cue effects at a time, i.e., do not call PlayACue() more than once during a single UpdateWorld() function. For example, in your application a hero is walking and encountered gold nugget during a single UpdateWorld() function. It may be your desired to play a cue representing hero walking, and a separate cue representing the encountering of gold nugget. In this case, you should weigh the importance and only play one of the cues.
3. Use shorter cues rather than longer cues: The audio support will honor the requested duration of a cue before continuing to the next cue. This means, if you start a 5 minute audio effect, within this 5 minutes no other audio effects will be played. In general multiple meaningless short audio snippets corresponding to significant events is much more informative than one meaningful audio segment representing one of the significant events. For example, if 5 collisions occurred over a period of 1 seconds. In this case it is much more informative for the user to hear 5 distinct audio cues (each can be 0.1 seconds in length), than for the user to hear a single one-second audio segment that accurately represents one of the 5 collisions. With our simple library support, in general, your audio cues should probably be less than 1 seconds.
Color: defined in System.Drawing. Please refer to http://msdn2.microsoft.com/en-us/library/system.drawing.color.aspx
for more information.
String: defined in Sytem.String. Please refer to http://msdn2.microsoft.com/en-us/library/system.string.aspx
for more information.
Vector2: defined in Microsoft.xna.Framework. Please refer to http://msdn2.microsoft.com/en-us/library/microsoft.xna.framework.vector2.aspx
for more information.
Gamepad Input with XNA: defined in Microsoft.xna.Framework.Input.
Please refer to http://msdn2.microsoft.com/en-us/library/microsoft.xna.framework.input.aspx
for more information.
Microsoft Cross-Platform Audio Creation Tool (XACT): This program is part of
the Game Studio Express release. Please
refer to http://msdn2.microsoft.com/en-us/library/bb174772%28VS.85%29.aspx
to find out more about how to work with this program.
|
|
This document and the related materials
are developed with support from Microsoft Research Computer Gaming Initiative
under the Computer Gaming Curriculum in Computer Science RFP, Award Number
15871 and 16531.
|
Kelvin Sung |