NullReferenceException未处理 - 不明白为什么

时间:2013-07-19 15:22:08

标签: c# xna xna-4.0 nullreferenceexception

我正在尝试用XNA编写一个非常基本的自上而下的2D游戏,我已经到了我试图在游戏中添加草纹理然后将这些纹理绘制到游戏底部的部分。屏幕。

但是,我在Level.cs类的第32行上遇到“NullReferenceException is Unhandled”错误。因为我刚刚接触XNA并且与C#相当新(相比之下),我无法想象我的生活。

更新1: 感谢mcmonkey4eva,该错误已得到解决。但是,我的代码现在在TestLevel类(Level.cs)的Draw()方法中停止。该错误仍然是“NullReferenceException未处理”错误,并且方法与它们有点不同。

任何人都知道我在这里做错了吗?


这是我更新的Level.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;
using First.Tiles;
using First;


namespace First.Level
{
    class TestLevel
    {
        //An array of groundtiles that will be set to grass, lava, etc
        public GroundTile[,] groundlevel;

        //Width/Height of the Level
        int width, height;

        Grass grass;

        public TestLevel(int width, int height, ContentManager myContent)
        {
            content = myContent;
            //I input my screen dimensions as my level size
            this.width = width;
            this.height = height;

            groundlevel = new GroundTile[width, height];

            grass = new Grass(content.Load<Texture2D>(@"Images\GroundTiles"));
        }

        //Drawing the grass near the bottom of the screen
        public void generateGround()
        {
            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x += 32)
                {
                    if (y == (height - 100))
                    {
                        if (groundlevel[x, y] == null)
                        {
                            groundlevel[x, y] = grass;
                        }

                    }
                }
            }

        }

        public void draw(GameTime gameTime, SpriteBatch spriteBatch)
        {
            foreach(GroundTile ground in groundlevel)
            {
                ground.Draw(gameTime, spriteBatch); //Here's where the error is
            }
        }

        public static ContentManager Content
        {
            get { return content; }
        }
        static ContentManager content;
    }
}

这是我更新的Game1.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;
using First.Entity;
using First.Tiles;
using First.Level;

namespace First
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {

        const int SCREEN_WIDTH = 600;
        const int SCREEN_HEIGHT = 400;

        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        TestLevel level;

        UserControlledSprite Lancer;
        Texture2D lancerTexture;
        Vector2 position = new Vector2(200, 200);
        Point frameSize = new Point(32, 48);
        int collisionOffset = 0;
        Point currentFrame = new Point(0, 0);
        Point sheetSize = new Point(4, 4);
        Point spriteToUse = new Point(0, 0);
        Vector2 speed = new Vector2(2, 2);
        int millisecondsPerFrame = 500;

        Rectangle clientBounds;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        /// <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()
        {
            // TODO: Add your initialization logic here

            clientBounds = graphics.GraphicsDevice.Viewport.Bounds;
            clientBounds.Width = SCREEN_WIDTH;
            clientBounds.Height = SCREEN_HEIGHT;

            this.IsMouseVisible = true;

            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()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            Content.RootDirectory = "Content";

            level = new TestLevel(SCREEN_WIDTH, SCREEN_HEIGHT, Content);
            level.generateGround();

            lancerTexture = Content.Load<Texture2D>(@"Images\Lancer");
            Lancer = new UserControlledSprite(lancerTexture, position, frameSize, collisionOffset,
                                              currentFrame, sheetSize, spriteToUse, speed, millisecondsPerFrame);
        }

        /// <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();

            Lancer.Update(gameTime, clientBounds);

            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();
            Lancer.Draw(gameTime, spriteBatch);
            level.draw(gameTime, spriteBatch);
            spriteBatch.End();

            base.Draw(gameTime);
        }
    }
}

这是我的Grass.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;
using First.Tiles;
using First;


namespace First.Level
{
    class TestLevel
    {
        //An array of groundtiles that will be set to grass, lava, etc
        public GroundTile[,] groundlevel;

        //Width/Height of the Level
        int width, height;

        Grass grass;

