1

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

但是,我在 Level.cs 类的第 32 行收到“NullReferenceException was Unhandled”错误。由于我只是 XNA 的新手,而 C# 的新手(相比之下),我无法终生解决这个问题。

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

有人知道我在这里做错了什么吗?


这是我更新的 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);
        }

    }
}
4

2 回答 2

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)(注意:确保在创建 Content 对象TestLevel 创建 [在 LoadContent 方法中]!)

编辑:

对于新问题:

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

线

            ground.Draw(gameTime, spriteBatch);

改成

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

但是您还应该确保地面实际上充满了内容......特别是阵列中每个点的新平铺对象,而不仅仅是一条线,而不仅仅是每个位置的相同“草”实例。

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

于 2013-07-19T15:26:41.997 回答
0

我不知道 XNA,但显然你的内容。返回空值。

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

于 2013-07-19T15:27:09.773 回答