XNA Game-Themed Assignment (XGA)
XGA-100: Implementation Guide
Kelvin Sung Computing and Software Systems University of Washington, Bothell ksung@u.washington.edu |
Michael Panitz Software Programming Cascadia Community College mpanitz@cascadia.ctc.edu |
1. Topics Covered:
This document explains some of the implementation details found in the example solution to the XGA-100 assignment module. Please follow this link to find out more about XGA-100 assignment module and all other XGA assignments. Topics covered in this implementation guide include:
Controlling object movements based on controller trigger.
Using texture maps to show left/right facing.
Changing object color during run time.
Pre-Requisite:
It is assumed that you have read the following documents:
The XNA Installation Guide: guides you download and install the XNA SDK and Game Studio Express IDE.
The XNACS1Lib Guide: describes how to work with the XNACS1Lib class.
If you have never worked with XGA assignments before, here is the summary of all XGA implementation guides.
Please download the XNA_Tutorial zip file and unzip this file. It is best to open the project in the Game Studio Express IDE and follow the source code while reading the rest of this implementation guide.
2. Implementation:
Now, compile and run the XNA_Tutorial application. You should see:
Notice that (note: this is the controller keyboard mapping):
Left Trigger: When depressed, the
chameleon turns and face left and the circle
will move left.
Right
Trigger:
When depressed, the chameleon turns to face right and the circle will move right.
In addition, notice that the color at the center of the circle reflects the
region it is located in. This color will change as the circle center is moved across the boundary between the blue/pink regions. In this application, the
two color regions are defined by two constant color rectangles.
The rest of this document explains how these functionality are implemented.
3. Images in the Content/Resources/Textures Folder:
The Resources/Textures folder (in the IDE this can be found under the Content folder) contains two files, l_chameleon.png and r_chameleon.png. The two files represent the left (l__) facing and right (r_) facing version of the chameleon.
The above figure shows that depending on which of the left or right trigger is depressed the corresponding chameleon image will be mapped onto a square. The textured square will then overlap on top of a circle to create the effect of a "chameleon in a circle". The implementation for texture selection is explained in UpdateWorld.
4. The Source Code Structure:
The source code folder structure and file names are similar to that described in the XNACS1Lib guide. The only difference is that, in this case, the program source code is located in the SwitchAndMod_Guide.cs file (instead of the Game1.cs file). We are going to examine the content of this file in detailed.
Recall that when working with the XNACS1Base class, we need to pay attention to the following 6 specific items:
- Declaring and using libraries.
- Resources folders (Fonts, Textures, and Audio) and files.
- Subclass from XNACS1Base.
- Override the two functions:
- InitializeWorld()
- UpdateWorld()
- Understand and know how to use the classes defined in the XNACS1Base class.
- Know how to call the input functions to work with the XBOX controller.
Since the provided source code is a working program, the above items has all been properly taken cared for. The functionality we are interested in are implemented in items 2, 3 and 4. We will examine these functions.
Main
Class Declaration and Construction
In the beginning of
SwitchAndMode_Guide.cs
file we can see:
public class
SwitchAndMode_Guide
: XNACS1Base {
private const float WORLD_MIN_X = 0.0f; // lower left
corner (0, 0)
private const float WORLD_MIN_Y = 0.0f;
private const float WORLD_WIDTH = 20.0f; // width is 20.0
float m_RecWidth;? // width of the two constant color
rectangles float m_RecHeight;?// Height of the two constant color rectangles |
Notice that in this case, we have
defined an intuitive coordinate system where the lower-left corner is the
origin (0,0), and we have defined the width of the drawing area to be 20 units.
4a. The InitializeWorld()
function:
protected override void
InitializeWorld() {
World.SetWorldCoordinate(new
Vector2(WORLD_MIN_X, WORLD_MIN_Y),
WORLD_WIDTH);
m_RecHeight =
WorldMax.Y - WorldMin.Y; // rectangle covers the
height XNACS1Rectangle r = new XNACS1Rectangle(rCenter, m_RecWidth, m_RecHeight); r.OutsideColor = Color.LightBlue; // Left rectangle is in light blue r.CenterColor = Color.LightBlue; rCenter.X += m_RecWidth; r = new XNACS1Rectangle(rCenter, m_RecWidth, m_RecHeight); r.OutsideColor = Color.Pink; // Right rectangle is in pink r.CenterColor = Color.Pink;
// B: Top-most object should be created last Vector2 chameleonPos = new Vector2(5.0f, 6.0f); m_ChameleonBase = new XNACS1Circle(chameleonPos, 2.0f); m_ChameleonBase.OutsideColor = Color.White; m_ChameleonBase.CenterColor = Color.White; m_Chameleon = new XNACS1Rectangle(chameleonPos, 3.0f, 3.0f, "l_chameleon"); // Look left "l_chameleon" } |
As shown above, we always initialize the coordinate system first. After which:
A: create the two background constant colored rectangles: the two rectangles are created side-by-side horizontally each with width of half the WORLD_WIDTH and height equals to the entire height of the WORLD_HEIGHT. In this way, the two rectangles will cover the entire drawing area.
B: the Chameleon is a textured rectangle
over a circle. To ensure the Chameleon-rectangle is displayed over
the circle, we have to create the circle first.
We use the
In both cases, the created primitives (circle and rectangles) will be added to
the AutoRedraw set and will be drawn in the application window.
4b. The UpdateWorld() function:
Recall that the UpdateWorld()
function is responsible for keeping the application’s state up-to-date. In
this case, we need to check the Triggers to
move the Chameleon:
protected override void
UpdateWorld() { // Allows the default game to exit on Xbox 360 and Windows if (XNACS1Base.GamePad.ButtonBackClicked()) this.Exit();
// Label A: Pool the left/right triggers float deltaL = XNACS1Base.GamePad.Triggers.Left; float deltaR = XNACS1Base.GamePad.Triggers.Right;
// Label B: Update Chameleon texture and audio if (deltaR > 0.0f) { m_Chameleon.Texture = "r_chameleon"; // right-facing texture XNACS1Base.PlayACue("zoom"); // audio response } else if (deltaL > 0.0f) { m_Chameleon.Texture = "l_chameleon"; // left-facing texture XNACS1Base.PlayACue("zoom"); // audio response }
// Label C: Update Chameleon position m_Chameleon.CenterX += deltaR - deltaL; // chameleon position World.ClampAtWorldBound(m_Chameleon); // clamp to window bounds m_ChameleonBase.Center = m_Chameleon.Center; // base circle position
// Label D: Update Chameleon base circle color if (m_ChameleonBase.CenterX < m_RecWidth) m_ChameleonBase.CenterColor = Color.LightBlue; else m_ChameleonBase.CenterColor = Color.Pink;
// Label E: Echo status EchoToTopStatus(@"ChameleonBase Position:" + ...); EchoToBottomStatus(@"World Min:" ...); } |
As in most cases, the first operation
performed is check for exit status (BackButton clicked). after which, the
application state is updated accordingly:
Label A:
We poll the left and right triggers' states and use those values to update
the circle center position. These two delta values will be used to update the
position of the chameleon.
Label B: We use the values of deltaL/R as a hint to determine which of the left/right chameleon texture to use and to provide audio feedback for the user. For example, a value of greater than zero signifies the right trigger is depressed and thus we should use the right-facing chameleon image.
Label C: We use the values of deltaL/R to update the horizontal position of the chameleon (m_Chameleon.CenterX). After the update, we first clamp Chameleon position to within the application boarder by calling ClampAtWorldBound() before assigning the position to the base circle.
Label D: We check the current circle position to determine the color to use for drawing the center of the circle.
Label E: text status update.
Note: Since all primitives are in the AutoDraw set, we do not need to worry about drawing these primitives.
5. Important Observations:
The above implementation demonstrates: User control of object: notice that the position of the circle is controlled by the user. Values from the input devices (user choice) are used to modify the current values of the circle.
6. Exercises:
1. Instead of WORLD_WIDTH of 20, change it 30. Now modify all necessary values (including rectangle width) such that the look and behavior of this program remains the same. The important lesson from this exercise is that we can implement the same functionality with different coordinate dimensions. Depending on the graphics and interaction of your applications (assignments) you should design the coordinate range/dimension accordingly.
2. Add a third color region (e.g., LightGreen) with a third rectangle covering the center third of the drawing area. Change the width of the two existing rectangles such that they only cover the left and right one-third of the drawing area. Now, in UpdateWorld(),?include the logic to compute the proper color such that the m_ChameleonBase's center color will properly reflect that of the three region as user moves the circle left/right.
7. Start the Assignment:
Here is the starter project where the students should start their work to complete the assignment. We have isolated the logic for computing color into the BackgroundStrip.cs file such that students only need to work on this file. In addition, we have clearly identified regions where students should add in their code: it's between the note that says "STUDENTS: YOU NEED TO WRITE YOUR CODE BELOW:", and "STUDENTS: YOU NEED TO WRITE YOUR CODE ABOVE:" with . In this way students do not need to change anything except for the code that they add in order to complete the assignment.
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.