Reputation: 179
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.
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! :)
Upvotes: 0
Views: 243
Reputation: 11
The key solution which Nico included is just that you using the original rectangle coordinates you made when you draw:
Rectangle playerPos = new Rectangle(
Convert.ToInt32(Player.Pos.X),
Convert.ToInt32(Player.Pos.Y), 32, 32);
Here you make the rectangle using the players CURRENT starting time position. Then you ALWAYS draw based on this rectangle you made ages ago and never updated:
spriteBatch.Draw(PlayerTex, playerPos, Color.White);
The right way as Nico mentioned is just to change the draw to this:
playerPos = new Rectangle(
Convert.ToInt32(Player.Pos.X),
Convert.ToInt32(Player.Pos.Y), 32, 32);
spriteBatch.Draw(PlayerTex, playerPos, Color.White);
Now you will be drawing at a new place every time. There are better ways to do this (like what nico did) but here is the core idea.
Upvotes: 0
Reputation: 32597
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
.
Upvotes: 2