<< Chapter < Page
  Xna game studio     Page 13 / 13
Chapter >> Page >

Listing 13 . Sprite class for project XNA0132Proj.

/*Project XNA0132Proj * This file defines a Sprite class from which a Sprite* object can be instantiated. This version supports * collision detection based on intersecting rectangles.* It also provides an Edge property that records and * returns the edge number if a sprite collides with an* edge. However, the edge information is available for * only one iteration of the game loop. Normally the* value of Edge is 0. However, it changes to 1,2,3,or4 * if a sprite collides with the top, right, bottom, or* left edge of the game window. *******************************************************/using System; using System.Collections.Generic;using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Content;using Microsoft.Xna.Framework.Graphics; namespace XNA0132Proj {class Sprite { private int edge = 0;//new to this versionprivate 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; //-------------------------------------------------////New to this version. //Edge property accessorpublic int Edge { get {return edge; }//end get}//end Edge property accessor //-------------------------------------------------////Image property accessor 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;this.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;}//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) { //New to this version//Clear the Edge property value. Edge information // is available for only one iteration of the// game loop. edge = 0;//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. Also set the Edge property to// indicate which edge was involved. 1 is top, 2// is right, 3 is bottom, and 4 is left. // Note that the Edge property will be cleared// to 0 the next time the Move method is called. if(position.X<-image.Width) { position.X = windowSize.X;edge = 4;//collision with the left edge - new NewDirection();}//end if if(position.X>windowSize.X) { position.X = -image.Width / 2;edge = 2;//collision with the right edge - new NewDirection();}//end if if(position.Y<-image.Height) { position.Y = windowSize.Y;edge = 1;//collision with the top - new NewDirection();}//end if if(position.Y>windowSize.Y) { position.Y = -image.Height / 2;edge = 3;//collision with the bottom - new 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//-------------------------------------------------// //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 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 14 . Game1 class for project XNA0132Proj.

/*Project XNA0132Proj * This project demonstrates how to write a simple 2D* arcade style game. Ten spiders try to make it across * a web from top to bottom in opposition to two* ladybugs. If a ladybug collides with a spider, the * spider is eaten by the ladybug.* * The ladybugs can be moved either with the keyboard or* the mouse. Press the arrow keys to move one of the * ladybugs. Press the A key plus the arrow keys to move* the other ladybug. ** Press the left mouse button to drag one of the * ladybugs with the mouse. Press the right arrow key* to drag the other ladybug with the mouse. ** If a spider makes it from the top to the bottom of * the game window, it wraps back to the top and starts* the trip over. ** On-screen text keeps track of the number of spider * crossings at the bottom of the game window. Note,* however, that if two spiders cross the bottom in * very close proximity, they may not both get counted.* * This program demonstrates how to display on-screen* text. Note however that it is necessary to create * a font resource before you can display onscreen text.* *****************************************************/ using System;using System.Collections.Generic; using Microsoft.Xna.Framework;using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input;using XNA0132Proj; namespace XNA0132Proj {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 = 10;//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 = 2;//Max number of ladybugs//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();//The following variable is used to count the number // of spiders that make it past the ladybugs and// reach the bottom of the game window. int spiderCount = 0;SpriteFont Font1;//font for on-screen text Vector2 FontPos;//position of on-screen text//-------------------------------------------------//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); Font1 = Content.Load<SpriteFont>("Kootenay"); IsMouseVisible = true;//make mouse visible//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 but // near the top of the game window.spiders[cnt].Position = new Vector2((float)(windowWidth * random.NextDouble()), (float)((windowHeight/10) *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//Instantiate all of the ladybugs.They move under // control of the keyboard or the mouse.for(int cnt = 0;cnt<numLadybugs;cnt++) { ladybugs.Add(new Sprite("ladybug",Content,random)); //Position the ladybugs at a random position// near the bottom of the game window. ladybugs[cnt].Position = new Vector2( (float)(windowWidth * random.NextDouble()),(float)(windowHeight - ladybugs[cnt].Image.Height)); }//end for loop//Position the on-screen text. FontPos = new Vector2(windowWidth / 2, 50);//Position the mouse pointer in the center of the // game window.Mouse.SetPosition(windowWidth / 2,windowHeight /2); }//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 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. The spider gets eaten.// Remove it from the list of spiders. spiders.Remove(target);}//end if }//end for loop//Check to see if any spiders have made it to the // bottom edge.for(int cnt = 0;cnt<spiders.Count;cnt++) { if(spiders[cnt].Edge == 3) //One or more made it to the bottom edge.spiderCount += 1; }//end for loop//The following code is used to move one or the // other of two ladybugs using the arrow keys.// Press only the arrow keys to move one of the // ladybugs. Press the A or a plus the arrow keys// to move the other ladybug. //The ladybugs cannot be moved outside the game// window. //When an arrow key is pressed, the ladybug moves//five pixels per call to the Update method. //Get the state of the keyboard.KeyboardState keyboardState = Keyboard.GetState(); //Execute moves on one ladybug with arrow keys plus// the A or a key. if(keyboardState.IsKeyDown(Keys.Left)&&(keyboardState.IsKeyDown(Keys.A))&&(ladybugs[0].Position.X>0)) { ladybugs[0].Position = new Vector2( ladybugs[0].Position.X - 5, ladybugs[0].Position.Y); }//end ifif(keyboardState.IsKeyDown(Keys.Right)&&(keyboardState.IsKeyDown(Keys.A))&&(ladybugs[0].Position.X<(windowWidth - ladybugs[1].Image.Width))) { ladybugs[0].Position = new Vector2( ladybugs[0].Position.X + 5, ladybugs[0].Position.Y); }//end ifif(keyboardState.IsKeyDown(Keys.Up)&&(keyboardState.IsKeyDown(Keys.A))&&(ladybugs[0].Position.Y>0)) { ladybugs[0].Position = new Vector2( ladybugs[0].Position.X, ladybugs[0].Position.Y - 5); }//end ifif(keyboardState.IsKeyDown(Keys.Down)&&(keyboardState.IsKeyDown(Keys.A))&&(ladybugs[0].Position.Y<(windowHeight - ladybugs[1].Image.Height))) { ladybugs[0].Position = new Vector2( ladybugs[0].Position.X, ladybugs[0].Position.Y + 5); }//end if//Execute moves on the other ladybug with arrow // keys pressed but the A key not pressed.if(keyboardState.IsKeyDown(Keys.Left)&&!(keyboardState.IsKeyDown(Keys.A))&&(ladybugs[1].Position.X>0)) { ladybugs[1].Position = new Vector2( ladybugs[1].Position.X - 5, ladybugs[1].Position.Y); }//end ifif(keyboardState.IsKeyDown(Keys.Right)&&!(keyboardState.IsKeyDown(Keys.A))&&(ladybugs[1].Position.X<(windowWidth - ladybugs[1].Image.Width))) { ladybugs[1].Position = new Vector2( ladybugs[1].Position.X + 5, ladybugs[1].Position.Y); }//end ifif(keyboardState.IsKeyDown(Keys.Up)&&!(keyboardState.IsKeyDown(Keys.A))&&(ladybugs[1].Position.Y>0)) { ladybugs[1].Position = new Vector2( ladybugs[1].Position.X, ladybugs[1].Position.Y - 5); }//end ifif(keyboardState.IsKeyDown(Keys.Down)&&!(keyboardState.IsKeyDown(Keys.A))&&(ladybugs[1].Position.Y<(windowHeight - ladybugs[1].Image.Height))) { ladybugs[1].Position = new Vector2( ladybugs[1].Position.X, ladybugs[1].Position.Y + 5); }//end if//The following code is used to drag one or the // other of two ladybugs using the mouse. Press// the left mouse button to drag one of the // ladybugs. Press the right mouse button to drag// the other ladybug. //Get the state of the mouse.MouseState mouseState = Mouse.GetState(); //Press the left mouse button to move one ladybug.if(mouseState.LeftButton == ButtonState.Pressed) { ladybugs[0].Position = new Vector2(mouseState.X,mouseState.Y);}//end if //Press the right mouse button to move the other// ladybug. if(mouseState.RightButton == ButtonState.Pressed) {ladybugs[1].Position =new Vector2(mouseState.X,mouseState.Y); }//end ifbase.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 loop//Draw the output text. string output = "";if(spiderCount == 0){ output = "Congratulations. No spiders made it to"+ " the bottom."; }else{output = "Oops, " + spiderCount + " or more " + "spiders made it to the bottom.";}//end else// Find the center of the string Vector2 FontOrigin =Font1.MeasureString(output) / 2; // Draw the stringspriteBatch.DrawString(Font1, output,FontPos, Color.Yellow,0,//angle FontOrigin,1.0f,//scale SpriteEffects.None,0.0f);//layer depth spriteBatch.End();base.Draw(gameTime); }//end Draw method//-------------------------------------------------// }//end class}//end namespace

-end-

Get Jobilize Job Search Mobile App in your pocket Now!

Get it on Google Play Download on the App Store Now




Source:  OpenStax, Xna game studio. OpenStax CNX. Feb 28, 2014 Download for free at https://legacy.cnx.org/content/col11634/1.6
Google Play and the Google Play logo are trademarks of Google Inc.

Notification Switch

Would you like to follow the 'Xna game studio' conversation and receive update notifications?

Ask