Search code examples
c#xnaspritexna-4.0

XNA Sprite doesn't seem to be updating?


I've looked through some other questions and haven't found my answer so I'm asking you lovely people as you have helped me before :)

I have a main class (RPG.cs) and a player class (Player.cs) and I want the Player class to be as self-contained as possible (because I don't want a huuuge main class) but here is my problem.

Problem

My Player sprite draws fine but when I want it to move, it won't update! At the moment I'm attempting to make it act like a cursor to test movement but eventually I'll have it bound to WASD or the arrow keys. So I want my sprite to follow my mouse at the moment but it just stays at 50, 50 (it's preset starting position) Have I missed something obvious? I'm new to XNA and I've spent half an hour on this problem!

RPG.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
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 TestGame
{
    public class RPG : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        Texture2D PlayerTex;
        Rectangle playerPos = new Rectangle(
            Convert.ToInt32(Player.Pos.X), 
            Convert.ToInt32(Player.Pos.Y), 32, 32);
        public RPG()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            IsMouseVisible = true;
        }
        protected override void Initialize() { base.Initialize(); }
        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);
            PlayerTex = Content.Load<Texture2D>("testChar");
        }
        protected override void UnloadContent() { }
        protected override void Update(GameTime gameTime)
        {
            if 
            (
                GamePad.GetState(PlayerIndex.One)
                .Buttons.Back == ButtonState.Pressed
            )
                this.Exit();
            base.Update(gameTime);
        }
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.White);
            spriteBatch.Begin();
            spriteBatch.Draw(PlayerTex, playerPos, Color.White);
            spriteBatch.End();
            base.Draw(gameTime);
        }
    }
}

Player.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 TestGame
{
    /// This is a game component that implements IUpdateable.
    public class Player : Microsoft.Xna.Framework.GameComponent
    {
        public static Vector2 Pos = new Vector2(50, 50);
        MouseState ms = Mouse.GetState();
        public Player(Game game) : base(game) { }
        /// 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.
        public override void Initialize() { base.Initialize(); }
        /// Allows the game component to update itself.
        public override void Update(GameTime gameTime)
        {
            Pos.X = ms.X;
            Pos.Y = ms.Y;
            base.Update(gameTime);
        }
    }
}

Hope you can help! :)


Solution

  • As mentioned in the comment, I am not going to solve every problem. But the main errors.

    Let the player be responsible for its position, not the game. Furthermore, I would make the player responsible for drawing itself, but that goes a bit too far for this answer.

    The following code should at least work.

    public class Player : Microsoft.Xna.Framework.GameComponent
    {
        public Vector2 Pos { get; set; }
    
        public Player(Game game) : base(game)
        {
            this.Pos = new Vector2(50, 50);
        }
    
        public override void Initialize() { base.Initialize(); }
    
        public override void Update(GameTime gameTime)
        {
            var ms = Mouse.GetState();
            Pos.X = ms.X;
            Pos.Y = ms.Y;
            base.Update(gameTime);
        }
    }
    

    Then use the player in your game:

    public class RPG : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        Texture2D PlayerTex;
    
        Player player;
    
        public RPG()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            IsMouseVisible = true;
            player = new Player(this);
            Components.Add(player);
        }
        protected override void Initialize() { base.Initialize(); }
        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);
            PlayerTex = Content.Load<Texture2D>("testChar");
        }
        protected override void UnloadContent() { }
        protected override void Update(GameTime gameTime)
        {
            if 
            (
                GamePad.GetState(PlayerIndex.One)
                .Buttons.Back == ButtonState.Pressed
            )
                this.Exit();
            base.Update(gameTime);
        }
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.White);
            spriteBatch.Begin();
            spriteBatch.Draw(PlayerTex, player.Pos, Color.White);
            spriteBatch.End();
            base.Draw(gameTime);
        }
    }
    

    I have removed the texture's size. Don't know if you really need this. If so, you can let Player expose a Rectangle, not just a Vector2.