【问题标题】:Disappearing Objects消失的物体
【发布时间】:2017-03-30 05:04:39
【问题描述】:

所以对于我的第一个 MonoGame 项目,我决定制作一个俄罗斯方块克隆,但我遇到了一个我不知道如何解决的问题。

目前我的代码正在生成一个块并将其向下移动,直到它到达特定的 y 位置。方块需要停留在这个位置并生成一个新方块。我正在使用包含块类对象的列表来执行此操作,然后仅绘制此列表中的所有块。

我取出了我认为与问题无关的部分:

 public class PlayField : DrawableGameComponent
    {
        private Game1 gameRef;
        private Texture2D fieldTexture;
        private BlockGenerator blockGenerator;
        private Texture2D[] allBlocks;

        private Block currentBlock;

        public bool[,] fieldFilled;
        private int down_Blocks = 22;
        private int side_Blocks = 10;

        public List<Block> placedBlocks;

        public PlayField(Game game) : base(game)
        {
            placedBlocks = new List<Block>();
            allBlocks = new Texture2D[4];
            blockGenerator = new BlockGenerator(allBlocks,gameRef);

        }   
        public override void Update(GameTime gameTime)
        {
            base.Update(gameTime);
            try
            {
                if (currentBlock.isMoving == false)
                {
                    placedBlocks.Add(currentBlock);
                    currentBlock = null;
                    currentBlock = blockGenerator.GenerateBlock();
                }
                else
                {
                    currentBlock.UpdatePosition(gameTime);
                    if (InputManager.CheckForKeyBoardRelease(Keys.A))
                    {
                        currentBlock.MoveLeft();
                    }

                    if (InputManager.CheckForKeyBoardRelease(Keys.D))
                    {
                        currentBlock.MoveRight();
                    }
                }
            }
            catch(NullReferenceException e)
            {
                currentBlock = blockGenerator.GenerateBlock();
            }


        }

        public override void Draw(GameTime gameTime)
        {
            gameRef.SpriteBatch.Begin();

            if(currentBlock != null)
            {
                currentBlock.DrawBlocks();
            }

            foreach(Block b in placedBlocks)
            {
                b.DrawBlocks();
            }

            gameRef.SpriteBatch.End();
            base.Draw(gameTime);
        }

“GenerateBlock”方法返回“Block”类型的对象

public class Block : DrawableGameComponent
    {
        Game1 gameRef;
        public Texture2D blockTexture;
        public Vector2[] blockPositions;
        TimeSpan lastMove;
        TimeSpan blockMove = TimeSpan.FromMilliseconds(500);

        public bool isMoving;


        public Block(Game game, Texture2D _blockTexture, Vector2[] _blockPositions) : base(game)
        {
            gameRef = (Game1)game;
            blockTexture = _blockTexture;
            blockPositions = _blockPositions;
            isMoving = true;
        }

        public void UpdatePosition(GameTime gameTime)
        {
            Vector2 bottomBlockPositon = FindBottomBlock();
            if(bottomBlockPositon.Y < 550)
            {
                if (WaitTillMove(gameTime))
                {
                    for (int i = 0; i < blockPositions.Length; i++)
                    {
                        blockPositions[i] = new Vector2(blockPositions[i].X, blockPositions[i].Y + 25);
                    }
                }
            }
            else
            {
                isMoving = false;
                Console.WriteLine("X: " +blockPositions[0].X + " Y:" + blockPositions[0].Y);
            }

        }

        public Vector2 FindBottomBlock()
        {
            Vector2 result = new Vector2(0, 0);
            for(int i = 0; i < blockPositions.Length; i++)
            {
                if(blockPositions[i].Y > result.Y)
                {
                    result = blockPositions[i];
                }
            }

            return result;
        }

        public bool WaitTillMove(GameTime gameTime)
        {
            if (lastMove + blockMove < gameTime.TotalGameTime)
            {
                lastMove = gameTime.TotalGameTime;
                return true;
            }
            return false;
        }

        public void DrawBlocks()
        {
            gameRef.SpriteBatch.Draw(blockTexture, blockPositions[0], Color.White);
            gameRef.SpriteBatch.Draw(blockTexture, blockPositions[1], Color.White);
            gameRef.SpriteBatch.Draw(blockTexture, blockPositions[2], Color.White);
            gameRef.SpriteBatch.Draw(blockTexture, blockPositions[3], Color.White);
        }
    }

调试表明我的列表包含一个元素,即使它的位置错误。但这无关紧要,因为我仍然只能同时“看到”一个 Block。

希望有人能把我引向正确的方向。

编辑:

public class BlockGenerator
    {
        Random random;
        Texture2D[] allBlocks;
        Vector2[] blockPositions;
        Texture2D currentBlock;
        BlockEnums currentBlockEnum;

        Game1 gameRef;

        public BlockGenerator(Texture2D[] blocks, Game1 game)
        {
            gameRef = (Game1)game;
            allBlocks = blocks;
            currentBlock = allBlocks[1];
            blockPositions = new Vector2[4];
            random = new Random();
        }

        public Block GenerateBlock()
        {
            int colorValue = random.Next(0, 4);     //0 = blue, 1 = green, 2 = red, 3 = yellow

            currentBlock = allBlocks[colorValue];
            currentBlockEnum = BlockEnums.Line;

            blockPositions[0] = new Vector2(100, 0);
            blockPositions[1] = new Vector2(125, 0);
            blockPositions[2] = new Vector2(150, 0);
            blockPositions[3] = new Vector2(175, 0);

            Block generatedBlock = new Block(gameRef,currentBlock, blockPositions);

            return generatedBlock;
        }

【问题讨论】:

  • 我认为您也需要发布 BlockGenerator 类,我怀疑 GenerateBlock 的实现是相关的。
  • 这个catch(NullReferenceException e) 看起来很奇怪。 NullReferenceException 发生在不小心进行编程时。您必须在null 上检查它,而不是使用磁带。我仍在尝试掌握您的代码。太糟糕了,我不能踩它;-)
  • 我已将代码发布到 BlockGenerator。 @Jeroen van Langen:是的,我实际上只在第一次迭代中使用 try/catch,因为在创建 PlayField 时 currentBlock 将为空,因此我什至会在生成单个块之前得到异常^^
  • 旧对象消失了吗?新区块不会出现吗?
  • @Wikked 您可以在方法的开头添加if(currentBlock == null) currentBlock = blockGenerator.GenerateBlock();。然后你将摆脱 try/catch

标签: c# monogame


【解决方案1】:
public class BlockGenerator
    {
        Random random;
        Texture2D[] allBlocks;
        Vector2[] blockPositions; // delete this

然后将初始化代码从构造函数移入GenerateBlock(添加var)。

var blockPositions = new Vector2[4];

那么它应该可以工作。您每次创建块时都在创建新向量,但每次都重复使用相同的 blockPositions 实例,因此两个块确实存在,但始终具有完全相同的位置。

我还没来得及测试,但我认为它是正确的......让我知道:)

edit:我还建议将 blockPositions 完全移动到 Block 类中。我认为在真正拥有它的类之外拥有该逻辑没有任何价值(在您发布的代码中,也许您有以后的计划)......如果它最初包含在类中,您将避免这种情况问题。只是一个建议:)

【讨论】:

  • 谢谢(:稍作调整
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-10-10
  • 1970-01-01
  • 1970-01-01
  • 2013-12-31
  • 1970-01-01
  • 2017-12-28
  • 2015-10-18
相关资源
最近更新 更多