0
\$\begingroup\$

I am pretty new to Monogame, and I'm trying to draw a character sprite and move it using keyboard. Instead of moving to different positions, it leaves a track of copies along the way.

I have 2 game states; one is the menu, and the other one is the level, where the sprite is called to draw.

Why is my sprite leaving copies as it moves in Monogame?


Player.cs

class Player : Entity
{
    private float velocity;
    private int hp;
    public Texture2D texture;
    public Rectangle hitbox;
    public Vector2 pos;
    KeyboardState oldState;

    public void Init(ContentManager content)
    {
        texture = content.Load<Texture2D>("char");
        hitbox.Width = texture.Width;
        hitbox.Height = texture.Height;
        velocity = 150f;
        pos.X = 100;
        pos.Y = 100;
    }

    public void Update(float delta)
    {
        KeyboardState newState = Keyboard.GetState();

        if (newState.IsKeyDown(Keys.D))
            pos.X += 100 * delta;
        if (newState.IsKeyDown(Keys.A))
            pos.X -= 100 * delta;

        oldState = newState;
    }

    public void Draw(SpriteBatch sb)
    {
        sb.Begin();
        sb.Draw(texture, pos, Color.White);
        sb.End();
    }
}

Level1.cs

class Level1 : State
{
    private Texture2D background;
    public Player player;

    public void Init(ContentManager content)
    {
        //background = content.Load<Texture2D>("Level1/bg");
        player = new Player();
        player.Init(content);
    }

    public void Update(float delta)
    {
        player.Update(delta);
    }

    public void Draw(SpriteBatch sb, GraphicsDeviceManager graphics)
    {
        player.Draw(sb);
    }
}

Game1.cs

public class Game1 : Game
{
    GraphicsDeviceManager graphics;
    SpriteBatch spriteBatch;
    State CurrentState;
    KeyboardState oldState;

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

    void SetState(State state)
    {
        GraphicsDevice.Clear(Color.White);
        CurrentState = state;
        CurrentState.Init(Content);
    }

    protected override void Initialize()
    {
        SetState(new MenuState());
        graphics.PreferredBackBufferWidth = 1920;
        graphics.PreferredBackBufferHeight = 1080;
        graphics.IsFullScreen = true;
        graphics.ApplyChanges();
        base.Initialize();
    }

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

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

        var delta = (float)gameTime.ElapsedGameTime.TotalSeconds;

        CurrentState.Update(delta);

        if (CurrentState is MenuState && (newState.IsKeyDown(Keys.F) 
            && oldState.IsKeyUp(Keys.F)))
        {
            SetState(new Level1());
        }

        if (CurrentState is MenuState && (newState.IsKeyDown(Keys.Escape) 
            && oldState.IsKeyUp(Keys.Escape)))
        {
            this.Exit();
        }

        if (CurrentState is Level1 && (newState.IsKeyDown(Keys.Escape) 
            && oldState.IsKeyUp(Keys.Escape)))
        {
            this.Exit();
        }

        base.Update(gameTime);
        oldState = newState;
    }

    protected override void Draw(GameTime gameTime)
    {
        CurrentState.Draw(spriteBatch, graphics);
    }
}
\$\endgroup\$
1
  • \$\begingroup\$ Try removing all irrelevant code (for example, you have an empty UnloadContent method, so it's not that), and testing/debugging extra code to try and narrow down the problem. Not sure if a value is being passed through properly? Manually set the value to a set value, and see if the problem persists. As it is, your question may be closed; Debugging questions are only on topic if they contain a minimal, verifiable code example. \$\endgroup\$
    – Gnemlock
    Apr 9 '17 at 23:04
2
\$\begingroup\$

You want to call GraphicsDevice.Clear(Color.White); before rendering the state.

\$\endgroup\$
2
  • \$\begingroup\$ Thanks, it helped :) Can't figure out how i didn't notice it by myself \$\endgroup\$
    – Steyrix
    Apr 9 '17 at 19:31
  • \$\begingroup\$ Yeah, you need to clear every frame or else the frames start rendering ontop of each other. Additionally, if your game is 3D, a Skybox can also replace the need for calling Clear. \$\endgroup\$
    – Krythic
    Apr 9 '17 at 23:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.