0

I need to make my sprite shoot each time i presses space. I'm pretty sure I've created the texture and draw it (inside my player class), but every time it was reading bulletTexture.width it always returns null. I hope some1 can help me.

Here's a complete rundown of my code:

Player.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Input;

namespace SpaceShooter_Beta.Animation.PlayerCollection
{
    public class Player : SpriteManager
    {
        #region Field Region

        public bool isAnimating = false, isDirectional = false;
        private float loadTime = 0.05f, shootDelay, bulletDelay, timeElapsed;
        public float speed;
        public List<CommonBullet> commonBulletList;
        public int bulletCap = 20;

        KeyboardState kbs;

        #endregion

        #region Property Region

        public int fps
        {
            set { loadTime = (1f / value); }
        }

        #endregion

        #region Constructor Region

        public Player(Texture2D texture, int frame, int animations) :
            base(texture, frame, animations)
        {
            speed = 2f;
            shootDelay = 5f;

            this.AddAnimation("down", 1);
            this.AddAnimation("up", 2);
            this.AddAnimation("right", 3);
            this.AddAnimation("left", 4);
            this.AddAnimation("upright", 5);
            this.AddAnimation("upleft", 6);
            this.AddAnimation("downright", 7);
            this.AddAnimation("downleft", 8);

            commonBulletList = new List<CommonBullet>();
            bulletDelay = 5f;
        }

        public void Update(GameTime gt)
        {
            timeElapsed += (float)gt.ElapsedGameTime.TotalSeconds;

            if (!this.isAnimating)
            {
                if (timeElapsed > loadTime)
                {
                    timeElapsed -= loadTime;
                    if (frameIndex == rects.Length - 1) this.isAnimating = false;
                    else frameIndex++;
                }
            }

            kbs = Keyboard.GetState();
            GetMovement();
            if (kbs.IsKeyDown(Keys.Space)) Attack();
            UpdateBullet();
        }

        #endregion

        #region Method Region

        private void GetMovement()
        {
            if (kbs.IsKeyDown(Keys.W))
            {
                this.pos.Y -= speed;
                this.animation = "up";

                if (kbs.IsKeyDown(Keys.D))
                {
                    if (!isDirectional)
                    {
                        frameIndex = 0;
                        isDirectional = true;
                    }
                    this.pos.X += speed;
                    this.animation = "upright";
                }
                else if (kbs.IsKeyDown(Keys.A))
                {
                    if (!isDirectional)
                    {
                        frameIndex = 0;
                        isDirectional = true;
                    }
                    this.pos.X -= speed;
                    this.animation = "upleft";
                }

                if (!this.isAnimating) this.isAnimating = true;
                else this.isAnimating = false;
            }
            else if (kbs.IsKeyDown(Keys.S))
            {
                this.pos.Y += speed;
                this.animation = "down";

                if (kbs.IsKeyDown(Keys.D))
                {
                    if (!isDirectional)
                    {
                        frameIndex = 0;
                        isDirectional = true;
                    }
                    this.pos.X += speed;
                    this.animation = "downright";
                }
                else if (kbs.IsKeyDown(Keys.A))
                {
                    if (!isDirectional)
                    {
                        frameIndex = 0;
                        isDirectional = true;
                    }
                    this.pos.X -= speed;
                    this.animation = "downleft";
                }

                if (!this.isAnimating) this.isAnimating = true;
                else this.isAnimating = false;
            }
            else if (kbs.IsKeyDown(Keys.A))
            {
                this.pos.X -= speed;
                this.animation = "left";
                if (!this.isAnimating) this.isAnimating = true;
                else this.isAnimating = false;
            }
            else if (kbs.IsKeyDown(Keys.D))
            {
                this.pos.X += speed;
                this.animation = "right";
                if (!this.isAnimating) this.isAnimating = true;
                else this.isAnimating = false;
            }
            else
            {
                this.isAnimating = false;
                this.isDirectional = false;
                frameIndex = 0;
            }

            if (this.pos.X <= 0) this.pos.X = 0;
            if (this.pos.X >= (800 - this.width)) this.pos.X = 800 - this.width;
            if (this.pos.Y <= 0) this.pos.Y = 0;
            if (this.pos.Y >= (600 - this.height)) this.pos.Y = 600 - this.height;
        }
        private void Attack()
        {
            if (bulletDelay > 0) bulletDelay--;
            if (bulletDelay <= 0)
            {
                CommonBullet cb = new CommonBullet();
                if(cb.bulletTexture.Width > 0)
                {
                    Console.WriteLine("this");
                    return;
                }
                cb.pos = new Vector2(this.pos.X - cb.bulletTexture.Width / 2, this.pos.Y + 15);
                cb.hasFired = true;
                if (commonBulletList.Count < bulletCap) commonBulletList.Add(cb);
                bulletDelay = 0;
            }
            if (bulletDelay == 0) bulletDelay = shootDelay;
        }
        private void UpdateBullet()
        {
            foreach (CommonBullet cb in commonBulletList)
            {
                cb.box = new Rectangle((int)cb.pos.X, (int)cb.pos.Y, cb.bulletTexture.Width, cb.bulletTexture.Height);
                cb.pos.Y -= cb.bulletSpeed;
                if (cb.pos.Y < 0) cb.hasFired = false;
            }

            for (int i = 0; i < commonBulletList.Count; i++)
            {
                if (!commonBulletList[i].hasFired)
                {
                    commonBulletList.RemoveAt(i);
                    i--;
                }
            }
        }

