【发布时间】: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