2013-03-22 53 views
1

我試圖創建一個簡單的遊戲來測試碰撞檢測,但它不會正常運行。它構建得很好,但運行時出現此錯誤:「NullReferenceException:對象引用未設置爲對象的實例」。xna中的NullReferenceException

SpriteManager.cs:

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 Project_3 
{ 
    public class SpriteManager : Microsoft.Xna.Framework.DrawableGameComponent 
    { 
     private Game1 _Game1; 
     //SpriteBatch for drawing 
     SpriteBatch spriteBatch; 

     //A sprite for the player and a list of automated sprites 
     UserControlledSprite player; 
     List<Sprite> spriteList = new List<Sprite>(); 


     public SpriteManager(Game1 game) 
      : base(game) 
     { 
      // TODO: Construct any child components here 
      _Game1 = game; 
     } 

     public override void Initialize() 
     { 
      // TODO: Add your initialization code here 

      base.Initialize(); 
     } 

     protected override void LoadContent() 
     { 

      spriteBatch = new SpriteBatch(Game.GraphicsDevice); 

      //Load the player sprite 
      player = new UserControlledSprite(
       Game.Content.Load<Texture2D>("Images/bill"), 
       Vector2.Zero, 10, new Vector2(6, 6)); 

      //Load several different automated sprites into the list 
      spriteList.Add(new AutomatedSprite(
       Game.Content.Load<Texture2D>("Images/kit"), 
       new Vector2(150, 150), 10, Vector2.Zero)); 
      spriteList.Add(new AutomatedSprite(
       Game.Content.Load<Texture2D>("Images/kit"), 
       new Vector2(300, 150), 10, Vector2.Zero)); 
      spriteList.Add(new AutomatedSprite(
       Game.Content.Load<Texture2D>("Images/beast"), 
       new Vector2(150, 300), 10, Vector2.Zero)); 
      spriteList.Add(new AutomatedSprite(
       Game.Content.Load<Texture2D>("Images/beast"), 
       new Vector2(600, 400), 10, Vector2.Zero)); 

      base.LoadContent(); 
     } 

     public override void Update(GameTime gameTime) 
     { 
      // Update player 
      player.Update(gameTime, Game.Window.ClientBounds); 

      // Update all sprites 
      foreach (Sprite s in spriteList) 
      { 
       s.Update(gameTime, Game.Window.ClientBounds); 
      } 

      base.Update(gameTime); 
     } 

     public override void Draw(GameTime gameTime) 
     { 
      spriteBatch.Begin(SpriteSortMode.FrontToBack, BlendState.AlphaBlend); 

      // Draw the player 
      player.Draw(gameTime, spriteBatch); 

      // Draw all sprites 
      foreach (Sprite s in spriteList) 
       s.Draw(gameTime, spriteBatch); 

      spriteBatch.End(); 
      base.Draw(gameTime); 
     } 
    } 
} 

拋出異常是從SpriteManagerplayer.Update(gameTime, Game.Window.ClientBounds);線。完整的異常消息是「在Project 3.exe中發生了類型爲」System.NullReferenceException「的未處理異常。附加信息:未將對象引用設置爲對象實例。」

UserControlledSprite.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.Input; 

namespace Project_3 
{ 
class UserControlledSprite : Sprite 
{ 
    // Movement stuff 
    MouseState prevMouseState; 

    // Get direction of sprite based on player input and speed 
    public override Vector2 direction 
    { 
     get 
     { 
      Vector2 inputDirection = Vector2.Zero; 

      // If player pressed arrow keys, move the sprite 
      if (Keyboard.GetState().IsKeyDown(Keys.Left)) 
       inputDirection.X -= 1; 
      if (Keyboard.GetState().IsKeyDown(Keys.Right)) 
       inputDirection.X += 1; 
      if (Keyboard.GetState().IsKeyDown(Keys.Up)) 
       inputDirection.Y -= 1; 
      if (Keyboard.GetState().IsKeyDown(Keys.Down)) 
       inputDirection.Y += 1; 

      // If player pressed the gamepad thumbstick, move the sprite 
      GamePadState gamepadState = GamePad.GetState(PlayerIndex.One); 
      if (gamepadState.ThumbSticks.Left.X != 0) 
       inputDirection.X += gamepadState.ThumbSticks.Left.X; 
      if (gamepadState.ThumbSticks.Left.Y != 0) 
       inputDirection.Y -= gamepadState.ThumbSticks.Left.Y; 

      return inputDirection * speed; 
     } 
    } 

    public UserControlledSprite(Texture2D textureImage, Vector2 position, int collisionOffset, Vector2 speed) 
    { 
    } 

    public override void Update(GameTime gameTime, Rectangle clientBounds) 
    { 
     // Move the sprite based on direction 
     position += direction; 

     // If player moved the mouse, move the sprite 
     MouseState currMouseState = Mouse.GetState(); 
     if (currMouseState.X != prevMouseState.X || 
      currMouseState.Y != prevMouseState.Y) 
     { 
      position = new Vector2(currMouseState.X, currMouseState.Y); 
     } 
     prevMouseState = currMouseState; 

     // If sprite is off the screen, move it back within the game window 
     if (position.X < 0) 
      position.X = 0; 
     if (position.Y < 0) 
      position.Y = 0; 
     if (position.X > clientBounds.Width - 150) 
      position.X = clientBounds.Width - 150; 
     if (position.Y > clientBounds.Height - 150) 
      position.Y = clientBounds.Height - 150; 

     base.Update(gameTime, clientBounds); 
    } 
} 
} 

