2013-03-19 73 views
0

嘿,我真的需要一些幫助,我的spriteBatch不斷返回一個NullReference異常,我不知道我做錯了什麼! (我正在製作一款破磚機遊戲),並且每當我的磚塊在Game1.cs中創建時,它都能正常工作,但是當我將它移動到Wall.cs(這是我想要顯示磚塊圖案的地方)時,遊戲只會崩潰並給出NullReference異常。我的繼承人代碼:C#XNA SpriteBatch爲空?

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 BrickBreaker 
{ 
    /// <summary> 
    /// This is the main type for your game 
    /// </summary> 
    public class Game1 : Microsoft.Xna.Framework.Game 
    { 
     GraphicsDeviceManager graphics; 
     SpriteBatch spriteBatch; 
     private Paddle paddle; 
     private Ball ball; 
     private Texture2D background; 
     private static int screenWidth = 750; 
     private static int screenHeight = 600; 
     private int leftBorder = 20; 
     private int rightBorder = 28; 
     private int topBorder = 20; 
     private readonly int normalBrickResist = 2; 
     private readonly int normalBrickPoints = 10; 
     private Wall wall; 

     //DELETE this shit 
     private Brick brick; 

     /// <summary> 
     /// Contructor for the Game1 class. 
     /// </summary> 
     public Game1() 
     { 
      graphics = new GraphicsDeviceManager(this); 
      Content.RootDirectory = "Content"; 
     } 


     /// <summary> 
     /// Read only property for the screen height. 
     /// </summary> 
     public static int ScreenHeight 
     { 
      get { return screenHeight; } 
     } 

     /// <summary> 
     /// Read only property for the screen width. 
     /// </summary> 
     public static int ScreenWidth 
     { 
      get { return screenWidth; } 
     } 

     /// <summary> 
     /// Allows the game to perform any initialization it needs to before starting to run. 
     /// This is where it can query for any required services and load any non-graphic 
     /// related content. Calling base.Initialize() will enumerate through any components 
     /// and initialize them as well. 
     /// </summary> 
     protected override void Initialize() 
     { 
      graphics.PreferredBackBufferHeight = screenHeight; 
      graphics.PreferredBackBufferWidth = screenWidth; 
      graphics.ApplyChanges(); 

      paddle = new Paddle(this); 
      Components.Add(paddle); 

      wall = new Wall(this); 
      Components.Add(wall); 

      ball = new Ball(this, paddle, leftBorder, rightBorder, topBorder, brick); 
      Components.Add(ball); 

      base.Initialize(); 
     } 

     /// <summary> 
     /// LoadContent will be called once per game and is the place to load 
     /// all of your content. 
     /// </summary> 
     protected override void LoadContent() 
     { 
      spriteBatch = new SpriteBatch(GraphicsDevice); 

      background = Content.Load<Texture2D>("background"); 
     } 

     /// <summary> 
     /// UnloadContent will be called once per game and is the place to unload 
     /// all content. 
     /// </summary> 
     protected override void UnloadContent() 
     { 
      // TODO: Unload any non ContentManager content here 
     } 

     /// <summary> 
     /// Allows the game to run logic such as updating the world, 
     /// checking for collisions, gathering input, and playing audio. 
     /// </summary> 
     /// <param name="gameTime">Provides a snapshot of timing values.</param> 
     protected override void Update(GameTime gameTime) 
     { 
      // Allows the game to exit 
      if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) 
       this.Exit(); 

      base.Update(gameTime); 
     } 

     /// <summary> 
     /// This is called when the game should draw itself. 
     /// </summary> 
     /// <param name="gameTime">Provides a snapshot of timing values.</param> 
     protected override void Draw(GameTime gameTime) 
     { 
      GraphicsDevice.Clear(Color.CornflowerBlue); 

      spriteBatch.Begin(); 
      Vector2 position = new Vector2(0, 0); 
      spriteBatch.Draw(background, position, Color.White); 
      spriteBatch.End(); 

      base.Draw(gameTime); 
     } 

     public void RemoveComponent(IGameComponent obj) 
     { 
      this.Components.Remove(obj); 
     } 
    } 
} 

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 BrickBreaker 
{ 

    /// <summary> 
    /// This is a game component that implements IUpdateable. 
    /// </summary> 
    public class Wall : Microsoft.Xna.Framework.DrawableGameComponent 
    { 
     private Brick brick; 
     private Brick[,] brickLayout = new Brick[5, 8]; 
     private Game game; 
     SpriteBatch spriteBatch; 
     private Texture2D brickImg; 

     public Wall(Game game) 
      : base(game) 
     { 
      this.game = game; 
     } 

     /// <summary> 
     /// Allows the game component to update itself. 
     /// </summary> 
     /// <param name="gameTime">Provides a snapshot of timing values.</param> 
     public override void Draw(GameTime gameTime) 
     { 
      foreach (var item in brickLayout) 
      { 
       if (item != null) 
       { 
        item.Draw(gameTime); 
       } 

      } 

      base.Draw(gameTime); 
     } 

     /// <summary> 
     /// Allows the game component to update itself. 
     /// </summary> 
     /// <param name="gameTime">Provides a snapshot of timing values.</param> 
     public override void Update(GameTime gameTime) 
     { 
      foreach (Brick item in brickLayout) 
      { 
       item.Update(gameTime); 
      } 

      base.Update(gameTime); 
     } 

     /// <summary> 
     /// Allows the game component to perform any initialization it needs to before starting 
     /// to run. This is where it can query for any required services and load content. 
     /// </summary> 
     public override void Initialize() 
     { 
      // TODO: Add your initialization code here 
      foreach (var item in brickLayout) 
      { 
       if (item != null) 
       { 
        item.Initialize(); 
       } 
      } 
      base.Initialize(); 
     } 

     protected override void LoadContent() 
     { 

      int x = 0; 
      int y = 0; 
      Vector2 startPosition; 
      for (int i = 0; i < brickLayout.GetLength(0); i++) 
      { 
       for (int j = 0; j < brickLayout.GetLength(1); j++) 
       { 
        startPosition = new Vector2(x, y); 
        brickLayout[i, j] = new Brick(game, 20, 1, startPosition); 
        x += 20; 
       } 
       y += 20; 
      } 

      base.LoadContent(); 
     } 
    } 
} 

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 BrickBreaker 
{ 
    /// <summary> 
    /// This is a game component that implements IUpdateable. 
    /// </summary> 
    public class Brick : Microsoft.Xna.Framework.DrawableGameComponent 
    { 
     enum brickType 
     { 
      Regular1, 
      Regular2, 
      Regular3, 
      Regular4, 
      Regular5, 
      PowerUp, 
      Unbreakable 
     } 

     private Texture2D brick; 
     private SpriteBatch spriteBatch; 
     private Game game; 
     private int brickValue; 
     private Vector2 startPosition, position; 
     private Rectangle collisionBox; 
     private int brickWidth; 
     private bool isBroken = false; 
     private int resistance; 

     public Brick(Game game, int brickValue, int resistance, Vector2 startPosition) 
      : base(game) 
     { 
      this.brickValue = brickValue; 
      this.game = game; 
      this.resistance = resistance; 
      this.startPosition = startPosition; 
     } 

     public Boolean IsBroken 
     { 
      get 
      { 
       return this.isBroken; 
      } 
      set 
      { 
       this.isBroken = value; 
      } 
     } 

     /// <summary> 
     /// Property for the paddle collision box. 
     /// </summary> 
     public Rectangle CollisionBox 
     { 
      get { return collisionBox; } 
     } 


     /// <summary> 
     /// Read only property for the paddle width. 
     /// </summary> 
     public int BrickWidth 
     { 
      get { return brickWidth; } 
     } 

     /// <summary> 
     /// Allows the game component to perform any initialization it needs to before starting 
     /// to run. This is where it can query for any required services and load content. 
     /// </summary> 
     public override void Initialize() 
     { 
      // TODO: Add your initialization code here 

      base.Initialize(); 
     } 

     /// <summary> 
     /// Allows the game component to update itself. 
     /// </summary> 
     /// <param name="gameTime">Provides a snapshot of timing values.</param> 
     public override void Update(GameTime gameTime) 
     { 
      // TODO: Add your update code here 

      base.Update(gameTime); 
     } 

     /// <summary> 
     /// Allows the game component to update itself. 
     /// </summary> 
     /// <param name="gameTime">Provides a snapshot of timing values.</param> 
     public override void Draw(GameTime gameTime) 
     { 

      if (isBroken == false) 
      { 
       spriteBatch.Begin(); 
       spriteBatch.Draw(brick, this.position, Color.White); 
       spriteBatch.End(); 
      } 


      base.Draw(gameTime); 
     } 

     /// <summary> 
     /// Comment 
     /// </summary> 
     protected override void LoadContent() 
     { 
      spriteBatch = new SpriteBatch(GraphicsDevice); 
      brick = game.Content.Load<Texture2D>("brick"); 

      collisionBox = new Rectangle(0, 0, brick.Width, brick.Height); 

      position = startPosition; 
      collisionBox.X = (int)position.X; 
      collisionBox.Y = (int)position.Y; 

      base.LoadContent(); 
     } 

     public void TakeHit() 
     { 
      resistance--; 

      if (resistance == 0) 
       IsBroken = true; 

     } 

    } 
} 

