Bobby Gannard Bobby Gannard - 2 months ago 7
C# Question

How to debug where an unexpected null is coming from in my class?

In my

Boss
class, it says that my List "bulletlist" is null and give me a run time error but I see no errors can someone tell me what I am doing wrong? The games runs fine if I don't update my boss class. I put in my main class, player class, and bullet class, in as well.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace Space_Shooter
{
public class Boss
{
public Texture2D texture, bulletTexture , healthBarTexture;
public Vector2 position;
public float randomPositionX, randomPositionY , bulletDamage, shipDamage , health , MaxBullets;
public int speed, bulletSpeed , bulletDelayTime, bulletDelayTimeReset;
public bool isVisible;
public Rectangle boundingBox , bossHealthBar;
public List<Bullet> bulletList;
Random random = new Random();
Player p = new Player();


public Boss(Texture2D newTexture, Vector2 newPosition, Texture2D newBulletTexture)
{
texture = newTexture;
position = newPosition;
bulletTexture = newBulletTexture;
bulletList = new List<Bullet>();
bulletSpeed = 25;
bulletDamage = 25;
shipDamage = p.health / 2;
health = 2000;
bulletDelayTime = 30;
bulletDelayTimeReset = 30;
MaxBullets = 30;
isVisible = true;

}
public Boss()
{

}

public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(texture, position, Color.White);
spriteBatch.Draw(healthBarTexture, bossHealthBar, Color.White);

foreach (Bullet b in bulletList)
{
b.Draw(spriteBatch);
}

}

public void loadContent(ContentManager content)
{
texture = content.Load<Texture2D>("Ship4");
bulletTexture = content.Load<Texture2D>("EnemyBullet");
healthBarTexture = content.Load <Texture2D> ("healthbar");

}
public void update(GameTime gameTime)
{
updateBullets();
Shoot();
checkBossCollison();

// Making bosses health bar
bossHealthBar = new Rectangle((int)position.X, (int)position.Y + 30, (int)health, 25);

// Creating collision box for boss
boundingBox = new Rectangle((int)position.X, (int)position.Y, (int)texture.Width, (int)texture.Height);

randomPositionX = random.Next(50, 750);
randomPositionY = random.Next(50, 400);

// setting boss movement
if (position.Y > randomPositionY)
position.Y -= speed;

if (position.Y < randomPositionY)
position.Y += speed;

if (position.X > randomPositionX)
position.X -= speed;

if (position.X < randomPositionX)
position.X += speed;
}
public void updateBullets()
{
// for each bullet in the bulletList: update the movement and if the bullet hits the bottom of the screen, remove it from the list
foreach (Bullet b in bulletList)
{
//make a Bounding box for every bullet in the bulletList
b.boundingBox = new Rectangle((int)b.position.X, (int)b.position.Y, b.texture.Width, b.texture.Height);

// set movement for the bullets

// if a bullet hits the bottom of the screen, then make visable false
if (b.position.Y >= 850)
b.isVisible = false;

// go through the bulletList and see if any of the bullets are not visible, if they are not then remove that bullet from the bulletList
for (int i = 0; i < bulletList.Count; i++)
{
if (!bulletList[i].isVisible)
{
bulletList.RemoveAt(i);
i--;
}
}
}
}

public void checkBossCollison()
{
// if boss ship comes in bcontact with player ship player is damaged
if (boundingBox.Intersects(p.boundingBox))
p.health -= shipDamage;

// if player bullets hit boss then boss is damaged and player bullets go invisible
for(int i = 0; i < p.bulletList.Count; i++)
{
if (boundingBox.Intersects(p.bulletList[i].boundingBox))
{
health -= p.bulletDamage;
p.bulletList[i].isVisible = false;

if (health == 0)
isVisible = false;
}
}

// if boss shoots player player is damaged and boss bullets go invisible
for(int i = 0; i < bulletList.Count; i++)
{
if (p.boundingBox.Intersects(bulletList[i].boundingBox))
{
p.health -= bulletDamage;
bulletList[i].isVisible = false;

}
}
}

public void Shoot()
{
// shoot only if our bullet delay resets
if (bulletDelayTime >= 0)
bulletDelayTime--;

// If bulletDelay is at 0, create a new bullet at enemy position, make it visible on the screen, then add that bullet to bulletList
if (bulletDelayTime <= 0)
{
// create new bullet and center it front and center of enemy ship
Bullet newBullet = new Bullet(bulletTexture);
newBullet.position = new Vector2(position.X + texture.Width / 2 - newBullet.texture.Width / 2, position.Y + 30);

newBullet.isVisible = true;

if (bulletList.Count() < MaxBullets)
bulletList.Add(newBullet);
}

// Reset bullet delay
if (bulletDelayTime == 0)
bulletDelayTime = bulletDelayTimeReset;
}
}
}