我不知道爲什麼它不工作。我嘗試了一堆不同的東西,但由於我對xna很陌生,因此我可能錯過了一些簡單的東西。

任何幫助將不勝感激。

編輯:忘了補充Sprite.cs:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using Microsoft.Xna.Framework; 
using Microsoft.Xna.Framework.Graphics; 

namespace Project_3 
{ 
    abstract class Sprite 
    { 
    // Stuff needed to draw the sprite 
    Texture2D textureImage; 

    // Collision data 
    int collisionOffset; 

    // Movement data 
    protected Vector2 speed; 
    protected Vector2 position; 

    // Abstract definition of direction property 
    public abstract Vector2 direction 
    { 
     get; 
    } 

    public Sprite() 
    { 
    } 

    public Sprite(Texture2D textureImage, Vector2 position, int collisionOffset, Vector2 speed) 
    //: this(textureImage, position, collisionOffset, speed) 
    { 
    } 

    public virtual void Update(GameTime gameTime, Rectangle clientBounds) 
    { 

    } 

    public virtual void Draw(GameTime gameTime, SpriteBatch spriteBatch) 
    { 
     // Draw the sprite 
     if (textureImage != null) 
     { 
      spriteBatch.Draw(textureImage, position, Color.White); 
     } 
    } 

    // Gets the collision rect based on position, framesize and collision offset 
    public Rectangle collisionRect 
    { 
     get 
     { 
      return new Rectangle(
       (int)position.X + collisionOffset, 
       (int)position.Y + collisionOffset, 
       150 - (collisionOffset * 2), 
       150 - (collisionOffset * 2)); 
     } 
    } 


    public Game1 _Game1 { get; set; } 
} 
} 
+0

嘗試Game.Content.Load (「/ Images/bill」)注意/之前圖像 – Alekstim 2013-03-22 20:06:49

+4

Visual Studio調試器允許您將鼠標懸停在變量上以查看其值。做到這一點,並找出哪個變量是null,這是取消引用。 – 2013-03-22 20:07:54

+0

'player'爲null。我嘗試了一些不同的東西,但我不確定如何調試這樣的東西。 – 2013-03-22 20:13:13

回答

0

您還沒有實例position。您將position變量傳遞給UserControlledSprite的構造函數,但不將其應用於類範圍內的變量。您需要聲明另一個變量來保存位置變量,該變量僅對構造函數方法可見。

這意味着第一次UserControlledSprite對象調用Update,那麼position += direction;將拋出NullReferenceException。說實話,我不知道你怎麼沒有得到編譯時錯誤,因爲position將不存在於Update的上下文中,除非你沒有向我們展示整個代碼。

+0

我在另一個文件Sprite.cs中實例化位置,我最初錯誤地忽略了它。我編輯了原始文章以添加該文件。 – 2013-03-25 12:38:54

+0

假設代碼沒有丟失,這不是問題(它仍然可能是一個問題) - 'Sprite'不在構造函數中調用'Update',也不'UserControlledSprite'。由於實例化引發異常,這不是造成它的原因 - 但它是一個很好的選擇。也不是'Vector2'結構?如果是這樣,它不會爲空 – Charleh 2013-03-25 12:42:20

+0

Yeah'Vector2'是struct,所以position永遠不會爲空:http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.vector2.aspx – Charleh 2013-03-25 12:43:11

0

對不起,我還不能評論。

當你創建玩家(一個UserControlledSprite),然後你從「UserControlledSprite(... parameters ...)」中調用Sprite構造函數時,它看起來並不像。

public UserControlledSprite(Texture2D textureImage, Vector2 position, int collisionOffset, Vector2 speed) 
{ 
} 

可能需要:

public UserControlledSprite(Texture2D textureImage, Vector2 position, int collisionOffset, Vector2 speed) 
    : base(TextureImage, position, collisionOffset, speed) 
{ 
} 

這也將是有益的設置,你通過數據。所以你通過textureImage,position,collisionOffset和速度。我發現你在Sprite類中有變量,但是我沒有看到你在使用構造函數創建它們時設置它們。除非,請告訴我,如果是這種情況,請傳入與變量名稱相同的參數自動設置它?如果不是這種情況,那麼確保你將精靈類中的position,collisionOffset,speed和textureImage設置爲實際傳遞的參數。我一直認爲你不能在參數中使用與你作爲類的變量相同的名字。

所以,你必須做(如果上述爲真):

public UserControlledSprite(Texture2D _textureImage, Vector2 _position, int _collisionOffset, Vector2 _speed) 
    : base(_textureImage, _position, _collisionOffset, _speed) 
{ 
    //Do this either here or in Sprite. 
    this.textureImage = _textureImage; 
    this.position = _position; 
    this.collisionOffset = _collisionOffset; 
    this.speed = _speed. 
}  

我覺得上面的(正上方這一點)細節是不是你的問題,當前非常重要的。我認爲它與構造函數有更多關係,但我不確定。我在這裏沒有VS,只想嘗試幫助你現在。

無論如何,我希望有所幫助。對不起,如果可以的話,我會發表評論。可悲的是我還不能。