        public TestLevel(int width, int height, ContentManager myContent)
        {
            content = myContent;
            //I input my screen dimensions as my level size
            this.width = width;
            this.height = height;

            groundlevel = new GroundTile[width, height];

            grass = new Grass(content.Load<Texture2D>(@"Images\GroundTiles"));
        }

        //Drawing the grass near the bottom of the screen
        public void generateGround()
        {
            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x += 32)
                {
                    if (y == (height - 100))
                    {
                        if (groundlevel[x, y] == null)
                        {
                            groundlevel[x, y] = grass;
                        }

                    }
                }
            }

        }

        public void draw(GameTime gameTime, SpriteBatch spriteBatch)
        {
            foreach(GroundTile ground in groundlevel)
            {
                ground.Draw(gameTime, spriteBatch);
            }
        }

        public static ContentManager Content
        {
            get { return content; }
        }
        static ContentManager content;
    }
}

以防万一,这里也是我的GroundTile课程:

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 First.Entity;

namespace First.Tiles
{
    class GroundTile
    {

        //public GroundTile grass = new Grass(content.Load<Texture2D>(@"Images\GroundTiles"));

        // frameSize needs to be modular, for the objects above walking-ground level

        public Texture2D texture;
        protected Point frameSize;
        public Point frame;
        public Vector2 position;
        int collisionOffset;
        protected Point sheetSize = new Point(9, 19);

        public GroundTile(Texture2D tiles, Point frame, Point frameSize, int collisionOffset)
        {
            this.frame = frame;
            this.frameSize = frameSize;
            this.collisionOffset = collisionOffset;

            this.texture = tiles;
        }

        //Collision Detection, incase of water or something
        public Rectangle collisionRect
        {
            get
            {
                return new Rectangle(
                    (int)position.X + collisionOffset,
                    (int)position.Y + collisionOffset,
                    frameSize.X - (collisionOffset * 2),
                    frameSize.Y - (collisionOffset * 2));
            }
        }

        //Not really used, but just in case
        public bool collidesWith(GroundTile tile, Sprite sprite)
        {
            if (sprite.collisionRect.Intersects(collisionRect))
            {
                sprite.position -= sprite.direction;
            }

            return false;
        }

        public static ContentManager Content
        {
            get { return content; }
        }
        static ContentManager content;

        public GraphicsDevice Graphicsdevice
        {
            get { return graphicsDevice; }
        }
        GraphicsDevice graphicsDevice;

        public virtual void Draw(GameTime gameTime, SpriteBatch spriteBatch)
        {
            spriteBatch.Draw(texture,
                position,
                new Rectangle(frame.X * frameSize.X,
                    frame.Y * frameSize.Y,
                    frameSize.X, frameSize.Y),
                    Color.White, 0, Vector2.Zero,
                    1f, SpriteEffects.None, 0);
        }

    }
}

2 个答案:

答案 0 :(得分:1)

您在设置之前访问Content - 或者说,您根本就没有设置它。

更改

public TestLevel(int width, int height)
{
    //I input my screen dimensions as my level size

public TestLevel(int width, int height, ContentManager myContent)
{
    content = myContent;
    //I input my screen dimensions as my level size

然后在创建TestLevel对象时添加Content参数(我假设来自Game1.cs)(注意:确保在创建之后创建TestLevel 内容对象[在LoadContent方法中]!)

编辑:

对于新问题:

你没有定义数组的内容,除了单层草......

该行

            ground.Draw(gameTime, spriteBatch);

更改为

            if (ground != null)
            {
                 ground.Draw(gameTime, spriteBatch);
            }

但是你还应该确保地面实际上充满了内容......特别是,数组中每个点的新tile对象,而不仅仅是一行,而不仅仅是同一个'grass'实例每个地方。

我不是故意冒犯,但你在这里处理的是非常基本的错误。查阅并遵循一些基本的C#教程可能对您有所帮助。

答案 1 :(得分:0)

我不知道XNA,但很明显你的内容。返回null。

这是您的级别类的类名称还是属性?如果它是属性,则确保它已初始化。 Otherwize,我不明白如果你调用类的静态属性你将如何收到nullreferenceexception