using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace Space_Shooter
{

// Main
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;

// variabls
SpriteBatch spriteBatch;
Random random = new Random();
Random randomNumberOfAsteroids = new Random();
int maxNumberOfAsteroids;
int numbersOfInvisibleEnemies;



// Lists
List<Asteroid> asteroidList = new List<Asteroid>();
List<Enemy> enemyList = new List<Enemy>();

// making player and starfield objects
Player P = new Player();
StarField starfield = new StarField();
Enemy E = new Enemy();
Boss boss = new Boss();

// Construtor
public Game1()
{
graphics = new GraphicsDeviceManager(this);

// setting full scren to off and setting screen measurments
graphics.IsFullScreen = false;
graphics.PreferredBackBufferWidth = 800;
graphics.PreferredBackBufferHeight = 850;
maxNumberOfAsteroids = 5; // Set the max number of asteroids that will be on the screen at one time ( randomly 0 to Max number)
numbersOfInvisibleEnemies = 0;

// Setting Title of screen
this.Window.Title = "Star Voyage";

Content.RootDirectory = "Content";
}

// Initialize
protected override void Initialize()
{
base.Initialize();
}

// Load content
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);

// Call Load content function from Player.cs
P.LoadContent(Content);
starfield.LoadContent(Content);
boss.loadContent(Content);


}

// unload content
protected override void UnloadContent()
{

}

// update game screen
protected override void Update(GameTime gameTime)
{

// updating enemies and checking collision of thier ships to player ship
foreach (Enemy e in enemyList)
{
if (e.boundingBox.Intersects(P.boundingBox))
{
P.health -= e.enemyShipDamage;
e.isVisible = false;
}

// check enemy bullet collision with player ship
for (int i = 0; i < e.bulletList.Count; i++)
{
if (P.boundingBox.Intersects(e.bulletList[i].boundingBox))
{
P.health -= e.enemyBulletDamage;
e.bulletList[i].isVisible = false;
}
}

// check player bullet collision with enemy ships
for (int i = 0; i < P.bulletList.Count; i++)
{
if (e.boundingBox.Intersects(P.bulletList[i].boundingBox))
{
// when bullet hits enemy ship they disapear
P.bulletList[i].isVisible = false;
e.health -= P.bulletDamage;

if (e.health == 0)
e.isVisible = false;

}
}
e.Update(gameTime);
}
// for each asteroid in the asteroid list call the update function from Asteroid.cs
foreach (Asteroid a in asteroidList)
{
//Check to see if any of the arteroids are colliding with player ship
if (a.boundingBox.Intersects(P.boundingBox))
{
P.health -= a.asteroidDamage; // taking 20 off of player health bar each time the play shit is hit by an asteroid
a.isVisible = false;
}
// going through bullet list to see if any bullets come in contact with asteroids if they do set both the bullet and the asteroid to not visible
for (int i = 0; i < P.bulletList.Count; i++)
{
if (a.boundingBox.Intersects(P.bulletList[i].boundingBox))
{
a.isVisible = false;
P.bulletList.ElementAt(i).isVisible = false;
}
}
a.Update(gameTime);
}

loadAsteroids();
loadEnemyShips();
// Call fucntion Update from Player,cs
P.Update(gameTime);
// Call function update from StarField.cs
starfield.Update(gameTime);
boss.update(gameTime);
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();

base.Update(gameTime);
}

