#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);
Теперь вы каждый раз будете рисовать в новом месте. Есть лучшие способы сделать это (например, то, что сделал Нико), но вот основная идея.