0

嘿伙计们,我真的需要一些帮助,我的 spriteBatch 不断返回 NullReference 异常,我不知道我做错了什么!?(我正在制作一个破砖游戏),每当在 Game1.cs 中创建我的砖块时,它都可以正常工作,但是当我将它移动到 Wall.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 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;
    }

但是现在碰撞箱根本不起作用。

4

2 回答 2

1

仔细看看你的积木课。在您的墙类中,您没有初始化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();
    }
于 2013-03-19T18:06:40.413 回答
0

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

于 2013-03-19T18:08:19.460 回答