// Draw to game screen
protected override void Draw(GameTime gameTime)
{
spriteBatch.Begin();

starfield.Draw(spriteBatch);

foreach (Asteroid a in asteroidList)
{
a.Draw(spriteBatch);
}

foreach (Enemy e in enemyList)
{
e.Draw(spriteBatch);
}

// Backgound color
GraphicsDevice.Clear(Color.CornflowerBlue);

// Call Draw fuction from Player.cs
P.Draw(spriteBatch);
// boss.Draw(spriteBatch);
spriteBatch.End();
base.Draw(gameTime);
}

// Load Asteroids function
public void loadAsteroids()
{
// creating random variabls for X and Y positions of asteroids
int random_x = random.Next(0, 750), random_y = random.Next(-600, -50);

// if the number of Asteroids on the screen is less than the variable (numberOfAsteroids), create more untill it is not
if (asteroidList.Count() < randomNumberOfAsteroids.Next(0, maxNumberOfAsteroids))
{
asteroidList.Add(new Asteroid(Content.Load<Texture2D>("asteroid"), new Vector2(random_x, random_y)));
}

// if any of the asteroids from the list are destroyed (not visible) then remove them from the list
for (int i = 0; i < asteroidList.Count; i++)
{
if (!asteroidList[i].isVisible)
{
asteroidList.RemoveAt(i);
i--;
}
}
}

public void loadEnemyShips()
{
// creating random variabls for X and Y positions of asteroids
int random_x = random.Next(0, 750), random_y = random.Next(-600, -50);

// if the number of enemies on the screen is less than the variable (numberOfEnemies), create more untill it is not
if (enemyList.Count() < 3 && numbersOfInvisibleEnemies <= 9)
{
enemyList.Add(new Enemy(Content.Load<Texture2D>("enemyship"), new Vector2(random_x, random_y), Content.Load<Texture2D>("EnemyBullet")));
}

// keeping count of the number of destroied enemies
for (int i = 0; i < enemyList.Count; i++)
{
if (!enemyList[i].isVisible)
numbersOfInvisibleEnemies += 1;

// if any of the enemies from the list are destroyed (not visible) or if they go passed the bottom of the screen, then remove them from the list
if (!enemyList[i].isVisible || enemyList[i].position.Y >= 840)
{
enemyList.RemoveAt(i);
--i;
}
}

}

}
}




