引用sprite类(XNA C#)时出现System.NullReferenceException错误

时间:2012-11-24 17:42:35

标签: c# xna nullreferenceexception

构建代码时,它构建正常,但不会运行。每当精灵使用精灵类中的变量时,调试它会导致Nullreferenceexception错误(Setup()的第一个实例

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 BilliardsEngine2D
{
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        Sprite CueBall;
        Sprite DirectionArrow;
        Sprite RedBall;

        SpriteFont myFont;

       //SoundEffect HitCue;
       //SoundEffect Collision;

        int ScreenWidth, ScreenHeight;

        float distance = 0.0f;
        public static float MasterVolume { get; set; }

        KeyboardState oldState;

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

        protected override void Initialize()
        {
            Setup();
            SoundEffect.MasterVolume = 0.01f;
            base.Initialize();
        }

        private void Setup()
        {
            ScreenHeight = graphics.GraphicsDevice.Viewport.Height;
            ScreenWidth = graphics.GraphicsDevice.Viewport.Width;
            CueBall.Rotation = 0.0f;
            DirectionArrow.Rotation = CueBall.Rotation;
            CueBall.Velocity = Vector2.Zero;
            CueBall.Position = new Vector2(ScreenWidth / 2, ScreenHeight / 2);
            DirectionArrow.Position = CueBall.Position;
        }

        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);

            CueBall = new Sprite(Content.Load<Texture2D>("Sprites/CueBall"));
            DirectionArrow = new Sprite(Content.Load<Texture2D>("Sprites/Arrow"));
            RedBall = new Sprite(Content.Load<Texture2D>("Sprites/RedBall"));

            myFont = Content.Load<SpriteFont>("LucidaSans");
        }

        protected override void Update(GameTime gameTime)
        {
            KeyboardState newState = Keyboard.GetState();



            if (newState.IsKeyDown(Keys.Escape)) //Pause
            {
                Exit();
            }

            if (newState.IsKeyDown(Keys.Left)) //Rotate Left
            {
                CueBall.Rotation -= 0.05f;
                DirectionArrow.Rotation = CueBall.Rotation;
            }

            if (newState.IsKeyDown(Keys.Right)) //Rotate Right
            {
                CueBall.Rotation += 0.05f;
                DirectionArrow.Rotation = CueBall.Rotation;
            }

            if (newState.IsKeyDown(Keys.Space) && oldState.IsKeyUp(Keys.Space)) //Power Up
        {
        }

        if (newState.IsKeyUp(Keys.Space) && oldState.IsKeyDown(Keys.Space)) //Fire
        {
            HitCueBall();
        }

        oldState = newState;

        SideCollision();
        //BallCollision();

        base.Update(gameTime);
    }

    private void AccelerateCueBall() //
    {
        CueBall.Velocity += new Vector2(
            (float)(Math.Cos(CueBall.Rotation - MathHelper.PiOver2) * 0.05f),
            (float)((Math.Sin(CueBall.Rotation - MathHelper.PiOver2) * 0.05f)));

        if (CueBall.Velocity.X > 7.5f)
        {
            CueBall.Velocity = new Vector2(5.0f, CueBall.Velocity.Y);
        }
        if (CueBall.Velocity.X < -7.5f)
        {
            CueBall.Velocity = new Vector2(-5.0f, CueBall.Velocity.Y);
        }
        if (CueBall.Velocity.Y > 7.5f)
        {
            CueBall.Velocity = new Vector2(CueBall.Velocity.X, 5.0f);
        }
        if (CueBall.Velocity.Y < -7.5f)
        {
            CueBall.Velocity = new Vector2(CueBall.Velocity.X, -5.0f);
        }
    }

    public void SideCollision()
    {
        CueBall.Position += CueBall.Velocity;

        if (CueBall.Position.X + CueBall.Width < 0)
        {
            CueBall.Position = new Vector2(ScreenWidth, CueBall.Position.Y);
        }
        if (CueBall.Position.X - CueBall.Width > ScreenWidth)
        {
            CueBall.Position = new Vector2(0, CueBall.Position.Y);
        }
        if (CueBall.Position.Y + CueBall.Height < 0)
        {
            CueBall.Position = new Vector2(CueBall.Position.X, ScreenHeight);
        }
        if (CueBall.Position.Y - CueBall.Height > ScreenHeight)
        {
            CueBall.Position = new Vector2(CueBall.Position.X, 0);
        }
    }

    private bool CheckBallCollision(Sprite CueBall, Sprite RedBall)
    {
        Vector2 position1 = CueBall.Position;
        Vector2 position2 = RedBall.Position;

        float Cathetus1 = Math.Abs(position1.X - position2.X);
        float Cathetus2 = Math.Abs(position1.Y - position2.Y);

        Cathetus1 *= Cathetus1;
        Cathetus2 *= Cathetus2;

        distance = (float)Math.Sqrt(Cathetus1 + Cathetus2);
        if ((int)distance < CueBall.Width)
            return true;

        return false;
    }

    private void HitCueBall()
    {


        Vector2 Velocity = new Vector2(
            (float)Math.Cos(CueBall.Rotation - (float)MathHelper.PiOver2),
            (float)Math.Sin(CueBall.Rotation - (float)MathHelper.PiOver2));

        Velocity.Normalize();
        Velocity *= 6.0f;
        CueBall.Velocity = Velocity;
        CueBall.Position = CueBall.Position + CueBall.Velocity;
    }

    protected override void UnloadContent()
    {

    }

    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.Green);

        spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend);

        spriteBatch.Draw(CueBall.Texture, CueBall.Position, null, Color.White, CueBall.Rotation, CueBall.Center, CueBall.Scale, SpriteEffects.None, 1.0f);
        spriteBatch.Draw(DirectionArrow.Texture, DirectionArrow.Position, null, Color.White, DirectionArrow.Rotation, DirectionArrow.Center, 
            DirectionArrow.Scale, SpriteEffects.None, 1.0f);

        spriteBatch.End();
        base.Draw(gameTime);
    }
}

