2013-07-11 64 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