XNA Game-Themed Assignment (XGA)
XGA-500: 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-500 assignment module. Please follow this link to find out more about XGA-500 assignment module and all other XGA assignments. Topics covered in this implementation guide include:
Working with more complex application state (a continuously descending rectangles).
Simulating free fall: animation with simple equation (ball with initial velocity and gravity).
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, XGA-300, XGA-400, and here is the summary of all XGA implementation guides.
Please download the XNA_Tutorial zip file and unzip this file. You should open the project in the Game Studio Express IDE and follow the source code while reading the rest of this lab manual.
2. Implementation:
Now, compile and run the XNA_Tutorial application. You should see:
Notice that (note: this is
the
controller keyboard mapping):
Rectangle: The texture mapped (UW Bothell) rectangle continuously sink towards the lower part of the application window. When the
rectangle reaches the bottom, it jumps to
the top and repeats the descending action.
Left ThumbStick and A Button: Push the left ThumbStick to control the green rectangle on the lower left side of the drawing area. Since it's being drawn at an almost 45 degree angle, it may appear to be more like a stick. Observe that the green rectangle/stick change size/direction according to the left thumbstick movements. When you click the A button the circle on the lower-left corner will appear as though it has been shot along the green rectangle towards the top-right and free falls down towards the bottom. Notice that the longer the green rectangle, the further the circle is shot.
In this case, we want to concentrate on the controls and interaction of the objects in motion (the circle and the dropping rectangle). For simplicity and clarity, there is only single source file in this project. In the rest of this document, we will first examine the image textures and then explain the implementation of the above functionality.
3. Images in the Content/Resource/Textures Folder:
![]() |
uwb_logo.jpg |
![]() |
![]() |
![]() |
explosion.png | rock.jpg | bgTexture.jpg |
4. The Source Code Structure:
The source code folder structure and
file names are identical to the previous examples. In this case, we are only interested in the BurstABubble_Guide.cs source file. Once again, we will
concentrate on examining:
4a. Main class declaration, constants, and instance variables:
In the beginning of BurstABubble_Guide.cs
file we can see:
public
class
BurstABubble_Guide :
XNACS1Base
{
// Private application
state
private Vector2
m_ShotV;
// Velocity of the shot
private
Vector2 m_UserV;
// Velocity defined by the thumbStick |
The constants define the coordinate for the
application window and the dimensions of the shot-circle (m_ShotCircle)
and the dropping rectangle(m_DroppingRect) is the dropping rectangle and
m_ShotCircle. We can see that the circle’s
velocity changes as it moves across the application window. Thus, we define the
m_ShotV to record the uptodate circle
velocity.
protected override
void InitializeWorld() {
World.SetWorldCoordinate(new
Vector2(WORLD_MIN_X, WORLD_MIN_Y),
WORLD_WIDTH);
World.SetBackgroundColor(Color.LightPink);
Vector2 pos = new
Vector2(50.0f, 50.0f);
m_DroppingRect = new
XNACS1Rectangle(pos, ..., @"uwb_logo");
pos.X
= INIT_SHOT_POS_X;
pos.Y
= INIT_SHOT_POS_Y;
// Initial position of the shot
m_ShotCircle = new
XNACS1Circle(pos, SHOT_RADIUS);
m_ShotCircle.CenterColor = Color.White;
m_ShotCircle.OutsideColor = Color.Black;
m_ShotV = new
Vector2(0.0f, 0.0f);
m_UserV = new
Vector2(3.0f, 3.0f);
m_ShootRect = new
XNACS1Rectangle(new
Vector2(0.0f, 0.0f), m_UserV, 1.0f,
"");
m_ShootRect.OutsideColor = m_ShootRect.CenterColor =
Color.Green;
|
As always, we first
define the coordinate system and the background color. After which:
· Label A: Define the dropping rectangle to be located at (50,50) with "uwb_logo" texture.
· Label B: The shot circle is initialized to locate at the lower left corner with proper outside and inside colors.
· Label C: Initialize the shot-circle velocity to be zero and the velocity of the "shot-stick" (green stick at the lower left corner) to be some sensible value.
· Label D: The lower-left corner green "shot-stick".
4c. 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 sink the
rectangle, fly the circle, and when A button
is pressed/released re-shoot the circle:
protected override void UpdateWorld() { float gravity = 0.12f;
if (World.CollideWorldBound(m_DroppingRect) == BoundCollideStatus.CollideBottom) m_DroppingRect.CenterY = 50.0f; else m_DroppingRect.CenterY -= gravity;
// Label B: collide the circle with the window bounds and decide what to do BoundCollideStatus stat = World.ClampAtWorldBound(m_ShotCircle); float len = m_ShotV.Length(); switch (stat) {
case BoundCollideStatus.InsideBound: // Label B1: if completely inside the window bounds if ((len > 0.05f)||(m_ShotCircle.CenterY > (1.5f * INIT_SHOT_POS_Y))) { m_ShotCircle.Center = m_ShotCircle.Center + m_ShotV; m_ShotV.Y -= gravity; } else { // if the circle is moving very slowly, stop it. m_ShotV = new Vector2(0.0f, 0.0f); m_ShotCircle.CenterY = INIT_SHOT_POS_Y; } break;
case BoundCollideStatus.CollideBottom: // Label B2: bounces off the bottom if ((len < 0.05f)&&(m_ShotCircle.CenterY < (1.5f * INIT_SHOT_POS_Y))) { // if the circle is moving very slowly, stop it. m_ShotV = new Vector2(0.0f, 0.0f); m_ShotCircle.CenterY = INIT_SHOT_POS_Y; } else { // bounce the circle m_ShotV = DecreaseVelocity(m_ShotV, len*0.75f); m_ShotV.Y = -m_ShotV.Y; } break;
case BoundCollideStatus.CollideTop: // Label B3: bounces off the top m_ShotV = DecreaseVelocity(m_ShotV, len); m_ShotV.Y = -m_ShotV.Y; break;
case BoundCollideStatus.CollideLeft: case BoundCollideStatus.CollideRight: // Label B4: bounces off the sides m_ShotV = DecreaseVelocity(m_ShotV, len); m_ShotV.X = -m_ShotV.X; break; }
// Label C: if button-A clicked, re-shoot the circle Vector2 aim = XNACS1Base.GamePad.ThumbSticks.Left; m_UserV += aim * 0.1f; if (XNACS1Base.GamePad.ButtonAClicked()) { m_ShotV = m_UserV; // Fire new shot m_ShotCircle.CenterX = INIT_SHOT_POS_X; m_ShotCircle.CenterY = INIT_SHOT_POS_Y*1.1f; }
// Label D: manipulating the shooting rectangle Vector2 pa = new Vector2(0.0f, 0.0f); Vector2 pb = 5.0f * m_UserV; m_ShootRect.SetEndPoints(pa, pb, 1.0f); ... } |
Notice that the
first line defines a gravity. This number will be used to
decreased the y-component of the rectangle position and the circle’s velocity.
5. Important Observations:
The above implementation demonstrates:
·
1.
The circle: follows its initial velocity with y-component
continuously decreases, when the y-position of the circle is zero, it stops
moving.
2.
The rectangle: decreases y-component (dropping) until it’s
y-component becomes zero, it is reset to initial-y value to repeat the dropping
behavior.
This rules are referred to as our application state. In general our application state can be arbitrarily complex. For efficiency
consideration, it is important to remember to check if objects are visible in
the application window. For example, as the traveling circle drops beneath the
lower boundary of the application window (y < 0), it will not be visible in the application window
any longer and thus we will not need to compute the circle’s positions any
further.
·
Input device (user)
specifying values:
the left thumbstick specifies the initial velocity of the circle. This value is
used only when the user shoots the circle (when the A-Button is
depressed). Allowing the user specifying an initial value for an object is an
important interaction technique.
· Input device (user) initiates action: notice that the A-Button click causes the circle to begin traveling. In this case, we have chosen to receive the initial velocity from the thumbstick. It is just as simple to choose two random numbers as the initial x/y-components for the circle velocity. The important observation here is that the user’s action initiates an application state change.
6.
Exercises:
1.
Implement 3 dropping rectangles:Define
3 rectangle positions in the
BurstABubble_Guide class,
initialize the positions to:
i.
(20, 50)
ii.
(50, 50)
iii.
(80, 50)
In UpdateWorld(), decrease the y-values of each of the above position by 0.1. If the y-component of a position becomes less than zero, reset it to 50 again.
2.
Modify the above dropping rectangle with some randomness: in UpdateWorld() when the y-component of a
position is less than zero, instead of resetting to 50, compute a random number
between 40 to 60 as the initial y-component.
3.
Implement shoot 2 circles: Define 2 circles and 2 shot
velocities in the BurstABubble_Guide class:
XNACS1Circle m_ShotCircle1, m_ShotCircle2;
Vector2 m_ShotV1, m_ShotV2;
In our application we will treat ShotCircle1/V1, and
ShotCircle2/V2
as two separate pairs. In UpdateWorld():
o
If Button-A is clicked, we will initialize V1 with m_UserV and begin changing
Circle1.
o
If Button-B is clicked, we will initialize V2 with m_UserV and
begin changing Circle2.
Now, instead of one shooting
circle, we can have two.
7. Start
the Assignment:
Here is the
starter project for students to start working on the assignment. You should
be able to compile and have a skeleton program where you can burst bubbles with
rocks (Button-A). The .exe file in the SampleSolution folder of
the start project is an implementation of solution. Check out the fireworks that you can
release with Button-B!
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.