using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
namespace Space_Shooter
{
// main
public class Player
{
// Variables
public Texture2D texture , bulletTexture , healthTexture;
public Vector2 position , healthBarPosition;
public int speed;
public float health , bulletDamage , bulletDelay , bulletDelayReset;
double bulletCount;

// Lists
public List<Bullet> bulletList;



// Collision variables
public bool isColliding;
public Rectangle boundingBox , healthRectangle;

// Constructor
public Player()
{
bulletList = new List<Bullet>();
bulletDelay = 1; // for faster fire rate reduce number
bulletDelayReset = 5; // bullet delay reset has to be the same number as bullet delay
bulletCount = 1000; // amount of bullets alowed on the screen at a time
texture = null;
health = 200;
bulletDamage = 3;
healthBarPosition = new Vector2(50, 50);
position = new Vector2 (300, 300) ;
speed = 10;
isColliding = false;
}

// Load content
public void LoadContent(ContentManager Content)
{
texture = Content.Load<Texture2D>("player01");
bulletTexture = Content.Load<Texture2D>("playerbullet");
healthTexture = Content.Load<Texture2D>("healthbar");
}

// Draw
public void Draw(SpriteBatch spritebatch)
{
spritebatch.Draw(texture, position, Color.White);
spritebatch.Draw(healthTexture, healthRectangle, Color.White);

// For each Bullet b (bullet) in our bullet list, draw the bullet
foreach (Bullet b in bulletList)
{
b.Draw(spritebatch);
}
}

// Update
public void Update(GameTime gametime)
{
// Checking for keyboard input every frame
KeyboardState keystate = Keyboard.GetState();

// setting collision box for player ship
boundingBox = new Rectangle((int)position.X, (int)position.Y, texture.Width, texture.Height);

//set rectangle for healthbar (where to print on the screen and the height and width (25) is height (health is width
healthRectangle = new Rectangle((int) healthBarPosition.X, (int) healthBarPosition.Y, (int)health, 25);

if (keystate.IsKeyDown(Keys.Space))
{
shoot();
}
updateBullets();

// ship controls
if (keystate.IsKeyDown(Keys.W))
position.Y = position.Y - speed;

if (keystate.IsKeyDown(Keys.S))
position.Y = position.Y + speed;

if (keystate.IsKeyDown(Keys.A))
position.X = position.X - speed;

if (keystate.IsKeyDown(Keys.D))
position.X = position.X + speed;


// Keep ship in screen bounds
if (position.X <= 0)
position.X = 0;

if (position.X >= 800 - texture.Width)
position.X = 800 - texture.Width;

if (position.Y <= 0)
position.Y = 0;

if (position.Y >= 850 - texture.Height)
position.Y = 850 - texture.Height;

}

// Shoot Function, used to set the starting position of the players bullet
public void shoot()
{
// Shoot only if the bullet delay resets
if (bulletDelay >= 0)
bulletDelay--;

// If bulletDelay is at 0, create a new bullet at player position, make it visible on the scrren, then add that bullet to bulletList
if (bulletDelay <= 0)
{
Bullet newBullet1 = new Bullet(bulletTexture);
newBullet1.position = new Vector2(position.X - newBullet1.texture.Width / 2, position.Y + 30);
newBullet1.isVisible = true;

Bullet newBullet2 = new Bullet(bulletTexture);
newBullet2.position = new Vector2(position.X + 64 - newBullet2.texture.Width / 2, position.Y + 30);
newBullet2.isVisible = true;

// control the amount of bullets on the screen by increasing number
if (bulletList.Count() < bulletCount)
bulletList.Add(newBullet1);
bulletList.Add(newBullet2);
}

// Reset bullet dleay
if (bulletDelay == 0)
bulletDelay = bulletDelayReset;
}
public void updateBullets()
{
// for each bullet in the bulletList: update the movement and if the bullet hits the top of the screen, remove it from the list
foreach (Bullet b in bulletList)
{
// set movement for the bullets
b.position.Y = b.position.Y - b.speed;

//make a Bounding box for every bullet in the bullet list
b.boundingBox = new Rectangle((int)b.position.X, (int)b.position.Y, b.texture.Width, b.texture.Height);

// if a bullet hits the top of the screen, then make visable false
if (b.position.Y <= 0)
b.isVisible = false;
}

// go through the bulletList and see if any of the bullets are not visible, if they are not then remove that bullet from the bulletList
for (int i = 0; i < bulletList.Count; i++)
{
if (!bulletList[i].isVisible)
{
bulletList.RemoveAt(i);
i--;
}
}
}
}
}




using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;


namespace Space_Shooter
{


public class Bullet
{
public Rectangle boundingBox;
public Texture2D texture;
public Vector2 position , origin;
public float speed;
public bool isVisible;

public Bullet(Texture2D newTexture)
{
speed = 25;
texture = newTexture;
isVisible = false;
}

public void Draw(SpriteBatch spritebatch)
{
spritebatch.Draw(texture, position, Color.White);
}

}

}

Answer

You initialize the list in the constructor:

public Boss(Texture2D newTexture, Vector2 newPosition, Texture2D newBulletTexture)

But, you don't call this constructor. You call Boss boss = new Boss();

Thus the constructor which initializes the list is not called.

You should initialize the list in all constructors:

public Boss()
{
    bulletList = new List<Bullet>();
}

Better is too make the default constructor set all the default values, and if you need to set other values in another constructor, is to call the default constructor from the "second" constructor using : this():

public Boss()
{
    bulletList = new List<Bullet>();
    bulletSpeed = 25;
    bulletDamage = 25;
    shipDamage = p.health / 2;
    health = 2000;
    bulletDelayTime = 30;
    bulletDelayTimeReset = 30;
    MaxBullets = 30;
    isVisible = true;
}

public Boss(Texture2D newTexture, Vector2 newPosition, Texture2D newBulletTexture)
    : this() //Call default constructor
{
    texture = newTexture;
    position = newPosition;
    bulletTexture = newBulletTexture;
}