Reputation: 33
I am trying to create collision between my bullets and the enemy. I have created bounding boxes for each and placed them into their own class. However, I am getting a Null reference error in my HandleCollision
function, specifically at the if statement with the bounding boxes. I will also post the rest of my code.
I discussed this with two lecturers and some peers and they asy it is because bullet and enemy are equal to null. This is because it takes a couple of seconds for the enemy to spawn and the bullet only spawns once it is fired. To counter this I added an if statement to check if the bullet or enemy is null yet it still throws up the same error.
HandleCollision Function
private void HandleCollision()//collision
{
Sprite toRemove = null;
if (bullet != null || enemyTexture != null)
{
foreach (EnemySprite e in enemyList) //checks each enemy sprite
{
if (bullet.BoundingBox.Intersects(enemy.BoundingBox))
{
enemyList.Remove(enemy); //removes enemy
//toRemove = enemy;
break;
}
}
}
}
Game1.cs
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Rectangle spriteRectangle;
Rectangle bulletBounds;
Rectangle enemyBounds;
Sprite player;
Bullets bullet;
EnemySprite enemy;
Texture2D enemyTexture;
List<EnemySprite> enemyList = new List<EnemySprite>();
List<Bullets> bulletsList = new List<Bullets>();
//Pause
bool paused = false;
Texture2D pauseTexture;
Rectangle pauseRectangle;
KeyboardState pastKey;
Vector2 enemyPos = new Vector2(100, 400);
Vector2 Position;
Vector2 Distance;
Vector2 spriteOrigin;
Vector2 spriteVelocity;
const float tangentialVelocity = 5f;
float friction = 0.1f;
float rotation;
float timer = 0f;
float dropInterval = 2f;
float speed = 4f;
float angle;
Random random;
enum GameState
{
MainMenu,
Options,
Help,
Playing,
Exit,
}
GameState CurrentGameState = GameState.MainMenu;
// Screen adjustments
int screenWidth = 800, screenHeight = 600;
cButton btnPlay;
cButtonExit btnExit;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
// TODO: Add your initialization logic here
random = new Random();
Position = new Vector2(150, 150);
this.IsMouseVisible = true;
base.Initialize();
}
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
player = new Sprite();
player.Texture = Content.Load<Texture2D>("graphics/player");
// Screen stuff
graphics.PreferredBackBufferWidth = screenWidth;
graphics.PreferredBackBufferHeight = screenHeight;
//graphics.IsFullScreen = true;
graphics.ApplyChanges();
IsMouseVisible = true;
btnPlay = new cButton(Content.Load<Texture2D>("Graphics/play"), graphics.GraphicsDevice);
btnPlay.setPosition(new Vector2(350, 190));
btnExit = new cButtonExit(Content.Load <Texture2D>("Graphics/exit"), graphics.GraphicsDevice);
btnExit.setPosition(new Vector2(350, 220));
enemyTexture = Content.Load<Texture2D>("graphics/enemy");
player.Texture = Content.Load<Texture2D>("Graphics/player");
int screenCenterX = GraphicsDevice.Viewport.Width / 2;
player.Position = new Vector2(screenCenterX - (player.Texture.Width / 2), screenHeight - player.Texture.Height - 20);
pauseTexture = Content.Load<Texture2D>("graphics/paused");
pauseRectangle = new Rectangle(0, 0, pauseTexture.Width, pauseTexture.Height);
Bullets.BulletTexture = Content.Load<Texture2D>("graphics/bullet");
}
protected override void Update(GameTime gameTime)
{
MouseState mouse = Mouse.GetState();
IsMouseVisible = true;
switch (CurrentGameState)
{
case GameState.MainMenu:
if (btnPlay.isClicked == true) CurrentGameState = GameState.Playing;
btnPlay.Update(mouse);
if (btnExit.isClicked == true) CurrentGameState = GameState.Help;
btnExit.Update(mouse);
if (btnExit.isClicked == true) CurrentGameState = GameState.Options;
btnExit.Update(mouse);
if (btnExit.isClicked == true) CurrentGameState = GameState.Exit;
btnExit.Update(mouse);
break;
case GameState.Playing:
timer += (float)gameTime.ElapsedGameTime.TotalSeconds;
if (timer >= dropInterval)
{
int yPos = random.Next(GraphicsDevice.Viewport.Height - 50);
enemyList.Add(new EnemySprite(enemyTexture, new Vector2(GraphicsDevice.Viewport.Width + 100, yPos)));
timer = 0f;
}
HandleCollision();
HandleMovingEnemy();
MouseState curMouse = Mouse.GetState();
Vector2 mouseLoc = new Vector2(curMouse.X, curMouse.Y);
Vector2 direction = mouseLoc - Position;
spriteRectangle = new Rectangle((int)Position.X, (int)Position.Y,
player.Texture.Width, player.Texture.Height);
Position = spriteVelocity + Position;
spriteOrigin = new Vector2(spriteRectangle.Width / 2, spriteRectangle.Height / 2);
Distance.X = mouse.X - Position.X;
Distance.Y = mouse.Y - Position.Y;
rotation = (float)Math.Atan2(Distance.Y, Distance.X); //calculates the rotation(trigonometry)
//angle = (float)(Math.Atan2(direction.Y, direction.X));
KeyboardState keyState = Keyboard.GetState();
if (keyState.IsKeyDown(Keys.A))
Position.X -= 2;
if (keyState.IsKeyDown(Keys.D))
Position.X += 2;
if (keyState.IsKeyDown(Keys.W))
Position.Y -= 2;
if (keyState.IsKeyDown(Keys.S))
Position.Y += 2;
//right and left edge detection
if (Position.X < 0)
Position = new Vector2(0, Position.Y);
int rightEdge = GraphicsDevice.Viewport.Width - player.Texture.Width;
if (Position.X > rightEdge)
Position = new Vector2(rightEdge, Position.Y);
//bottom and top edge detection
if (Position.Y < 0)
Position = new Vector2(Position.X, 0);
int bottomEdge = GraphicsDevice.Viewport.Height - player.Texture.Height;
if (Position.Y > bottomEdge)
Position = new Vector2(Position.X, bottomEdge);
if (!paused)
{
if (Keyboard.GetState().IsKeyDown(Keys.Escape))
{
paused = true;
btnPlay.isClicked = false; //so that everytime its paused I can pause it again
}
enemy.Update();
}
else if(paused)
{
if (btnPlay.isClicked)
{
paused = false;
speed = 4;
}
if (btnExit.isClicked)
Exit();
btnPlay.Update(mouse);
btnExit.Update(mouse);
}
if (Keyboard.GetState().IsKeyDown(Keys.C))
{
spriteVelocity.X = (float)Math.Cos(rotation) * tangentialVelocity;
spriteVelocity.Y = (float)Math.Sin(rotation) * tangentialVelocity;
}
else if (spriteVelocity != Vector2.Zero)
{
float i = spriteVelocity.X;
float j = spriteVelocity.Y;
spriteVelocity.X = i -= friction * i;
spriteVelocity.Y = j -= friction * j;
}
if (Keyboard.GetState().IsKeyDown(Keys.Space) && pastKey.IsKeyUp(Keys.Space))
Fire();
pastKey = Keyboard.GetState();
UpdateBullets();
break;
case GameState.Exit:
this.Exit();
break;
}
base.Update(gameTime);
}
public void UpdateBullets()
{
foreach (Bullets bullet in bulletsList)
{
bullet.position += bullet.velocity;
if(Vector2.Distance(bullet.position, Position) > 500) //finds position
bullet.isVisible = false;
}
for (int i = 0; i < bulletsList.Count; i++)
{
if (!bulletsList[i].isVisible)
{
bulletsList.RemoveAt(i);
i--;
}
}
}
//function to handle movement of enemies
private void HandleMovingEnemy()
{
List<EnemySprite> toRemove = new List<EnemySprite>();
foreach (EnemySprite e in enemyList)
{
if (e.Position.X < (-20))
{
toRemove.Add(e);
}
else
e.Position -= new Vector2(speed, 0);
}
if (toRemove.Count > 0)
{
foreach (EnemySprite e in toRemove)
{
enemyList.Remove(e);
}
}
}
private void HandleCollision()//collision
{
Sprite toRemove = null;
if (bullet != null || enemyTexture != null)
{
foreach (EnemySprite e in enemyList) //checks each enemy sprite
{
if (bullet.BoundingBox.Intersects(enemy.BoundingBox)) //checks if a sprite has intersected an enemy
{
enemyList.Remove(enemy); //removes enemy
//toRemove = enemy;
break;
}
}
}
}
public void Fire()
{
Bullets newBullet = new Bullets(Content.Load<Texture2D>("graphics/bullet"));
Bullets.BulletTexture = Content.Load<Texture2D>("graphics/bullet");
//newBullet.LoadContent(LoadContent);
newBullet.velocity = new Vector2((float)Math.Cos(rotation), (float)Math.Sin(rotation)) * 5f + spriteVelocity;
newBullet.position = Position + newBullet.velocity * 5;
newBullet.isVisible = true;
if (bulletsList.Count() < 20)
bulletsList.Add(newBullet);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
switch (CurrentGameState)
{
case GameState.MainMenu:
spriteBatch.Draw(Content.Load<Texture2D>("Graphics/SeaSideDefenderMainMenu"), new Rectangle(0,0,screenWidth,screenHeight),Color.White);
btnPlay.Draw(spriteBatch);
btnExit.Draw(spriteBatch);
break;
case GameState.Playing:
spriteBatch.Draw(Content.Load<Texture2D>("Graphics/leveltest"), new Rectangle(0, 0, screenWidth, screenHeight), Color.White);
enemy = new EnemySprite();
enemy.Texture = Content.Load<Texture2D>("graphics/enemy");
enemy.Draw(spriteBatch);
spriteBatch.Draw(player.Texture, Position, null, Color.White, rotation, spriteOrigin, 1f, SpriteEffects.None, 0);
//player.Draw(spriteBatch);
foreach (EnemySprite e in enemyList)
{
e.Draw(spriteBatch);
}
foreach (Bullets bullet in bulletsList)
bullet.draw(spriteBatch);
/*for (int i; i < enemyList.Count; i++)
{
enemyList[i].Draw(spriteBatch);
}*/
if (paused)
{
speed = 0;
spriteBatch.Draw(Content.Load<Texture2D>("graphics/paused"), new Rectangle(0, 0, screenWidth, screenHeight), Color.White);
btnPlay.Draw(spriteBatch);
btnExit.Draw(spriteBatch);
}
break;
}
spriteBatch.End();
base.Draw(gameTime);
}
}
Bullets.cs
public class Bullets
{
public Texture2D texture;
public static Texture2D BulletTexture;
public Vector2 position;
public Vector2 velocity;
public Vector2 origin;
public bool isVisible;
public Rectangle BoundingBox
{
get { return new Rectangle((int)position.X, (int)position.Y, texture.Width, texture.Height); }
}
public Bullets(Texture2D newTexture)
{
texture = newTexture;
isVisible = false;
}
public void draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(texture,position,null,Color.White,0f,origin,1f, SpriteEffects.None, 0);
}
public void LoadContent(ContentManager Content)
{
BulletTexture = Content.Load<Texture2D>(@"graphics/bullet");
}
}
enemy.cs
public class EnemySprite
{
public Texture2D Texture { get; set; }
public Vector2 Position {get; set; }
public Vector2 origin;
public Vector2 velocity;
public Rectangle rectangle;
float rotation = 0f;
bool right;
float distance;
float oldDistance;
public Rectangle BoundingBox
{
get { return new Rectangle((int)Position.X, (int)Position.Y, Texture.Width, Texture.Height); } //uses enemy position and wiwdth to create bounding box
}
public EnemySprite() { }
public EnemySprite(Texture2D texture, Vector2 position)
{
Texture = texture;
Position = position;
oldDistance = distance;
}
float mouseDistance;
public void Update()
{
Position += velocity;
origin = new Vector2(Texture.Width / 2, Texture.Height / 2);
if (distance <= 0)
{
right = true;
velocity.X = 1f;
}
else if(distance <= oldDistance)
{
right = false;
velocity.X = -1f;
}
if (right) distance += 1; else distance -= 1;
MouseState mouse = Mouse.GetState();
mouseDistance = mouse.X - Position.X;
if (mouseDistance >= -200 && mouseDistance <= 200)
{
if (mouseDistance < -1)
velocity.X = -1f;
else if (mouseDistance > 1)
velocity.X = 1f;
else if (mouseDistance == 0)
velocity.X = 0f;
}
}
public void Draw(SpriteBatch spriteBatch)
{
if (Texture != null)
spriteBatch.Draw(Texture, Position, Color.White);
if (velocity.X > 0)
{
spriteBatch.Draw(Texture, Position, null, Color.White, rotation, origin, 1f, SpriteEffects.FlipHorizontally, 0f);
}
else
{
spriteBatch.Draw(Texture, Position, null, Color.White, rotation, origin, 1f, SpriteEffects.None, 0f);
}
}
}
Upvotes: 1
Views: 249
Reputation: 421
You've not initialized the global variable Bullet
anywhere in your game1.cs, therefore you would never get bullet != null
as true. Whereas, you'll always get enemyTexture != null
as true since you've already initialized enemyTexture
in the LoadContent().
Which means you'll always enter the if
block while having the Bullet
variable not initialized.
Hope this will lead you to the solution.
PS: Do mark the answer as 'Accepted' if this was the most helpful one.
Upvotes: 1