1

我正在尝试创建一个简单的游戏来测试碰撞检测,但它无法正常运行。它构建得很好,但是在运行它时出现此错误:“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);
        }
    }
}

引发异常的行是player.Update(gameTime, Game.Window.ClientBounds);from SpriteManager。完整的异常消息是“Project 3.exe 中发生了类型为 'System.NullReferenceException' 的未处理异常。附加信息:对象引用未设置为对象的实例。”

用户控制精灵.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; }
}
}
4

2 回答 2

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、位置、碰撞偏移和速度。我看到您在 Sprite 类中有变量,但我没有看到您在使用构造函数创建它们时设置它们。除非,请告诉我是否是这种情况,传入与变量同名的参数会自动设置它吗?如果不是这种情况,那么请确保您将 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,现在只想尝试帮助你。

无论如何,我希望这会有所帮助。对不起,如果可以的话,我会发表评论。可悲的是我还不能。

于 2014-04-04T02:11:17.680 回答
0

您没有实例化position. 您将position变量传递给构造函数,UserControlledSprite但不要将其应用于类范围内的变量。您需要声明另一个变量来保存位置变量,该变量仅对构造函数方法可见。

这意味着UserControlledSprite对象第一次调用Update,那么position += direction;就会抛出NullReferenceException。老实说,我不知道你是如何没有得到编译时错误的,因为position在 的上下文中不会存在Update,除非你没有向我们展示整个代码。

于 2013-03-25T09:29:50.573 回答