Есть много вещей, которые вы не указали, но я думаю, что могу сделать обоснованное предположение: вы изменили позицию, как только получили ввод, а затем ничего не сделали, кроме "отмены" изменения позиции при обнаружении столкновение, которое привело к тому, что вектор положения оказался там, где он был. Вы можете легко решить эту проблему, выполнив часть «отменить» как минимум дважды.
Итак, вместо того, где вы сделали
Position.Y -= Direction.Y * MovementSpeed;
, вы должны сделать что-то вроде
Position.Y -= Direction.Y * MovementSpeed * 2;
Далее вам нужно будет закрепить HitBox точно на краю стены. Если этого не сделать, ваш прямоугольник Hitbox может выступать за пределы стены, а вы, вероятно, этого не захотите. установка вектора направления из входных данных и проверка столкновения. Кроме того, я надеюсь, что вы используете движение, основанное на ускорении, поскольку использование только постоянной скорости для движения может показаться грубым, тогда как использование ускорения сделает вашу игру плавной.
При этом я могу предложить много улучшения в вашем коде
Я думаю, вы используете List Walls для хранения прямоугольника для каждой стороны стены, и я думаю, что вы без нужды усложняете проблему. Вам нужна «Комната» с 4 стенами. 1022 * Это означает, что у вас есть верхняя стена с (30,30) до (430,30), левая стена с (30,30) до (30,430), правая стена с (430,30) до (430,430) и нижняя Стена от (30,430) до (430,430)
Теперь я считаю, что у вас есть Player HitBox, который снова представляет собой прямоугольник
Rectangle HitBox;
Теперь в методе Update()
вам нужно проверить, HitBox и стена пересекаются, что довольно легко получить с помощью
if(HitBox.Intersects(Wall)
{
//Handle the bouncing logic here
}
Поскольку у меня много времени, я предлагаю вам полный рабочий пример этого.
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
namespace test
{
public class Game1: Game
{
private readonly GraphicsDeviceManager _graphics;
private SpriteBatch _spriteBatch;
private Texture2D HitboxTexture, WallTexture;
private Rectangle HitBox, Wall;
private Vector2 Position, Direction, Acceleration;
float Speed;
public Game1()
{
_graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
IsMouseVisible = true;
}
protected override void Initialize(){base.Initialize();}
protected override void LoadContent()
{
_spriteBatch = new SpriteBatch(GraphicsDevice);
// TODO: use this.Content to load your game content here
HitboxTexture = Content.Load<Texture2D>("dirt");
WallTexture = Content.Load<Texture2D>("wall");
Speed=2;
HitBox=new Rectangle(0,0,40,40);
Wall=new Rectangle(30,30,400,400);
Position=Wall.Center.ToVector2();
}
protected override void Update(GameTime gameTime)
{
var ks=Keyboard.GetState();
if (ks.IsKeyDown(Keys.Escape))Exit();
//Get the Direction Vector from the keyboard
Acceleration=Vector2.Zero;
if(ks.IsKeyDown(Keys.Left))Acceleration.X=-1;
else if(ks.IsKeyDown(Keys.Right))Acceleration.X=1;
if(ks.IsKeyDown(Keys.Up))Acceleration.Y=-1;
else if(ks.IsKeyDown(Keys.Down))Acceleration.Y=1;
Acceleration*=Speed;
Acceleration=Acceleration - Direction*0.54f;//Velocity = Acceleration - Friction
Direction+=Acceleration;
Position+=Direction; //Postition
//Check for Intersectrion
if(Wall.Intersects(HitBox))
{
//Intersection is true. Now add the bouncing logic
//First, clip the box so that it is inside the wall
if(HitBox.Left<Wall.Left)Position.X=Wall.X+1;
if(HitBox.Top<Wall.Top)Position.Y=Wall.Y+1;
if(HitBox.Right>Wall.Right)Position.X=Wall.Right-HitBox.Width -1;
if(HitBox.Bottom>Wall.Bottom)Position.Y=Wall.Bottom-HitBox.Height-1;
//Now, make the direction change
if(HitBox.Left<Wall.Left || HitBox.Right>Wall.Right) Direction.X*=-1;
if(HitBox.Top<Wall.Top || HitBox.Bottom>Wall.Bottom) Direction.Y*=-1;
Direction*=2;//For True rebound
}
HitBox.X=(int)Position.X;
HitBox.Y=(int)Position.Y;
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
Color color=gameTime.IsRunningSlowly?Color.Red:Color.CornflowerBlue;
GraphicsDevice.Clear(color);
// TODO: Add your drawing code here
_spriteBatch.Begin();
_spriteBatch.Draw(WallTexture, Wall, Color.White);
_spriteBatch.Draw(HitboxTexture, HitBox, Color.White);
_spriteBatch.End();
base.Draw(gameTime);
}
}
}