将世界保持在视口范围内

Keep world within viewport bounds

本文关键字:视口 范围内 世界      更新时间:2023-10-16

我目前正在尝试创建一个2D侧滚动,我目前有我的"世界"绘图(一个大的白色盒子暂时),但我不能找出世界地图的边缘和视口的边缘之间的任何关系,以确保视口总是完全被地图覆盖。

我的基本世界绘制代码是:

void drawTiles(void)
{
    for (int i = 0; i < 50; i++)
    {
        for (int j = 0; j < 500; j++) 
        {           
            glPushMatrix();
            glTranslatef(j, -i, 0);
            glBegin (GL_QUADS);
            glTexCoord2d(0.0, 0.0);
            glVertex3f(0.0, 0.0, 0.0);
            glTexCoord2d(1.0, 0.0);
            glVertex3f(1.0, 0.0, 0.0);
            glTexCoord2d(1.0, 1.0);
            glVertex3f(1.0, 1.0, 0.0);
            glTexCoord2d(0.0, 1.0);
            glVertex3f(0.0, 1.0, 0.0);
            glEnd();
            glPopMatrix();
        }
    }
}
void display(void)
{
    glClearColor(0.0, 0.0, 0.0, 1.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity(); 
    glEnable(GL_TEXTURE_2D);
    glPushMatrix();
    glTranslatef(camX, camY, -20); //translate back a bit to view the map correctly (our camera)
    drawTiles(); //draw our tiles
    glPopMatrix();
    glutSwapBuffers();
}
void reshape(int w, int h)
{
    glViewport(0, 0, (GLsizei)w, (GLsizei)h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(60, (GLfloat)w / (GLfloat)h, 1.0, 100.0);
    glMatrixMode(GL_MODELVIEW);
}
void keyboard(unsigned char key, int x, int y)
{
    switch(key)
    {
    case 'w':
        camY -= 0.25;
    break;
    case 's':
        camY += 0.25;
    break;
    case 'a':
        camX += 0.25;
    break;
    case 'd':
        camX -= 0.25;
    break;
    }
}

我该如何确保当我使用方向键和视口调整大小时,我不会超越地图的界限(目前为500x50块)?

如果你有一个平面场景(仅限2D),那么使用正交投影变换就足够了。投影变换决定了相机的参数。在当前状态下(使用透视投影),您有一个通常的针孔相机,垂直开口角度为60°。

一个正射影是由它的边定义的。假设你想让相机"看到"向左2个单位,向右3个单位,向上1个单位,向下4个单位。这是可能的,尽管在您的情况下可能不合理。

当前的透视相机上下"看到"大约11.5个单位。相应的宽度可以从窗口尺寸计算(我们不想拉伸图像)。因此,使用以下内容代替gluPerspective:

float halfHeight = 11.5f;
float halfWidth = halfHeight * (GLfloat)w / (GLfloat)h; //based on window aspect ratio
glOrtho(-halfWidth, halfWidth, halfHeight, -halfHeight, -1, 1);

如果要改变可见区域,只需调整halfHeight即可。-11为znear和zfar平面。这些平面之间的一切都是可见的。其他的都会被切断。但是因为你只有2D内容,所以这应该是不相关的。

在对glTranslatef(camX, camY, -20);的调用中,将z坐标设置为0。这是不需要的,因为我们有一个正射影视图。

现在,如果您想检查映射是否仍然可见,请执行以下操作。我将展示一个检查左右边界的例子。垂直的情况类似:

//The camera can see from camX-halfWidth to camX+halfWidth
//You might want to make halfWidth and halfHeight class variables
float leftMapBoundary = 0;
float rightMapBoundary = 500;
//the camera must be 
//  * at least halfWidth right of the left boundary and 
//  *  at least halfWidth left of the right one:
if(camX < leftMapBoundary + halfWidth)
    camX = leftMapBoundary + halfWidth;
if(camX > rightMapBoundary - halfWidth)
    camX = rightMapBoundary - halfWidth;

在键盘功能的switch之后添加代码,或者当您移动相机时。