<< Chapter < Page | Chapter >> Page > |
Complete listings of the program files discussed in this module are provided in Listing 14 and Listing 15 below.
Listing 14 . The Sprite class for the project named XNA0130Proj.
/*Project XNA0130Proj
* This file defines a Sprite class from which a Sprite* object can be instantiated. This version supports
* collision detection based on intersecting rectangles.*******************************************************/
using System;using System.Collections.Generic;
using Microsoft.Xna.Framework;using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;namespace XNA0130Proj {
class Sprite {private Texture2D image;
private Vector2 position = new Vector2(0,0);private Vector2 direction = new Vector2(0,0);
private Point windowSize;private Random random;
double elapsedTime;//in milliseconds//The following value is the inverse of speed in
// moves/msec expressed in msec/move.double elapsedTimeTarget;
//-------------------------------------------------////Image property accessor - new to this version.
public Texture2D Image {get {
return image;}//end get
}//end Image property accessor//-------------------------------------------------//
//Position property accessorpublic Vector2 Position {
get {return position;
}set {
position = value;}//end set
}//end Position property accessor//-------------------------------------------------//
//WindowSize property accessorpublic Point WindowSize {
set {windowSize = value;
}//end set}//end WindowSize property accessor
//-------------------------------------------------////Direction property accessor
public Vector2 Direction {get {
return direction;}
set {direction = value;
}//end set}//end Direction property accessor
//-------------------------------------------------////Speed property accessor. The set side should be
// called with speed in moves/msec. The get side// returns speed moves/msec.
public double Speed {get {
//Convert from elapsed time in msec/move to// speed in moves/msec.
return elapsedTimeTarget/1000;}
set {//Convert from speed in moves/msec to
// elapsed time in msec/move.elapsedTimeTarget = 1000/value;
}//end set}//end Speed property accessor
//-------------------------------------------------////This constructor loads an image for the sprite
// when it is instantiated. Therefore, it requires// an asset name for the image and a reference to a
// ContentManager object.//Requires a reference to a Random object. Should
// use the same Random object for all sprites to// avoid getting the same sequence for different
// sprites.public Sprite(String assetName,
ContentManager contentManager,Random random) {
image = contentManager.Load<Texture2D>(assetName);
image.Name = assetName;//new to this versionthis.random = random;
}//end constructor//-------------------------------------------------//
//This method can be called to load a new image// for the sprite.
public void SetImage(String assetName,ContentManager contentManager) {
image = contentManager.Load<Texture2D>(assetName);
image.Name = assetName;//new to this version}//end SetImage
//-------------------------------------------------////This method causes the sprite to move in the
// direction of the direction vector if the elapsed// time since the last move exceeds the elapsed
// time target based on the specified speed.public void Move(GameTime gameTime) {
//Accumulate elapsed time since the last move.elapsedTime +=
gameTime.ElapsedGameTime.Milliseconds;if(elapsedTime>elapsedTimeTarget){
//It's time to make a move. Set the elapsed// time to a value that will attempt to produce
// the specified speed on the average.elapsedTime -= elapsedTimeTarget;
//Add the direction vector to the position// vector to get a new position vector.
position = Vector2.Add(position,direction);//Check for a collision with an edge of the game
// window. If the sprite reaches an edge, cause// the sprite to wrap around and reappear at the
// other edge, moving at the same speed in a// different direction within the same quadrant
// as before.if(position.X<-image.Width){
position.X = windowSize.X;NewDirection();
}//end ifif(position.X>windowSize.X){
position.X = -image.Width/2;NewDirection();
}//end ifif(position.Y<-image.Height) {
position.Y = windowSize.Y;NewDirection();
}//end ifif(position.Y>windowSize.Y){
position.Y = -image.Height / 2;NewDirection();
}//end if on position.Y}//end if on elapsed time
}//end Move//-------------------------------------------------//
//This method determines the length of the current// direction vector along with the signs of the X
// and Y components of the current direction vector.// It computes a new direction vector of the same// length with the X and Y components having random
// lengths and the same signs.//Note that random.NextDouble returns a
// pseudo-random value, uniformly distributed// between 0.0 and 1.0.
private void NewDirection() {//Get information about the current direction
// vector.double length = Math.Sqrt(
direction.X * direction.X +direction.Y * direction.Y);
Boolean xNegative = (direction.X<0)?true:false;
Boolean yNegative = (direction.Y<0)?true:false;
//Compute a new X component as a random portion of// the vector length.
direction.X =(float)(length * random.NextDouble());
//Compute a corresponding Y component that will// keep the same vector length.
direction.Y = (float)Math.Sqrt(length*length -direction.X*direction.X);
//Set the signs on the X and Y components to match// the signs from the original direction vector.
if(xNegative)direction.X = -direction.X;
if(yNegative)direction.Y = -direction.Y;
}//end NewDirection//-------------------------------------------------//
public void Draw(SpriteBatch spriteBatch) {//Call the simplest available version of
// SpriteBatch.DrawspriteBatch.Draw(image,position,Color.White);
}//end Draw method//-------------------------------------------------//
//This method is new to this version of the Sprite// class.
//Returns the current rectangle occupied by the// sprite.
public Rectangle GetRectangle() {return new Rectangle((int)(position.X),
(int)(position.Y),image.Width,
image.Height);}//end GetRectangle
//-------------------------------------------------////This method is new to this version of the Sprite
// class.//This method receives a list of Sprite objects as
// an incoming parameter. It tests for a collision// with the sprites in the list beginning with the
// sprite at the head of the list. If it detects a// collision, it stops testing immediately and
// returns a reference to the Sprite object for// which it found the collision. If it doesn't find
// a collision with any sprite in the list, it// returns null.
//A collision is called if the rectangle containing// this object's image intersects the rectangle
// containing a target sprite's image.public Sprite IsCollision(List<Sprite>target) {
Rectangle thisRectangle =new Rectangle((int)(position.X),
(int)(position.Y),image.Width,
image.Height);Rectangle targetRectangle;
int cnt = 0;while(cnt<target.Count){
targetRectangle = target[cnt].GetRectangle();
if(thisRectangle.Intersects(targetRectangle)){return target[cnt];}//end if
cnt++;}//end while loop
return null;//no collision detected}//end IsCollision
//-------------------------------------------------//}//end class
}//end namespace
Listing 15 . The Game1 class for the project named XNA0130Proj.
/*Project XNA0130Proj
* This project demonstrates how to integrate* spiders, and ladybugs in a program using
* objects of a Sprite class with collision* detection.
* *****************************************************/using System;
using System.Collections.Generic;using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;using XNA0130Proj;
namespace XNA0130Proj {public class Game1 : Microsoft.Xna.Framework.Game {
GraphicsDeviceManager graphics;SpriteBatch spriteBatch;
//Use the following values to set the size of the// client area of the game window. The actual window
// with its frame is somewhat larger depending on// the OS display options. On my machine with its
// current display options, these dimensions// produce a 1024x768 game window.
int windowWidth = 1017;int windowHeight = 738;
//This is the length of the greatest distance in// pixels that any sprite will move in a single
// frame of the game loop.double maxVectorLength = 5.0;
Sprite spiderWeb;//reference to a background sprite.//References to the spiders are stored in this
// List object.List<Sprite>spiders = new List<Sprite>();
int numSpiders = 200;//Number of spiders.//The following value should never exceed 60 moves
// per second unless the default frame rate is also// increased to more than 60 frames per second.
double maxSpiderSpeed = 30;//moves per second//References to the Ladybugs are stored in this List.
List<Sprite>ladybugs = new List<Sprite>();
int numLadybugs = 5;//Max number of ladybugsdouble maxLadybugSpeed = 15;
//Random number generator. It is best to use a single// object of the Random class to avoid the
// possibility of using different streams that// produce the same sequence of values.
//Note that the random.NextDouble() method produces// a pseudo-random value where the sequence of values
// is uniformly distributed between 0.0 and 1.0.Random random = new Random();
//-------------------------------------------------//public Game1() {//constructor
graphics = new GraphicsDeviceManager(this);Content.RootDirectory = "Content";
//Set the size of the game window.graphics.PreferredBackBufferWidth = windowWidth;
graphics.PreferredBackBufferHeight = windowHeight;}//end constructor
//-------------------------------------------------//protected override void Initialize() {
//No initialization required.base.Initialize();
}//end Initialize//-------------------------------------------------//
protected override void LoadContent() {spriteBatch = new SpriteBatch(GraphicsDevice);
//Create a sprite for the background image.spiderWeb =
new Sprite("spiderwebB",Content,random);spiderWeb.Position = new Vector2(0f,0f);
//Instantiate all of the spiders and cause them to// move from left to right, top to
// bottom. Pass a reference to the same Random// object to all of the sprites.
for(int cnt = 0;cnt<numSpiders;cnt++) {
spiders.Add(new Sprite("blackWidowSpider",Content,random));
//Set the position of the current spider at a// random location within the game window.
spiders[cnt].Position = new Vector2(
(float)(windowWidth * random.NextDouble()),(float)(windowHeight * random.NextDouble()));
//Get a direction vector for the current spider.// Make both components positive to cause the
// vector to point down and to the right.spiders[cnt].Direction = DirectionVector((float)maxVectorLength,
(float)(maxVectorLength * random.NextDouble()),false,//xNeg
false);//yNeg//Notify the spider object of the size of the
// game window.spiders[cnt].WindowSize =new Point(windowWidth,windowHeight);
//Set the speed in moves per second for the// current spider to a random value between
// maxSpiderSpeed/2 and maxSpiderSpeed.spiders[cnt].Speed = maxSpiderSpeed / 2+ maxSpiderSpeed * random.NextDouble() / 2;
}//end for loop//Use the same process to instantiate all of the
// ladybugs and cause them to move from right to// left, bottom to top.
for(int cnt = 0;cnt<numLadybugs;cnt++) {
ladybugs.Add(new Sprite("ladybug",Content,random));
ladybugs[cnt].Position = new Vector2(
(float)(windowWidth * random.NextDouble()),(float)(windowHeight * random.NextDouble()));
ladybugs[cnt].Direction = DirectionVector(
(float)maxVectorLength,(float)(maxVectorLength * random.NextDouble()),
true,//xNegtrue);//yNeg
ladybugs[cnt].WindowSize =
new Point(windowWidth,windowHeight);ladybugs[cnt].Speed = maxLadybugSpeed / 2+ maxLadybugSpeed * random.NextDouble() / 2;
}//end for loop}//end LoadContent
//-------------------------------------------------////This method returns a direction vector given the
// length of the vector, the length of the// X component, the sign of the X component, and the
// sign of the Y component. Set negX and/or negY to// true to cause them to be negative. By adjusting
// the signs on the X and Y components, the vector// can be caused to point into any of the four
// quadrants.private Vector2 DirectionVector(float vecLen,
float xLen,Boolean negX,
Boolean negY) {Vector2 result = new Vector2(xLen,0);
result.Y = (float)Math.Sqrt(vecLen * vecLen- xLen * xLen);
if(negX)result.X = -result.X;
if(negY)result.Y = -result.Y;
return result;}//end DirectionVector
//-------------------------------------------------//protected override void UnloadContent() {
//No content unload required.}//end unloadContent
//-------------------------------------------------//protected override void Update(GameTime gameTime) {
//Tell all the spiders in the list to move.for(int cnt = 0;cnt<spiders.Count;cnt++) {
spiders[cnt].Move(gameTime);
}//end for loop//Tell all the ladybugs in the list to move.
for(int cnt = 0;cnt<ladybugs.Count;cnt++) {
ladybugs[cnt].Move(gameTime);
}//end for loop//Tell each ladybug to test for a collision with a
// spider and to return a reference to the spider// if there is a collision. Return null if there is
// no collision.for(int cnt = 0;cnt<ladybugs.Count;cnt++) {
//Test for a collision between this ladybug and// all of the spiders in the list of spiders.
Sprite target =ladybugs[cnt].IsCollision(spiders);if(target != null) {
//There was a collision. Cause the spider to// move 128 pixels to the right.
target.Position =new Vector2(target.Position.X + 128,
target.Position.Y);//If the collision was with a black widow
// spider, cause it to reincarnate into a// green spider.
if(target.Image.Name == "blackWidowSpider") {target.SetImage("greenspider",Content);
}//If the collision was with a green spider,// cause it to reincarnate into a brown
// spider.else if(target.Image.Name == "greenspider") {
target.SetImage("brownSpider",Content);}//If the collision was with a brown spider,
// it gets eaten. Remove it from the list of// spiders.
else if(target.Image.Name == "brownSpider") {spiders.Remove(target);
}// end else-if}//end if
}//end for loopbase.Update(gameTime);
}//end Update method//-------------------------------------------------//
protected override void Draw(GameTime gameTime) {spriteBatch.Begin();
spiderWeb.Draw(spriteBatch);//draw background//Draw all spiders.
for(int cnt = 0;cnt<spiders.Count;cnt++) {
spiders[cnt].Draw(spriteBatch);
}//end for loop//Draw all ladybugs.
for(int cnt = 0;cnt<ladybugs.Count;cnt++) {
ladybugs[cnt].Draw(spriteBatch);
}//end for loopspriteBatch.End();
base.Draw(gameTime);}//end Draw method
//-------------------------------------------------//}//end class
}//end namespace
-end-
Notification Switch
Would you like to follow the 'Xna game studio' conversation and receive update notifications?