2

我正在尝试创建一个简单的 2d 滚动游戏作为 monogame (XNA) 的学习练习。目前我从一个文本文件中加载平铺信息,创建一个数组 (tiles[,]),其中包含一个平铺对象存储有关平铺写入位置以及调用 draw 方法时应使用的纹理的信息。目前我一次绘制数组中的每个图块,然后简单地更新图块的位置以在屏幕上移动它。显然,一次绘制所有图块有点痛苦,我认为如果我只绘制屏幕上可见的图块会更好,因为随着图块在屏幕上移动,会绘制更多图块。我不确定如何最好地做到这一点?对于如何判断应该绘制哪些瓷砖,我有点迷茫。任何帮助将不胜感激。

    /// <summary>
    /// Draws each individual tile in the level.
    /// </summary>
    private void DrawTiles(SpriteBatch spriteBatch)
    {
        // For each tile position
        for (int y = 0; y < Height; ++y)
        {
            for (int x = 0; x < Width; ++x)
            {
               tiles[x, y].Draw(spriteBatch);
            }
        }
    }



    public void Update(GameTime gameTime, int scrollSpeed, ScrollDirection direction)
    {
        // Update the positions of each of the Background sprites
        foreach (Tile tile in tiles)
        {
            tile.Update(gameTime, new Vector2(0, scrollSpeed), scrollDirection);
        }
    }
}

提前致谢

我现在尝试使用从图形设备传递的视口仅循环通过屏幕上可见的图块进行绘制。我基本上尝试在尝试绘制它们之前获取可以在屏幕上放置的图块的数量,方法是将屏幕的高度除以图块的高度,宽度相同。这工作得很好,它绘制了视点中可见的所有图块。

唯一的问题是它不再绘制从视口之外开始的任何图块,因此即使在更新图块被移动到视口中时,它们也不会被绘制,因为循环使用它们的原始位置。我想不出在不遍历所有图块的情况下解决此问题的方法:-(

由于一个级别可能很大,因此循环遍历所有图块以仅绘制屏幕中的内容是非常低效的。

任何建议将不胜感激。

这是更新的平局:

    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);
            }
        }
    }
4

2 回答 2

1

您需要有关相机的信息。如果你知道你的相机的中心是什么以及你的屏幕尺寸是多少,你可以有一个这样的绘图调用:

private void DrawTiles(SpriteBatch spriteBatch)
{
    // For each tile position
    for (int y = cameraOffset.Y - screenHeight / 2; y < cameraOffset.Y + (int)Math.Ceiling(screenHeight / 2); ++y)
    {
        for (int x = cameraOffset.X - screenWidth / 2; x < cameraOffset.X + (int)Math.Ceiling(screenWidth / 2); ++x)
        {
           tiles[x, y].Draw(spriteBatch);
        }
    }
}

我使用 Math.Ceiling 的原因是为了掩盖瓷砖是否部分在屏幕上。另一边的 Math.Floor 是隐含的,因为它是整数除法。

请注意,这假定 cameraOffset、screenWidth 和 screenHeight 以图块为单位。如果不是,请适当地转换它们。

于 2013-06-02T16:01:59.900 回答
0

制作名为 WINDOW_WIDTH 和 WINDOW_HEIGHT 的常量来存储窗口的宽度和高度。然后,像您展示的那样绘制瓷砖,但只能使用 WINDOW_WIDTH 和 WINDOW_HEIGHT 值内的瓷砖。您还需要 Tile 类中的 X 和 Y 属性

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)
        {
            if (tiles[x, y].X <= WINDOW_WIDTH &&
                tiles[x, y].X >= 0 &&
                tiles[x, y].Y <= WINDOW_HEIGHT &&
                tiles[x, y].Y >= 0)
            {
                tiles[x, y].Draw(spriteBatch);
            }
        }
    }
}
于 2016-03-20T02:30:37.977 回答