XNA Sprite, похоже, не обновляется?

#c# #xna #sprite #xna-4.0

#c# #xna #sprite #xna-4.0

Вопрос:

Я просмотрел некоторые другие вопросы и не нашел своего ответа, поэтому я прошу вас, милые люди, поскольку вы помогали мне раньше 🙂

У меня есть основной класс (RPG.cs) и класс игрока (Player.cs), и я хочу, чтобы класс игрока был как можно более автономным (потому что мне не нужен основной класс huuuge), но вот моя проблема.

Проблема

Мой спрайт плеера рисует нормально, но когда я хочу, чтобы он двигался, он не обновляется! На данный момент я пытаюсь заставить его действовать как курсор для проверки движения, но в конечном итоге он будет привязан к WASD или клавишам со стрелками. Поэтому я хочу, чтобы мой спрайт в данный момент следовал за моей мышью, но он просто остается на 50, 50 (это заданное начальное положение). Я пропустил что-то очевидное? Я новичок в XNA, и я потратил полчаса на эту проблему!

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);
        }
    }
}
 

Надеюсь, вы сможете помочь! 🙂

Комментарии:

1. Я думаю, это потому, что вы не вызываете функцию обновления вашего класса player в своем основном методе.

2. @Haris Я так не думаю, потому что в моей основной функции обновления я ввел «Player». и функции обновления не было в списке. И когда я использую плеер. Update(GameTime);’ это дает мне следующее: ‘Для нестатического поля, метода или свойства требуется ссылка на объект.’ и я не могу изменить обновление на статическое, иначе возникнет больше ошибок.

3. Вам, очевидно, не хватает базовых знаний как ООП, так и о программировании на XNA. Ответ здесь не может охватить все проблемы вашего кода. Я бы посоветовал прочитать хотя бы о рисованных компонентах XNA (например, здесь ).

4. @NicoSchertler Я понимаю, что мало знаю об этом, но не могли бы вы ответить на мой вопрос, а не указывать на все проблемы в моем коде?

Ответ №1:

Как упоминалось в комментарии, я не собираюсь решать все проблемы. Но основные ошибки.

Пусть игрок несет ответственность за свою позицию, а не за игру. Кроме того, я бы возложил на игрока ответственность за сам розыгрыш, но это заходит слишком далеко для такого ответа.

Следующий код должен, по крайней мере, работать.

 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);
    }
}
 

Затем используйте плеер в своей игре:

 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);
    }
}
 

Я удалил размер текстуры. Не знаю, действительно ли вам это нужно. Если это так, вы можете позволить Player выставить прямоугольник, а не просто Vector2 .

Ответ №2:

Ключевое решение, которое включил Нико, заключается в том, что вы используете исходные координаты прямоугольника, которые вы создали при рисовании:

 Rectangle playerPos = new Rectangle(
             Convert.ToInt32(Player.Pos.X), 
             Convert.ToInt32(Player.Pos.Y), 32, 32);
 

Здесь вы создаете прямоугольник, используя ТЕКУЩУЮ начальную временную позицию игроков.
Тогда вы ВСЕГДА рисуете на основе этого прямоугольника, который вы создали много лет назад и никогда не обновлялись:

         spriteBatch.Draw(PlayerTex, playerPos, Color.White);
 

Правильный способ, как упоминал Нико, — просто изменить ничью на это:

  playerPos = new Rectangle(
             Convert.ToInt32(Player.Pos.X), 
             Convert.ToInt32(Player.Pos.Y), 32, 32);

    spriteBatch.Draw(PlayerTex, playerPos, Color.White);
 

Теперь вы каждый раз будете рисовать в новом месте. Есть лучшие способы сделать это (например, то, что сделал Нико), но вот основная идея.