C# 如何仅绘制屏幕上可见的平铺(精灵)

C# 如何仅绘制屏幕上可见的平铺(精灵),c#,xna,2d,monogame,side-scroller,C#,Xna,2d,Monogame,Side Scroller,我正在尝试创建一个简单的2d滚动游戏,作为monogame(XNA)中的学习练习。目前,我从文本文件加载平铺信息,创建一个数组(tiles[,]),其中一个平铺对象存储有关平铺写入位置以及调用draw方法时应使用何种纹理的信息。目前,我一次绘制阵列中的每个磁贴,然后简单地更新磁贴的位置,使其在屏幕上移动。显然,一次绘制所有的瓷砖有点痛苦,我认为如果我只绘制屏幕上可见的瓷砖会更好,这样当瓷砖在屏幕上移动时,会绘制更多的瓷砖。我不知道如何最好地做到这一点?我有点不知所措,不知道该怎么画瓷砖。 任何帮

我正在尝试创建一个简单的2d滚动游戏,作为monogame(XNA)中的学习练习。目前,我从文本文件加载平铺信息,创建一个数组(tiles[,]),其中一个平铺对象存储有关平铺写入位置以及调用draw方法时应使用何种纹理的信息。目前,我一次绘制阵列中的每个磁贴,然后简单地更新磁贴的位置,使其在屏幕上移动。显然,一次绘制所有的瓷砖有点痛苦,我认为如果我只绘制屏幕上可见的瓷砖会更好,这样当瓷砖在屏幕上移动时,会绘制更多的瓷砖。我不知道如何最好地做到这一点?我有点不知所措,不知道该怎么画瓷砖。 任何帮助都将不胜感激。 这是我的level类中的draw和update方法-它只是调用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);
        }
    }
}
//
///在标高中绘制每个单独的平铺。
/// 
专用空心抽瓷砖(SpriteBatch SpriteBatch)
{
//对于每个瓷砖位置
对于(int y=0;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)
            {
                tiles[x, y].Draw(spriteBatch);
            }
        }
    }
private void DrawTiles(SpriteBatch SpriteBatch)
{
浮动瓷砖宽度=40;
浮球高度=32;
对于(int y=0;y<(int)数学天花板(mViewport.Height/tileHeight);+y)
{
对于(int x=0;x<(int)数学天花板(mViewport.Width/tileWidth);+x)
{
瓷砖[x,y]。绘制(spriteBatch);
}
}
}

您需要有关相机的信息。如果您知道相机的中心位置和屏幕大小,您可以进行如下抽签:

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);
        }
    }
}
private void DrawTiles(SpriteBatch SpriteBatch)
{
//对于每个瓷砖位置
对于(int y=cameraOffset.y-screenHeight/2;y
我使用Math.天花的原因是,如果屏幕上有部分瓷砖,它将覆盖。另一侧的Math.Floor是隐含的,因为它是整数除法


请注意,这假设cameraOffset、screenWidth和screenHeight是以分幅为单位的。如果不是,请进行适当的转换。

创建名为WINDOW\u WIDTH和WINDOW\u HEIGHT的常量,存储窗口的宽度和高度。然后,按照所示绘制分幅,但仅使用WINDOW\u WIDTH和WINDOW\u HEIGHT值内的分幅。在平铺类中还需要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);
            }
        }
    }
}
private void DrawTiles(SpriteBatch SpriteBatch)
{
浮动瓷砖宽度=40;
浮球高度=32;
对于(int y=0;y<(int)数学天花板(mViewport.Height/tileHeight);+y)
{
对于(int x=0;x<(int)数学天花板(mViewport.Width/tileWidth);+x)
{
如果(平铺[x,y].x=0&&
平铺[x,y].y=0)
{
瓷砖[x,y]。绘制(spriteBatch);
}
}
}
}

再次感谢迈克,我对相机的这个概念有点迷茫。目前我只根据阵列位置定位磁贴,然后根据以下内容更改磁贴的位置:pritebatch.Draw(mSpriteTexture,position*sizeVector,Color.White);你知道我可以看哪些教程来让我了解如何设置摄像头吗?在本例中,摄像头是屏幕的中心,因此只需将其更改为玩家位置或其他“跟随”即可it@Pectus挖掘如果在你的spriteBatch中为世界设置一个矩阵,你可以轻松地变换整个“2d屏幕”。如果您的屏幕为400x400,并且您的相机位于X=0,Y=0,则它将在0,0到400400之间开始渲染所有内容。除非您缩放或旋转它。矩阵相机=矩阵。创建缩放(缩放)*矩阵。创建旋转Z(MathHelper.ToRadians(度))*矩阵。创建平移(位置X,位置Y,0);然后您只需将位置调整到您想要显示的任何位置。现在您可以将对象的位置设置为400,0(未渲染)但是如果你稍微移动一下相机,它就会显示出来。周围有一大堆2D相机的例子。我找不到我自己用过的那个,但这里有一个类似的例子。好吧,我得到了Mike建议的前提,只在屏幕上的瓷砖上循环。我认为这是一个很好的计划。但是我不明白为什么我不能使用视口让它工作-请看我的r对于代码,我提出了一个问题。当我尝试只循环t时,任何想法都将不胜感激