XNA - 创建纹理时的空引用异常

时间:2013-07-11 12:07:20

标签: xna nullreferenceexception texture2d

每次按空间我都需要拍摄精灵。我很确定我已经创建了纹理并绘制它(在我的播放器类中),但每次读取bulletTexture.width时它总是返回null。我希望some1可以帮助我。

以下是我的代码的完整概述:

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

继承自SpriteManager(对于它的动画),这里是SpriteManager类:

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

每次在Attack()函数中调用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;

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

错误每次都在player.cs,cb.pos = new Vector2(this.pos.X - cb.bulletTexture.Width / 2, this.pos.Y + 15);处抛出。从调试器,我很确定cb.bulletTexture是非null,但它的宽度返回null。

我希望有人可以帮助我,谢谢。

1 个答案:

答案 0 :(得分:1)

您正在每CommonBullet初始化一个新Attack()但是,您没有调用LoadContent()方法来加载图片。

可以通过添加LoadContent调用

轻松解决此问题
CommonBullet cb = new CommonBullet();
cb.LoadContent(your content manager)

然而,一直加载新图像通常不是一个好主意,特别是如果它是游戏图像,没有意义。

您应该在static

中制作CommonBullet变量

static Texture2D BulletTexture;

您还应该使用LoadContent方法static,而不是上面的方法(称之为每次攻击),您应该进入主Game文件,并找到它的LoadContent方法,并添加以下行:

CommonBullet.LoadContent(this.ContentManager);

或者您可以CommonBullet.BulletTexture = Content.Load<Texture2D>("Blah");