Search code examples
c#xna

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);
        }

    }

}

Solution

  • 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;
    }