Sorry about all of the code, but I am completely new to Visual C# and XNA.
This program is out of Learning XNA 4.0 by Aaron Reed. My professor modified some of the stuff its supposed to do (the book covers some of this but not all of it). Most of the code is copied from the book.
These are the minimum requirements for the finished product:
- You may use any 2 images in place of 3 Rings and Skull ball (or you can still use the same if you wish) – one is a player (3 Rings) and the other is a participant (also called an enemy)
- The player sprite can move only using the Arrow Keys (Mouse is not activated)
- The participant sprites are automated they move freely (randomly if you wish) and they bounce off the boundaries (in any manner you choose to)
- At the beginning of the game there are 1 player and 5 participant sprites
- The game lasts for exactly 120 seconds, at the end of the game if the player sprite has destroyed all the participant (enemy sprites) on the screen print a message indicating the player wins; otherwise print a message that the player loses
- Every 10 seconds a new incarnation of an enemy sprite emerges at any location
- The player sprite can destroy an enemy sprite only when it collides AND the “A” key is pressed at the same time. If the “A” key is pressed without a collision then 2 incarnations of the enemy occurs
- The enemy sprites must move at a reasonable speed (not very slow I mean) for the game to be meaningful
- You need to have some sounds in your program – a background sound that always plays, a sound that plays when an enemy is destroyed, a different sound when the player fires but the enemy does not get destroyed because there was no collision, a sound when a new enemy emerges (every 10 seconds)
I'm trying to make the enemies (skullballs) evade the player (threerings) but the enemies either don't respond on all sides (the player is on the right or left and the enemy doesn't evade until the player is above or below), and when the enemies do evade, they disappear offscreen shaking (they just suddenly go straight up or down and they're shaking rapidly.
When the new enemy spawns after 10 seconds, starting from the top-left corner, it bounces off the bottom wall and then disappears offscreen when it goes back up.
The skull also doesn't spawn randomly around the screen after 10 seconds.
Also I don't know how to make 2 more enemies spawn when the A button is pressed with no collision.
SpriteManager.cs
namespace Assignment_2
{
public class SpriteManager : Microsoft.Xna.Framework.DrawableGameComponent
{
//SpriteBatch for drawing
SpriteBatch spriteBatch;
//A sprite for the player and a list of automated sprites
UserControlledSprite player;
List<Sprite> spriteList = new List<Sprite>();
int enemySpawnMinMilliseconds = 10000;
int enemySpawnMaxMilliseconds = 10000;
int enemyMinSpeed = 10;
int enemyMaxSpeed = 10;
int nextSpawnTime = 0;
public SpriteManager(Game game)
: base(game)
{
// TODO: Construct any child components here
}
public override void Initialize()
{
// TODO: Add your initialization code here
ResetSpawnTime();
base.Initialize();
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(Game.GraphicsDevice);
//Load the player sprite
player = new UserControlledSprite(
Game.Content.Load<Texture2D>(@"Images/threerings"),
Vector2.Zero, new Point(75, 75), 10, new Point(0, 0),
new Point(6, 8), new Vector2(6, 6));
//Load several different automated sprites into the list to test
//spriteList.Add(new AutomatedSprite(
// Game.Content.Load<Texture2D>(@"Images/skullball"),
// new Vector2(150, 150), new Point(75, 75), 10, new Point(0, 0),
// new Point(6, 8), new Vector2(3, 0), "skullcollision"));
//spriteList.Add(new AutomatedSprite(
// Game.Content.Load<Texture2D>(@"Images/skullball"),
// new Vector2(300, 150), new Point(75, 75), 10, new Point(0, 0),
// new Point(6, 8), new Vector2(-2, 0), "skullcollision"));
////spriteList.Add(new AutomatedSprite(
//// Game.Content.Load<Texture2D>(@"Images/skullball"),
//// new Vector2(150, 300), new Point(75, 75), 10, new Point(0, 0),
//// new Point(6, 8), new Vector2(3, 4), "skullcollision"));
////spriteList.Add(new AutomatedSprite(
//// Game.Content.Load<Texture2D>(@"Images/skullball"),
//// new Vector2(300, 400), new Point(75, 75), 10, new Point(0, 0),
//// new Point(6, 8), new Vector2(0, -3), "skullcollision"));
////spriteList.Add(new AutomatedSprite(
//// Game.Content.Load<Texture2D>(@"Images/skullball"),
//// new Vector2(200, 300), new Point(75, 75), 10, new Point(0, 0),
//// new Point(6, 8), new Vector2(-3, 7), "skullcollision"));
spriteList.Add(new EvadingSprite(
Game.Content.Load<Texture2D>(@"Images/skullball"),
new Vector2(150, 150), new Point(75, 75), 10, new Point(0, 0),
new Point(6, 8), new Vector2(3, 0), "skullcollision", this, .75f, 150));
spriteList.Add(new EvadingSprite(
Game.Content.Load<Texture2D>(@"Images/skullball"),
new Vector2(300, 150), new Point(75, 75), 10, new Point(0, 0),
new Point(6, 8), new Vector2(-2, 0), "skullcollision", this, .75f, 150));
spriteList.Add(new EvadingSprite(
Game.Content.Load<Texture2D>(@"Images/skullball"),
new Vector2(150, 300), new Point(75, 75), 10, new Point(0, 0),
new Point(6, 8), new Vector2(3, 4), "skullcollision", this, .75f, 150));
spriteList.Add(new EvadingSprite(
Game.Content.Load<Texture2D>(@"Images/skullball"),
new Vector2(300, 400), new Point(75, 75), 10, new Point(0, 0),
new Point(6, 8), new Vector2(0, -3), "skullcollision", this, .75f, 150));
spriteList.Add(new EvadingSprite(
Game.Content.Load<Texture2D>(@"Images/skullball"),
new Vector2(200, 300), new Point(75, 75), 10, new Point(0, 0),
new Point(6, 8), new Vector2(-3, 7), "skullcollision", this, .75f, 150));
base.LoadContent();
}
public override void Update(GameTime gameTime)
{
nextSpawnTime -= gameTime.ElapsedGameTime.Milliseconds;
if (nextSpawnTime < 0)
{
SpawnEnemy();
//reset spawn timer
ResetSpawnTime();
}
// Update player
player.Update(gameTime, Game.Window.ClientBounds);
// Update all sprites
for (int i = 0; i < spriteList.Count; ++i)
{
Sprite s = spriteList[i];
s.Update(gameTime, Game.Window.ClientBounds);
// Check for collisions
if (s.collisionRect.Intersects(player.collisionRect) && (Keyboard.GetState().IsKeyDown(Keys.A)))
{
// Play collision sound
if (s.collisionCueName != null)
((Game1)Game).PlayCue(s.collisionCueName);
// Remove collided sprite from the game
spriteList.RemoveAt(i);
--i;
}
}
base.Update(gameTime);
}
public override void Draw(GameTime gameTime)
{
spriteBatch.Begin(SpriteSortMode.FrontToBack, BlendState.AlphaBlend);
// Draw the player
player.Draw(gameTime, spriteBatch);
// Draw all sprites
foreach (Sprite s in spriteList)
s.Draw(gameTime, spriteBatch);
spriteBatch.End();
base.Draw(gameTime);
}
// Return current position of the player sprite
public Vector2 GetPlayerPosition()
{
return player.GetPosition;
}
private void SpawnEnemy()
{
Vector2 speed = Vector2.Zero;
Vector2 position = Vector2.Zero;
// Default frame size
Point frameSize = new Point(75, 75);
// Create the sprite. NOTE: This sprite bounces off the bottom wall then goes back and disappears offscreen
spriteList.Add(
new EvadingSprite(Game.Content.Load<Texture2D>(@"images\skullball"),
position, new Point(75, 75), 10, new Point(0, 0),
new Point(6, 8), new Vector2(3, 4), "skullcollision", this, .75f, 150));
}
private void ResetSpawnTime()
{
nextSpawnTime = ((Game1)Game).rnd.Next(
enemySpawnMinMilliseconds,
enemySpawnMaxMilliseconds);
}
}
}
EvadingSprite
class EvadingSprite : Sprite
{
// Save a reference to the sprite manager to
// use to get the player position
SpriteManager spriteManager;
// Variables to delay evasion until player is close
float evasionSpeedModifier;
int evasionRange;
bool evade = false;
public EvadingSprite(Texture2D textureImage, Vector2 position,
Point frameSize, int collisionOffset, Point currentFrame,
Point sheetSize, Vector2 speed, string collisionCueName,
SpriteManager spriteManager, float evasionSpeedModifier,
int evasionRange)
: base(textureImage, position, frameSize, collisionOffset,
currentFrame, sheetSize, speed, collisionCueName)
{
this.spriteManager = spriteManager;
this.evasionSpeedModifier = evasionSpeedModifier;
this.evasionRange = evasionRange;
}
public EvadingSprite(Texture2D textureImage, Vector2 position,
Point frameSize, int collisionOffset, Point currentFrame,
Point sheetSize, Vector2 speed, int millisecondsPerFrame,
string collisionCueName, SpriteManager spriteManager,
float evasionSpeedModifier, int evasionRange)
: base(textureImage, position, frameSize, collisionOffset,
currentFrame, sheetSize, speed, millisecondsPerFrame,
collisionCueName)
{
this.spriteManager = spriteManager;
this.evasionSpeedModifier = evasionSpeedModifier;
this.evasionRange = evasionRange;
}
public override Vector2 direction
{
get { return speed; }
}
public override void Update(GameTime gameTime, Rectangle clientBounds)
{
// First, move the sprite along its direction vector
position += speed;
// Use the player position to move the sprite closer in
// the X and/or Y directions
Vector2 player = spriteManager.GetPlayerPosition();
if (evade)
{
// Move away from the player horizontally
if (player.X < position.Y)
position.X += Math.Abs(speed.Y);
else if (player.X > position.X)
position.X -= Math.Abs(speed.Y);
// Move away from the player vertically
if (player.Y < position.Y)
position.Y += Math.Abs(speed.X);
else if (player.Y > position.Y)
position.Y -= Math.Abs(speed.X);
}
else
{
if (Vector2.Distance(position, player) < evasionRange)
{
// Player is within evasion range,
// reverse direction and modify speed
speed *= -evasionSpeedModifier;
evade = true;
}
}
//make them bounce off walls
if (position.X > clientBounds.Width - frameSize.X ||
position.X < 0)
speed *= -1;
if (position.Y > clientBounds.Height - frameSize.Y ||
position.Y < 0)
speed *= -1;
base.Update(gameTime, clientBounds);
}
}