Моноигра, почему блок не перемещается, даже если для него есть функция?

#c# #xna #monogame

Вопрос:

Мне нужна помощь, у меня есть игра в лабиринт, в которой мне нужно нажать на блок. Если я пересечусь с блоком, первый должен переместиться вправо, а второй-влево. Проблема в том, что я не могу заставить ни одного из них двигаться, когда я пересекаюсь. Помощь была бы признательна.

Игра1.cs

 using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System.Collections.Generic;

namespace Labyrintspel

{
public class Game1 : Game
{
    private GraphicsDeviceManager _graphics;
    private SpriteBatch _spriteBatch;
    Texture2D pixelTexture;
    Texture2D playerTexture;
    List<Block> blocks = new List<Block>();
    Player player;
    Color backgroundColor = Color.CornflowerBlue;
    Block door;
    Block door2;
    int i = 0;
    int i2 = 0;
    int speed1 = 1;
    int speed2 = -1;

    public Game1()
    {
        _graphics = new GraphicsDeviceManager(this);
        _graphics.PreferredBackBufferWidth = 800;
        _graphics.PreferredBackBufferHeight = 500;
        _graphics.ApplyChanges();
        Content.RootDirectory = "Content";
        IsMouseVisible = true;
        
}

    protected override void Initialize()
    {
        base.Initialize();
    
        
            blocks.Add(BlockFactory.CreateEatableBlock(70, 300));
            blocks.Add(BlockFactory.CreateEatableBlock(190, 300));
            blocks.Add(BlockFactory.CreateEatableBlock(490, 300));
            blocks.Add(BlockFactory.CreateWall(0, 460, 800, 40));
            blocks.Add(BlockFactory.CreateWall(0, 0, 800, 30));
            blocks.Add(BlockFactory.CreateWall(0, 0, 40, 460));
            blocks.Add(BlockFactory.CreateWall(760, 0, 40, 460));
            blocks.Add(BlockFactory.CreateWall(640, 200, 40, 260));
            blocks.Add(BlockFactory.CreateWall(140, 100, 700, 40));
            blocks.Add(BlockFactory.CreateWall(540, 130, 40, 250));
            blocks.Add(BlockFactory.CreateWall(440, 200, 40, 260));
            blocks.Add(BlockFactory.CreateWall(340, 130, 40, 250));
            blocks.Add(BlockFactory.CreateWall(240, 200, 40, 260));
            blocks.Add(BlockFactory.CreateWall(140, 130, 40, 250));
            blocks.Add(BlockFactory.RemovableWall(600, 0, 40, 100));
            blocks.Add(BlockFactory.CreateWall(650, 375, 150, 200));
            door = new Block(720, 40, 30, 50, Color.SaddleBrown);
            blocks.Add(door);
            door2 = new Block(700, 400, 30, 50, Color.SaddleBrown);


            player = new Player(700, 300, playerTexture.Width, playerTexture.Height);
        
    }

    protected override void LoadContent()
    {
        _spriteBatch = new SpriteBatch(GraphicsDevice);
        pixelTexture = Content.Load<Texture2D>("pixel");
        playerTexture = Content.Load<Texture2D>("player");

    }

    protected override void Update(GameTime gameTime)
    {
        var keyState = Keyboard.GetState();
        base.Update(gameTime);

        player.StorePosition();

        if (keyState.IsKeyDown(Keys.Left)) player.MoveLeft();
        if (keyState.IsKeyDown(Keys.Right)) player.MoveRight();
        if (keyState.IsKeyDown(Keys.Up)) player.MoveUp();
        if (keyState.IsKeyDown(Keys.Down)) player.MoveDown();
        

        if (player.GetRectangle().Intersects(door.Rectangle))
        {
            i = 0;
            blocks.RemoveAll(block => block.IsVisible);
            blocks.Add(BlockFactory.CreateWall(0, 460, 800, 40));
            blocks.Add(BlockFactory.CreateWall(0, 0, 800, 30));
            blocks.Add(BlockFactory.CreateWall(0, 0, 40, 460));
            blocks.Add(BlockFactory.CreateWall(760, 0, 40, 460));
            blocks.Add(BlockFactory.CreateWall(100, 100, 800, 40));
            blocks.Add(BlockFactory.CreateWall(0, 200, 400, 40));
            blocks.Add(BlockFactory.CreateWall(500, 200, 400, 40));
            blocks.Add(BlockFactory.CreateWall(0, 300, 200, 40));
            blocks.Add(BlockFactory.CreateWall(300, 300, 500, 40));
            blocks.Add(BlockFactory.RemovableWall(600, 300, 40, 300));
            blocks.Add(BlockFactory.CreateEatableBlock(700, 250));
            blocks.Add(BlockFactory.CreateEatableBlock(190, 150));
            blocks.Add(BlockFactory.CreateEatableBlock(500, 400));
            blocks.Add(BlockFactory.CreatePushableBlock(50, 150));
            blocks.Add(BlockFactory.CreatePushableBlock(50, 400));
            blocks.Add(door2);

        }
        if (player.GetRectangle().Intersects(door2.Rectangle))
        {
            this.Exit();
        }
       

        backgroundColor = Color.CornflowerBlue;
            foreach (var block in blocks)
            {
                if (player.GetRectangle().Intersects(block.Rectangle))
                {
                   if (block.IsPushable amp;amp; keyState.IsKeyDown(Keys.Space) amp;amp; i2 == 0)
                   {
                    block.MoveRight();
                    i2  ;                        
                   }
                    if (block.IsSolid) player.RestorePosition();
                    if (block.IsEatable)
                    {
                        block.IsVisible = false;
                        i  ;

                    }
                }
                if (i == 3)
                {
                    if (block.IsRemovable)
                    {
                        block.IsSolid = false;
                        block.IsVisible = false;
                    }
                }


            }


            blocks.RemoveAll(block => !block.IsVisible);
        
    }

    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(backgroundColor);