編輯:在wall.cs

for (int i = 0; i < brickLayout.GetLength(0); i++) 
    { 
     for (int j = 0; j < brickLayout.GetLength(1); j++) 
     { 
      startPosition = new Vector2(x, y); 
      brickLayout[i, j] = new Brick(game, 20, 1, startPosition); 
      //Added this line: 
      brickLayout[i, j].Initialize(); 
      x += 45; 
     } 
     x = 150; 
     y += 25; 
    } 

加入這個固定的老問題,但現在的碰撞盒子根本不起作用。

回答

0

它在Draw方法中的SpriteBatch.Begin()行的Brick類中給出NullReferenceException。

1

仔細看看你的Brick類。在你的牆上類你沒有初始化spriteBatch,和你不打電話BeginEnd

LoadContent方法需要這樣的:

spriteBatch = new SpriteBatch(GraphicsDevice); 

而你需要一定要打電話,這是你的Draw方法:

spriteBatch.Begin(); 

spriteBatch.End(); 

編輯:你永遠不會在你的磚類上調用LoadContent這就是爲什麼spriteBatch永遠不會被初始化。嘗試:

protected override void LoadContent() 
    { 

     int x = 0; 
     int y = 0; 
     Vector2 startPosition; 
     for (int i = 0; i < brickLayout.GetLength(0); i++) 
     { 
      for (int j = 0; j < brickLayout.GetLength(1); j++) 
      { 
       startPosition = new Vector2(x, y); 
       brickLayout[i, j] = new Brick(game, 20, 1, startPosition); 
       // This new line... 
       brickLayout[i, j].LoadContent(); 
       x += 20; 
      } 
      y += 20; 
     } 

     base.LoadContent(); 
    } 
+0

什麼?但我在磚課上做了這兩件事。 (不要忘了我的第一部分代碼是game1.cs,我的第二部分代碼是wall.cs,我的第三部分代碼是brick.cs) – Mettalknight 2013-03-19 18:13:04

+0

看看我的編輯,我不認爲我的第一個建議會使任何區別。每個磚類的實例都需要調用LoadContent()。我將1行代碼添加到Wall類的LoadContent方法中,這會導致spriteBatch在每個Brick對象中初始化。 – 2013-03-19 18:14:58

+0

LoadContent受保護。我會試着爲它做一個方法,但我認爲它不會有所作爲。 編輯:現在我得到了InvalidOperationException線上處理「spriteBatch =新的SpriteBatch(GraphicsDevice);」在brick.cs中 – Mettalknight 2013-03-19 18:17:30