如何只绘制在屏幕上可见的贴图(精灵)

本文关键字:精灵 绘制 屏幕 | 更新日期: 2023-09-27 18:16:41

我正在尝试创造一个简单的2d滚动游戏作为学习练习在一夫一妻制(XNA)。目前,我从文本文件中加载贴图信息,创建一个数组(tiles[,]),其中包含一个tile对象,用于存储关于在哪里写入贴图以及在调用draw方法时应该使用什么纹理的信息。目前,我一次绘制数组中的每个贴图,然后简单地更新贴图的位置,使其在屏幕上移动。显然,一次画出所有的贴图有点痛苦,我认为如果我只画屏幕上可见的贴图会更好,这样当贴图在屏幕上移动时,就会画出更多的贴图。我不知道怎么做最好?我有点不知所措,我怎么知道应该画什么瓷砖。任何帮助都将非常感激。下面是我在关卡类中的绘制和更新方法——它只是调用Tile类中的方法来绘制/更新位置。

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

Thanks in advance

我现在尝试只循环通过屏幕上可见的瓷砖来绘制,使用从图形设备传递的视口。在尝试绘制它们之前,我基本上会尝试获得屏幕上可以容纳的瓷砖数量,方法是将屏幕的高度除以瓷砖的高度,宽度也是如此。这工作得很好,它绘制了视点中可见的所有瓷砖。

唯一的问题是它不再绘制任何开始于视口之外的贴图,所以即使在更新贴图被移动到视口中,它们也不会被绘制,因为循环使用它们的原始位置。我想不出一种方法来解决这个问题,而不是通过所有的瓷砖循环:-(

)

因为关卡可能很大,所以循环遍历所有贴图而只绘制屏幕上的内容是非常低效的。

如有任何建议,不胜感激。

这是更新后的图纸:

    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调用:

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

我用数学的原因。如果瓷砖部分在屏幕上,天花板将被覆盖。的数学。另一边的底数是隐含的,因为它是整数除法。

注意,这里假设cameraOffset, screenWidth和screenHeight都是以tile为单位的。如果不是,适当地转换它们。

创建名为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);
            }
        }
    }
}