        public void Draw(SpriteBatch sb)
        {
            sb.Draw(texture, pos, animations[animation][frameIndex], Color.White, rot, ori, s, se, 0f);
            foreach (CommonBullet cb in commonBulletList)
            {
                cb.Draw(sb);
            }
        }
        #endregion
    }
}

Inherits from SpriteManager(for its animation), here is SpriteManager class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;

namespace SpaceShooter_Beta
{
    public class SpriteManager
    {
        #region Field Region

        protected Texture2D texture;
        protected Rectangle[] rects;
        protected int frameIndex = 0, frames;
        protected Dictionary<string, Rectangle[]> animations = new Dictionary<string, Rectangle[]>();

        public Vector2 pos, ori;
        public float rot = 0f, s= 1f;
        public SpriteEffects se;
        public string animation;
        public int width, height;

        #endregion

        #region Property Region
        #endregion

        #region Constructor Region

        public SpriteManager(Texture2D texture, int frame, int animation)
        {
            this.texture = texture;
            this.frames = frame;

            rects = new Rectangle[frame];
            for (int i = 0; i < frame; i++)
            {
                rects[i] = new Rectangle(i * width, 0, width, texture.Height);
            }

            width = texture.Width / frame;
            height = texture.Height / animation;
        }

        #endregion

        #region Method Region

        public void AddAnimation(string name, int row)
        {
            Rectangle[] rects = new Rectangle[frames];
            for (int i = 0; i < frames; i++)
            {
                rects[i] = new Rectangle(i * width, (row - 1) * height, width, height);
            }
            animations.Add(name, rects);
        }

        #endregion
    }
}

I "draw" my bullet texture every time its called in player.cs in Attack() function. Here is my bullet class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;

namespace SpaceShooter_Beta.Animation.PlayerCollection
{
    public class CommonBullet
    {
        #region Field Region

        public float bulletSpeed = 5f;
        public double bulletDamage;
        public Texture2D bulletTexture;
        public Vector2 pos, ori;
        public bool hasFired;
        public Rectangle box;

        #endregion

        #region Property Region
        #endregion

        #region Constructor Region

        public CommonBullet()
        {
            hasFired = false;
        }

        #endregion

        #region Method Region

        public void Draw(SpriteBatch sb)
        {
            sb.Draw(bulletTexture, pos, Color.White);
        }

        public void LoadContent(ContentManager Content)
        {
            bulletTexture = Content.Load<Texture2D>(@"playerbullet");
        }

        #endregion
    }
}

The error throws everytime at player.cs, at cb.pos = new Vector2(this.pos.X - cb.bulletTexture.Width / 2, this.pos.Y + 15);. From the debugger, I'm pretty sure cb.bulletTexture is NOT null, but it's width returns null.

I hope someone can help me here, thanks.

1 Answer 1

1

You are initializing a new CommonBullet in every Attack() however, you are not calling the LoadContent() method to load the image.

This could easily be fixed by adding the LoadContent call

CommonBullet cb = new CommonBullet();
cb.LoadContent(your content manager)

However, it is generally not a good idea to load a new image all the time, especially if it is the game image, there is no point.

You should make a static variable in CommonBullet

static Texture2D BulletTexture;

You should also make your LoadContent method static, and instead of the way above (calling it each attack) you should go into your main Game file, and find it's LoadContent method, and add this line:

CommonBullet.LoadContent(this.ContentManager);

Or you could just do CommonBullet.BulletTexture = Content.Load<Texture2D>("Blah");

Sign up to request clarification or add additional context in comments.

2 Comments

How can a static variable be used/accessed in main Game file? Edit More specifically, since I need to know my bullet texture width and height in player class (see player.cs), how can i know that if it's static? Please don't get me wrong, I really appreciate the help. Edit Currently I'm getting it working if I change the bullet texture width and height to 8 px (the size of the image) but I feel like this is not really a solution (as the bullet image may change in the future)
Well the texture being static means it can be accessed from any class with CommonBullet.BulletTexture, to get the dimensions, same thing, CommonBullet.BulletTexture.Width

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.