3

我正在尝试创建一个 2d 滚动 XNA 游戏作为学习练习,但在滚动背景方面遇到了一些问题。我正在从文本文件加载关卡,通过解析创建适当的图块并将它们存储在矩阵(图块 [,])中。

然后我有一个更新方法,它改变了瓷砖的位置,所以当它被重绘时它会移动。

目前,我在移动之前遍历所有图块以绘制它们。这显然不是很有效。理想情况下,我只想在屏幕上绘制图块。我可以通过获取视口并使用图块的高度/宽度来确定屏幕上可以容纳多少图块并仅循环遍历这些图块,如下所示:

private void DrawTiles(SpriteBatch spriteBatch)
{
    float tileWidth = 40;
    float tileHeight = 32;


    for (int y = 0; y < (int)Math.Ceiling(mViewport.Height / tileHeight); ++y)
    {

       for (int x = 0; x < (int)Math.Ceiling(mViewport.Width / tileWidth); ++x)
        {
            tiles[x, y].Draw(spriteBatch);
        }
    }
}

但是,这只会在原始视口中绘制文件。外面的瓷砖永远不会被绘制,即使它们的位置确实出现了。

我认为这可以通过使用计数器来开始和结束循环来解决,每次调用 draw 方法时都会增加它。但是,我不认为这是一个很好的解决方案,但是我想不出更好的方法来确保只绘制视口中的图块。

4

2 回答 2

0

我在设计中实现的是一个继承接口,其中包含属性 IsInView 和碰撞属性,或者在您的情况下可以替换位置。然后我创建了一个单独的线程,该线程将循环并确定对象是否在视图中。然后,您可以在每个对象中添加 InView 和 OutView,并将其从绘制列表中删除。

使用循环从单独的线程运行。-- 这可以用来确定瓷砖是否可见

    public void CalculateObjsInView()
    {
        foreach (Obj o in new List<Obj>(ObjInstanceList))
        {
            if (o == null)
                continue;
            if (Camera.CollisionMask.Intersects(o.CollisionMask))
                o.IsInView = true;
            else
                o.IsInView = false;
        }
    }

在 Obj 类中

    private bool _isInView = false;
    public bool IsInView
    {
        get { return _isInView; }
        set
        {
            if (_isInView != value)
            {
                if (value)
                    InView();
                else
                    OutView();
            }
            _isInView = value;
        }
    }

    private void InView()
    {
        Game.ObjectDrawEventHandler.Add(Draw);
    }
    private void OutView()
    {
        Game.ObjectDrawEventHandler.Remove(Draw);
    }
于 2013-06-19T09:05:20.477 回答
0

您需要跟踪 ViewPort 的起点X和起点Y,就像您在0示例中始终从起点一样。例如

var startX = 10;  // Should increment as viewport scrolls
var startY = 10;  // Should increment as viewport scrolls

...

for (int y = startY; y < (int)Math.Ceiling(mViewport.Height / tileHeight); ++y)
{
   for (int x = startX; x < (int)Math.Ceiling(mViewport.Width / tileWidth); ++x)
   {
      tiles[x, y].Draw(spriteBatch);
   }
}

附带说明一下,您的 ViewPort 可能也有一个 Top 和 Left 或 X 和 Y 来跟踪这一点。在这种情况下,请将startX和替换startY为 ViewPort 中的适当属性。

于 2013-06-05T13:41:43.823 回答