在动画期间获取OpenGL中的鼠标单击坐标?

时间:2019-04-14 01:34:55

标签: c opengl glut

我想制作一个游戏,当有人单击移动的球时,它会破裂。我添加了动画和鼠标单击事件的代码,但是当动画进行时,单击功能不起作用。当我尝试不使用动画时,它可以正常工作。我想知道为什么会这样。

#include<stdio.h> 
#include<GL/glut.h> 
#include<unistd.h>
#include<math.h> 

int x, y;
float mx, my;
float i, j;

void mouse(int button, int state, int mousex, int mousey)
{
    if(button==GLUT_LEFT_BUTTON && state==GLUT_DOWN)
    {
        mx = mousex;
        my = mousey;
        printf("%f %f\n",mx,my);
        glutPostRedisplay();
    }
}

void init() 
{ 
    glClearColor(0.0, 0.0, 0.0, 1.0);
    glColor3f(0.0, 1.0, 0.0); 
    glPointSize(1.0);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0, 1560, 0, 840); 
} 

int randValue()
{
    int i = rand();
    int num = i%1000;
    return num;
}

void blast(int x, int y)
{
    glBegin(GL_POLYGON);
    glColor3f(1.0f,0.0f,0.0f);
    glVertex2i(x-100, y-100);
    glVertex2i(x, y-100);
    glVertex2i(x-22, y-20);
    glVertex2i(x-100, y-30);
    glVertex2i(x-30, y-40);
    glVertex2i(x-150, y-80);
    glVertex2i(x-20, y);
    glVertex2i(x, y-40);
    glVertex2i(x-66, y-125);
    glVertex2i(x-34, y-32);
    glVertex2i(x-32, y-55);
    glVertex2i(x-32, y);
    glVertex2i(x-60, y-57);
    glVertex2i(x-75, y-69);
    glVertex2i(x-100, y);
    glEnd();
    glFlush();
}

void display() 
{
    int j = 0, k = 0, l = 1;
    while(1)
    {
        glClear(GL_COLOR_BUFFER_BIT);

        glColor3f(0.0, 1.0, 0.0);
        glBegin(GL_POINTS);

        for (i = 0;i < 6.29;i += 0.001)
        {
            x = 100 * cos(i);
            y = 100 * sin(i);
            glVertex2i(x / 2 + j, y / 2 + k);
            if((x / 2 + j) >= 1560 || (y / 2 + k) >= 840)
            {
                glEnd();
                glFlush();
                glClear(GL_COLOR_BUFFER_BIT);
                blast(x / 2 + j, y / 2 + k);
                sleep(2);
                j = randValue();
                k = 0;
            }
        }
        j = j + 3;
        k = k + 5;
        glEnd();
        glFlush();
    }
}

int main (int argc, char** argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
    glutInitWindowSize(1360, 768);
    glutInitWindowPosition(0, 0);
    glutCreateWindow("{Project}");
    init();
    glutDisplayFunc(display);
    glutMouseFunc(mouse);
    glutMainLoop();
}

2 个答案:

答案 0 :(得分:3)

您的代码在display函数内部有一个无限循环,因此您永远不要将控件交还给GLUT。 GLUT已经在glutMainLoop内部产生了无限循环。

相反,您只能在display中渲染一个帧,发布glutPostRedisplay并返回:

void display() 
{
    glClear(GL_COLOR_BUFFER_BIT);
    // ... draw the frame here ...

    // for exmaple:
    i += 0.001;
    float x = 100 * cos(i);
    float y = 100 * sin(i);
    glColor3f(0.0, 1.0, 0.0);
    glBegin(GL_POINTS);
    glVertex2f(x, y);
    glEnd();

    glFlush();
    glutPostRedisplay();
}

然后将调用您的mouse函数,您将能够根据需要更新状态。

答案 1 :(得分:1)

这里有两个问题:

  • OpenGL本身不支持输入设备,您通常使用OpenGL来显示信息,但是在显示信息的窗口上附加了其他内容,这使鼠标可以访问。这涉及到知道您正在使用哪个其他环境,该环境会为您提供指向屏幕区域的指示设备。

  • 如果您具有窗口鼠标坐标,则需要在窗口上很好地映射,然后呈现OpenGL输出,但是必须将它们转换回场景中的某个点,但是可能您的球不在那儿。当从表示3D场景的平面图像传递到3D场景中的某个点时,存在一些歧义,因为Z轴上的所有点在2D屏幕中共享相同的屏幕坐标。因此,您必须基于鼠标的窗口坐标从视角(摄像机)追溯到球的可能位置。这是一个几何问题,涉及投影的逆变换,始终是奇异的。

您无需猜测就可以解决此问题,因为您知道球在哪里,所以可以重做使它出现在二维窗口中的变换,然后根据这些坐标比较坐标。 OpenGL可以让您知道它在表示场景时所进行的实际转换,您可以使用它来查看球在屏幕上的表示位置(您不需要为球的每个顶点都进行此操作。例如居中),然后检查您的投篮是否已经足够近以击中球。您还应该考虑Z轴上方的其他物体是否在挡路,这样就不会杀死任何人在墙后。