精灵类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;

namespace BilliardsEngine2D
{
class Sprite
{
    Texture2D texture;

    Vector2 position;
    Vector2 center;
    Vector2 velocity;

    float rotation;
    float scale;

    public Sprite(Texture2D texture)
    {
        this.texture = texture;

        position = Vector2.Zero;
        center = new Vector2(texture.Width / 2, texture.Height / 2);
        velocity = Vector2.Zero;

        Rotation = 0.0f;
        Scale = 1.0f;
    }

    public Texture2D Texture
    {
        get { return texture; }
    }

    public Vector2 Position
    {
        get { return position; }
        set { position = value; }
    }

    public Vector2 Center
    {
        get { return center; }
    }

    public Vector2 Velocity
    {
        get { return velocity; }
        set { velocity = value; }
    }

    public float Rotation
    {
        get { return rotation; }
        set
        {
            rotation = value;
            if (rotation < -MathHelper.TwoPi)
                rotation = MathHelper.TwoPi;
            if (rotation > MathHelper.TwoPi)
                rotation = -MathHelper.TwoPi;
        }
    }

    public float Scale
    {
        get { return scale; }
        set { scale = value; }
    }

    public int Width
    {
        get { return texture.Width; }
    }

    public int Height
    {
        get { return texture.Height; }
    }
}

任何想法如何解决这个问题。

1 个答案:

答案 0 :(得分:1)

我相信您的setup方法在LoadContent方法之前被调用。

根据this documentation LoadContentInitialize调用。

    protected override void Initialize()
    {
        Setup();
        SoundEffect.MasterVolume = 0.01f;
        base.Initialize();
    }

我认为假设base.Initialize()是调用LoadContent的地方是公平的。

我认为您的代码存在问题,因为您试图在Sprite方法之前设置Setup()类的属性之前 {1}}方法。


我建议您在修改Sprite属性的位置移动语句:

LoadContent()
在您使用CueBall.Rotation = 0.0f; 方法new Sprite()进行实例化后,

LoadContent
您的CueBall = new Sprite(Content.Load<Texture2D>("Sprites/CueBall")); 方法

中的

或者您可以将LoadContent来电转移到Setup方法