2013-07-11 26 views
0

我需要让我的精灵,每次我按下空间拍摄。我敢肯定,我创建了质感和绘制它(我的播放器类中),但每次有人读bulletTexture.width时候它总是返回null。我希望有些人能帮助我。XNA - 空引用异常时产生的纹理

这里是我的代码一个完整的破败:

Player.cs从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; 
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类类:

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

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

这很容易通过添加LoadContent呼叫固定

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

但是,它一般不会加载新的图像所有的时间是个好主意,尤其是如果它是游戏中的形象,也没有点。

你应该在CommonBullet

静态的Texture2D BulletTexture一个static变量;

你也应该让你LoadContent方法static,并且代替上述的方式(调用它每次攻击),你应该进入你的主Game文件,并找到它的LoadContent方法,并添加此行:

CommonBullet.LoadContent(this.ContentManager); 

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

+0

如何在主游戏文件中使用/访问静态变量? [编辑]更具体地说,因为我需要知道的播放器类(见player.cs)我的子弹纹理的宽度和高度,我怎么能知道,如果它是静态的?请不要误会我的意思,我真的很感谢你的帮助。 [编辑]目前,我得到它,如果我改变了子弹的纹理的宽度和高度,以8像素(图像的大小)工作,但我觉得这是不是一个真正的解决方案(如子弹的图像,将来可能会改变) – user2002495

+0

好质地是静态意味着它可以从'CommonBullet.BulletTexture'任何类访问,得到的尺寸,同样的事情,'CommonBullet.BulletTexture.Width' – Cyral

+0

非常感谢,我可以得到它现在 – user2002495