        _spriteBatch.Begin();
        blocks.ForEach(block => block.Draw(_spriteBatch, pixelTexture));
        player.Draw(_spriteBatch, playerTexture);
        _spriteBatch.End();

        Window.Title = "Antal block: "   blocks.Count;

        base.Draw(gameTime);
    }
}
 

Блок.cs

 public class Block
{

    public Rectangle Rectangle { get; set; }
    public Color Color { get; set; }
    public bool IsSolid { get; set; } = true;
    public bool IsEatable { get; set; } = false;
    public bool IsVisible { get; set; } = true;
    public bool IsRemovable { get; set; } = false;
    public bool IsPushable { get; set; } = false;
    private Vector2 position;
    private Rectangle rectangle;


    public Block(int x, int y, int w, int h, Color color)
    {
        
        Color = color;
        position.X = x;
        position.Y = y;
        Rectangle = new Rectangle(x, y, w, h);
    }

    public void Move(float dx, float dy)
    {
        position.X  = dx;
        position.Y  = dy;
    }
    public Rectangle PushabelRectangle()
    {
        rectangle.X = (int)position.X;
        rectangle.Y = (int)position.Y;
        return rectangle;
    }

    internal void MoveLeft() => Move(-10, 0);
    internal void MoveRight() => Move(100, 0);

    public void Draw(SpriteBatch spriteBatch, Texture2D texture)
    {
       
       if (IsVisible)
         {
                spriteBatch.Draw(texture, Rectangle, Color);
         }
       
    }
    
}
 

blockfactory.cs

  internal class BlockFactory
    
{
    internal static Block CreateEatableBlock(int x, int y)
    {
        var block = new Block(x, y, 40, 40, Color.Yellow);
        block.IsSolid = false;
        block.IsEatable = true;
        return block;
    }
    internal static Block CreatePushableBlock(int x, int y)
    {
        var block =  new Block(x, y, 40, 40, Color.Orange);
        block.IsPushable = true;
        return block;
    }

    internal static Block CreateWall(int x, int y, int w, int h)
    {
         return new Block(x, y, w, h, Color.Black);
    }

    internal static Block RemovableWall(int x, int y, int w, int h)
    {
        var block = new Block(x, y, w, h, Color.Black);
        block.IsSolid = true;
        block.IsEatable = false;
        block.IsVisible = true;
        block.IsRemovable = true;
        return block;
    }
    internal static Block CreatePushBlock(int x, int y, int w, int h)
    {
        return new Block(x, y, w, h, Color.Orange);
    }
}
 

Этот код не показывает ошибок, но ничего не происходит, когда я пересекаюсь и нажимаю пробел.

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

1. Вы установили точку останова и отладили ее, чтобы проверить и посмотреть, достигнет ли она block.MoveRight() ?

2. Мне нужно подчеркнуть минимальный воспроизводимый код, необходимый для отображения проблемы. Никаких толкаемых блоков до тех пор, пока вы не пройдете через дверь? Многократное сокращение кода показывает вам ответ.

Ответ №1:

Move() меняется position переменная, но блок рисуется из Rectangle поля, которое не изменяется для отражения движения.

Я бы предложил следующую корреляцию: public Rectangle Rectangle { get{return rectangle; } set {rectangle = value;} } )

 public void Move(float dx, float dy)
    {
        position.X  = dx;
        position.Y  = dy;
        Rectangle =  new Rectangle((int)position.X, (int)position.Y, Rectangle.Width, Rectangle.Height);
    // you cannot set the X and Y of field structures directly.
    }