XNA Game-Themed Assignment (XGA)
XGA-300: 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 sample solution to the XGA-300 assignment module. Please follow this link to find out more about XGA-300 assignment module and all other XGA assignments. Topics covered in this implementation guide include:
Working with button clicks..
Choosing a convenient coordinate system: matching game board dimension to the world dimension.
Creative use of textures (numbered textures as labels for game cells).
Working with more source code files.
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 not already done so, you may wish to look at implementation guides to earlier assignments: XGA-100, XGA-200, and 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):
Button-A: moves the girl hero character forward by some random steps.
The rest of this document explains how to draw the background game board and move the hero character.
3. Images in the Content/Resources/Textures Folder:
This project includes 4 texture files: the gold bar, the hero, the snake, and the ladder:
![]() |
![]() |
![]() |
![]() |
kid.png | gold.png | ladder.png | snake.png |
As in all texture images in XGA projects, these files are stored in the Content/Resources/Textures/ subfolder.
4. Coordinate and Design of the Game Board:
The above figure illustrates the design of the game board. In particular, notice that:
Coordinate system: for the ease of programming, we have designed each game cell to be of size 1 by 1. In this case, for the 5 rows by 10 columns game board, the application dimension should be 5x10. For aesthetic reasons, it is desirable to define some boundaries between the game board and the application window. For this reason, as illustrated at the lower-left corner of the above figure, we have defined the lower-left corner of the application window to be (-0.4, -0.4) and the width of the application window to be 10.8. The details of the coordinate system implementation can be found in SnaleAndLadder.cs, this will be discussed later.
Cell position and index: with the above coordinate design, each game cell's location and index has very simple relationships,
Cell located at row=r, column=c will have its center located at (r+0.5, c+0.5) where row/column are numbers between 0 and max row/column on the game board.
In a one-dimensional array the index of cell (r,c) is simply: (r * (maxColumn-1) + c).
For example, as illustrated at the bottom of the above figure, the cell located at row=1, column=5 has its center located at (1.5, 5.5) and with 10 columns on the game board, the index=9+5=14.
The details of cell position and index implementation can be found in GameBoardUI.cs and will be discussed later.
Game cell : The top of the figure uses cell-42 as an example to illustrate the construction of a game cell.
The cell: each game cell is drawn as a light-sea-green rectangle of 0.95 width by 0.95 height.
The grid lines: The grid lines between the cells are actually background color. Since each cell rectangle is drawn at its center and the size of each rectangle is 0.05 less the the dimension of the game cell, there is a 0.1 gap between neighboring cells and thus form the grid lines.
The cell number: the cell numbers are rectangles texture mapped with appropriate number images.
The gold: the gold is simple a texture mapped rectangle.
The details of game cell creation can be found in GameBoardUI.cs and will be discussed later.
Hero character: The hero character is a simple texture mapped rectangle.
Notice that the above details were designed before the implementation of the
actual assignment. In general, it is more efficient to have a detailed
layout of graphical object construction before implementation. 5. The Source Code Structure: The source code folder structure
and file names are similar to that discussed in the
XNACS1Lib
guide. In this case, there are two important
differences: SnakeAndLadder.cs: this
is the main source file of the project where we subclass from and override
the appropriate functions defined in the XNACS1Base class. GameBoardUI.cs: this is
the class defined to capture the behavior of the game board. Recall that in
XGA-100 and XGA-200 implementation guides, for simplicity and readability,
all functionality were defined in the same class/file. Starting from this
implementation guide, as the complexity of the applications increases we
will introduce extra source code files/classes to encapsulate behaviors.
6. The SnakeAndLadder.cs file :
Once again, this is the subclass from XNACS1Base where the required constructor/functions are implemented:
Constance and Instance Variables
InitializeWorld()
UpdateWorld()
6a. The Constance and Instance Variables:
In the beginning of
SnakeAndLadder.cs
file we can see:
public class SnakeAndLadder
: XNACS1Base { private ... TOTAL_CELLS = 50; // number of cells (row x column) private ... BORDER_SIZE = 0.4f; // boundaries around game board
private ... WORLD_MIN_X = -BORDER_SIZE; // lower-left corner private ... WORLD_MIN_Y = -BORDER_SIZE; // is (-0.4, -0.4) private ... WORLD_WIDTH = 10.0f + (2*BORDER_SIZE); // compensate boundaries
private GameBoardGUI m_Boardgui; // the game board ... |
As discussed in the design of the game board, for aesthetic reasons lower-left corner of the application window is defined to be (-0.4, -0.4). Notice the GameBoardUI class will encapsulate the game board user interaction. The SnakeAndLadder class will forward all appropriate user commands to the m_Boardgui object.
6b. The InitializeWorld() function:
protected override void InitializeWorld() { World.SetWorldCoordinate(new Vector2(WORLD_MIN_X, WORLD_MIN_Y), WORLD_WIDTH); World.SetBackgroundColor(Color.LightSkyBlue); // background color
} |
As always, defines the coordinate system, sets background color, allocates memory.
6c. The UpdateWorld() function:
protected override void UpdateWorld() { if (GamePad.ButtonAClicked()) { // A-Button clicked int move = 1 + RandomInt(5); // Random between 1 to 6 m_Boardgui.MoveBy(move); // invoke game board m_Status = @"Button A ... " + move; // status for user ... |
Since the game board behavior is supported in the m_Boardgui object, UpdateWorld() only need to forward user's commands.
7. The GameBoardUI.cs file:
This class supports the game board logic and drawing. The important functions contained in this file include:
Constructor: constructs the game board.
MoveBy(): support movement of the hero character in the game board.
GetCellPosition(int index): translates the hero position from index to 1D array to (x,y) coordinate position that is suitable for drawing.
The
constants: In the beginning of GameBoardUI.cs
file we can see:
enum
BoardCellContent {
// Game
cell
content
HasGold,
// either has gold ... or
HasNothing
// does not have anything
};
//
Label A:
instance variable describing the game board dimension
private
BoardCellContent[] m_GameBoard; // Game
board is stored as a 1D array
private
XNACS1Circle[] m_GoldBars; //
For
showing gold bars
private int
m_MaxColumn; // number of column
on the board
private int
m_TotalNumCells; // Total number game
cells
// Label B:
hero's position: index and (x,y) position
private int
m_CurrentIndex; // current index
position of the hero
private
XNACS1Circle
m_Hero; //
The
Kid
//
Label C:
constants for drawing the cells
private const
float SIZE = 0.95f;
// Size of each game cell
private const
float LABEL_SIZE = 0.2f; //
size of number label in the cell
private static
float GOLD_SIZE = 0.25f; //
size of the gold bars
... // offsets for number labels and the
gold
·
Label A:
here we represent the game board as 1D
array.
·
Label B:
notice that the index and position information are redundant. In our
application, the m_CurrentIndex is convenient for moving the hero forward
in the game board while the m_Hero is convenient for drawing and
everything else (e.g., collision if/when necessary).
·
Label C:
These constants supports the design of
the game board. Please refer to the earlier
discussion for details.
In the constructor of the game board, we must allocate the memory for the game cells, and initialize the location of the gold bars.
public GameBoardGUI(int numCells, int maxColumn) { m_MaxColumn = maxColumn; // initialize the variables m_TotalNumCells = numCells; m_GameBoard = new BoardCellContent[numCells]; // allocate the array m_GoldBar = new XNACS1Circle[numCells]; // allocate the array
// Label A: loop through all the game cells for (int i = 0; i < m_TotalNumCells; i++) m_GameBoard[i] = new BoardCellContent(); if (RandomNumber() > 0.3f) // 30% chance for gold bar m_GameBoard[i] = BoardCellContent.HasNothing; m_GoldBar[i] = null; else m_GameBoard[i] = BoardCellContent.HasGold;
... // Label B: Initialize the hero position m_CurrentIndex = 0; // initial hero index is 0 m_Hero = new XNACS1Circle(GetCellPosition(m_CurrentIndex), ...); // corresponding (x,y) pos } |
As show above after the initialization of instance variables:
· Label A: loops through each of the memory cell, allocate the memory, and with 30% of probability a gold bar may be present.
· Label B: initialization of the hero position at the 0-th position. Notice we call the GetCellPosition() to ensure that the hero's (x,y) coordinate position properly corresponds to its current index position.
7b. The
MoveBy() function:
public void MoveBy(int num) { m_CurrentIndex = (m_CurrentIndex + num) % m_TotalNumCells; m_Hero.Center = GetCellPosition(m_CurrentIndex); } |
7d. The GetCellPosition()
function:
private Vector2 GetCellPosition(int index) { int row = index / m_MaxColumn; // row is index div column int col = index % m_MaxColumn; // col is index mod column Vector2 p = new Vector2(); p.Y = row + 0.5f; // X is 0.5 offset from row p.X = col + 0.5f; // Y is 0.5 offset from column if (0 != (row % 2)) // if odd-row p.X = m_MaxColumn - p.X; // counts backwards return p; } |
Get cell position translates 1D index into the corresponding 2D coordinate position. In this case, the row number is imply index div maxColumn, and column number is simply the remainder of the same division. As discussed in the game board design, coordinate value is simply 0.5 offset away from the (row, column). The only additional detail here is that to support more graceful movement of the hero when she travels across different rows, odd-number rows count right-to-left.
8. Important Observations:
The above implementation demonstrates:
· Coordinate System: the choice of coordinate system allowed straightforward translation between array index, and coordinate drawing position. This greatly simplifies the logic of the application and thus the application.
· Abstraction: game board is complete self-contained. More importantly, in this application the hero is represented by a simple integer number (m_CurrentPos). This example clearly illustrate that internal representation can be drastically different from graphical display for the user.
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.