等距耕地图滚动

时间:2011-08-08 18:22:17

标签: opengl scroll sdl tiles

我这里有问题。我现在正在寻找这个问题的答案,试图自己解决,但没有结果。这个问题可能已被问过很多次了,但无论我发现什么,我总会发现一些东西,这对我来说并不清楚。 所以: 我正在使用SDL + OpenGL编写2D游戏。游戏以等轴测视图显示。玩家可以看到由瓷砖组成的地图,比如一个15x15的瓷砖(2D数组)。它看起来像这样: http://i.imgur.com/PVJe4.png

X和Y是每个图块的索引,但除此之外,这些图块具有自己的X和Y坐标(北顶点,用[0] [0]图块标记为绿点),其中它们正在绘制。

我的问题是,我想为此添加滚动。如果这张地图是100x100的瓷砖,那么绘制的速度非常慢,因为所有的瓷砖都是在屏幕外绘制的。我不希望它被完成。

让我们看看,例如,这个: http://imgur.com/vo3wg

蓝色矩形是我的屏幕(800x600,不可调整大小)。整体地图尺寸为8000x6000,并在屏幕上绘制图块。我知道,我只需绘制那些标记为绿色的瓷砖,但我的问题是:

如何确定必须绘制哪些图块(我的意思是指哪些图块)?

我感谢所有帮助我的尝试。

3 个答案:

答案 0 :(得分:3)

  

但无论我使用什么技术,它都只是......不能留下来呈现某些内容,而不会在屏幕上显示。

为什么不呢?屏幕外的整个三角形都会被剔除,所以你失去的就是顶点传输和转换时间。是的,您应该采取合理的措施确保您不会发送您可以轻松剔除的内容,但由于您只是绘制一个简单的2D平铺图,因此不会出现性能问题。即使是低端硬件。

这就是过早优化错误的原因。因为你花时间担心一些根本不是问题的事情。当某些东西实际上很慢时,而不是在它可能很慢的时候进行优化。

通常,您应该选择要绘制的图块组。如果有一个可见,则绘制所有这些。这样,你就不会花很多时间选择专门绘制的瓷砖。然后,您可以优化传输数据(即:将每个组放入缓冲区对象),然后一次性绘制整个组。

答案 1 :(得分:1)

我正在回答我自己,因为我不能发布超过2个链接(因为我是新的),而且我无法发布任何图像。

我做了一些测试:

对于100x100它运行良好,对于150x150,对于200x200它下降到地面,对于500x500它完全是灾难: http://imgur.com/msAx4l&EJ9Qw&iKXFZ&ybFt0 (画廊中的4个屏幕)

好吧,我正在考虑解决方案,不需要任何检查,只是一些数学方程式。 例如,在我的其他游戏(很久以前写过)中使用squre tile而不是diamond,确定绘制tile的索引非常简单。它看起来像这样: http://i.imgur.com/y9KUv.png

绘制程序:

//CameraXposition and CameraYposition is position of left-top corner of camera on map.
//Single tile height and width is 100, so if CameraXposition is 1456, then I start drawing from
//tile with index of 14 ((int)(1456/100) == 14).
//CAMERA_WIDTH is 800 and CAMERA_HEIGHT is 600 (screen resolution).
for(int x = (int)CameraXposition/100; x < ((CameraXposition+CAMERA_WIDTH)/100); ++x)
{
    for(int y = (int)CameraYposition/100; y < ((CameraYposition+CAMERA_HEIGHT)/100); y++)
    {
        //Draw(tiles[x][y]);
    }
}

在等轴测视图中,它不是那么简单,但我不知道如何确定这个起始索引和区块范围。

这是我目前的绘图代码:

void GraphicEngine::Render(Map &m)
{
    //camX and camY isn't coordinates of camera, they are coordinates of
    //starting point (everything is drawed according to that point)
    //it changes as I move mouse.
    //zoomFactor is basically a zoom variable, it's float and its minimum is 0.5 and maximum is 1.5.
    //It changes as I scroll my mousewheel. The smaller it is, the smaller is everything that's drawed,
    //so more tiles can be drawed on screen (becouse they are smaller) 
    //Not very good, but works.
    glTranslatef(camX*zoomFactor, camY*zoomFactor, 0);
    glBindTexture(GL_TEXTURE_2D, textures[0]);
    glBegin(GL_QUADS);
        for(int i = 0; i < m.get_width(); ++i)
        {
            for(int j = m.get_height()-1; j>=0; --j)
            {
                glTexCoord2f(0, 0);
                glVertex3f((m.get_fields()[i][j]->get_pX()-30)*zoomFactor, (m.get_fields()[i][j]->get_pY()+15)*zoomFactor, 0);
                glTexCoord2f(1, 0);
                glVertex3f((m.get_fields()[i][j]->get_pX())*zoomFactor, (m.get_fields()[i][j]->get_pY())*zoomFactor, 0);
                glTexCoord2f(1, 1);
                glVertex3f((m.get_fields()[i][j]->get_pX()+30)*zoomFactor, (m.get_fields()[i][j]->get_pY()+15)*zoomFactor, 0);
                glTexCoord2f(0, 1);
                glVertex3f((m.get_fields()[i][j]->get_pX())*zoomFactor,( m.get_fields()[i][j]->get_pY()+30)*zoomFactor, 0);
            }
        }
    glEnd();
    glLoadIdentity();
}

答案 2 :(得分:0)

我会在渲染全部和检查每个拼贴之间选择折衷解决方案。

在屏幕坐标中找到角落瓷砖。这将为您提供可见瓷砖的最小和最大X:Y位置。现在只渲染这些边界内的那些图块。 GPU将剪切看不见的图块,但您不需要发送所有8000x6000图块来渲染,但只需要发送一部分。

如上所述,过早的优化是错误的,所以除非你的地图至少是800x600的瓷砖,否则我会先尝试在其他地方搜索瓶颈。例如。将纹理按照纹理分配到显示列表或VBO似乎是一个更好的主意。