在OpenGL C ++中检测鼠标点击

时间:2013-04-19 10:26:16

标签: c++ glut

我是OpenGL的初学者,我正在尝试创建一个游戏,其中我有一个原始图像作为背景。当游戏开始时,我显示该图像,我希望能够点击它并在之后显示另一个图像。我尝试使用函数glutMouseFunc但是当我尝试运行程序时,我收到一条消息,说该程序停止工作。 以下是我的代码的一些部分:我有一个全局变量onMouse;如果我单击鼠标按钮,变量的值为1,如果值为1,我会尝试加载第二个图像。

int onMouse;
void mouseClicks(int button, int state, int x, int y) {
    if(button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
        onMouse = 1;
    }
}

这是主要功能:

//load first texture
texture = LoadTextureRAW( "2 Lock screen.raw", TRUE );
glutMouseFunc(mouseClicks);
if(onMouse == 1){
    //load second texture
    texture = LoadTextureRAW( "in_game.raw", TRUE );
}

我做错了什么?

编辑我对代码进行了一些更改,但背景图片仍然没有变化。这是新的主要功能:

glutCreateWindow("Game");
texture = LoadTextureRAW( "2 Lock screen.raw", 1 );
glutDisplayFunc(display);

glutMouseFunc(mouseClicks);
glutKeyboardFunc(key);

glutMainLoop();

if(onMouse == 1){
        texture = LoadTextureRAW( "in_game.raw", 2 );
        glutDisplayFunc(display);
}

这是显示功能,我将纹理映射到四边形:

glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
glClear( GL_COLOR_BUFFER_BIT );

// setup texture mapping
glEnable( GL_TEXTURE_2D );
glBindTexture( GL_TEXTURE_2D, texture );

glPushMatrix();
glBegin( GL_QUADS );
glTexCoord2d(1.0,0.0); glVertex3d(1.0,1.0, 1.0);
glTexCoord2d(0.0,0.0); glVertex3d(-1.0,1.0,1.0);
glTexCoord2d(0.0,1.0); glVertex3d(-1.0,-1.0, -1.0);
glTexCoord2d(1.0,1.0); glVertex3d(1.0,-1.0, 1.0);
glEnd();
glPopMatrix();
glutSwapBuffers();

// free the texture
FreeTexture( texture );

3 个答案:

答案 0 :(得分:7)

订单错误。

glutMouseFunc(mouseClicks);

在此处注册单击鼠标时要调用的函数。

if(onMouse == 1) {

您可以立即检查是否已单击鼠标。在这两行之间的短暂时间内点击鼠标是不可能的,而glutMainLoop还没有输入,所以你的程序甚至没有机会听老鼠事件。


至于崩溃,我只能用你提供的代码来帮助你调试它。请尝试调试器并找到导致崩溃的行。

答案 1 :(得分:5)

  

我做错了什么?

您期望glutMouseFunc等待鼠标点击。这不是GLUT的工作原理(GLUT不是OpenGL BTW的一部分)。要注册的另一个回调是绘图功能(在基于GLUT的程序中通常称为display)。

进入GLUT主循环(glutMainLoop()调用)后,将处理用户事件,如果请求重新显示,则调用显示函数。

所以这就是你所做的(简化伪代码)

// Define bitmasks for mouse status, we assume mice have less than 17 buttons
#define MB_LEFT   0
#define MB_MIDDLE 1
#define MB_RIGHT  2
#define LMB_PRESSED (1<<0)
#define MMB_PRESSED (1<<1)
#define RMB_PRESSED (1<<2)
#define LMB_CLICKED (1<<16)
#define MMB_CLICKED (1<<17)
#define RMB_CLICKED (1<<18)
#define MB_PRESSED(state, button) (1<<(button))
#define MB_CLICKED(state, button) (1<<((button)+16)))
#define MB_MASK_PRESSED 0x0000ffffL
#define MB_MASK_CLICKED 0xffff0000L

uint32_t mouse_status = 0;

void onMouseButton(int button, int state, int x, int y)
{
    int b;
    switch(button) {
    case GLUT_LEFT_BUTTON:   b=MB_LEFT;   break;
    case GLUT_MIDDLE_BUTTON: b=MB_MIDDLE; break;
    case GLUT_RIGHT_BUTTON:  b=MB_RIGHT;  break;
    }

    if(mouse_status & MB_PRESSED(b) && GLUT_UP == state) {
        mouse_status |= MB_CLICKED(b);
    }
    if( !(mouse_status & MB_PRESSED(b)) && GLUT_DOWN == state) {
        mouse_status = (mouse_status & ~(0L | MB_CLICKED(b))) | MB_PRESSED(b);
    }

    glutPostRedisplay();
}

void display(void)
{
    if(mouse_status & MB_CLICKED(MB_LEFT)) {
        /* do something */
        …

        /* clear the click flag */
        mouse_status &= ~MB_MASK_CLICKED;
    }
}

int main(…)
{
    …
    glutCreateWindow(…);
    glutDisplayFunc(display);
    glutMouseFunc(onMouseButton);

    glutMainLoop();
}

您当然可以使用任何其他类型的结构来在程序部件之间传递鼠标按钮状态。我更喜欢这种位掩码。其他人可能更喜欢数组(我个人不喜欢像这样的任务的数组,因为它们在调试器中看起来不像简单的位域那么容易。)

答案 2 :(得分:1)

glutMouseFunc注册一个回调函数:一个在特定事件(这里是鼠标事件)上调用的函数。这些事件由glutMainLoop收集,在您测试onMouse时尚未调用。

另一件事,虽然我无法从你提供的小代码摘录中确定,但是你最好从程序开始加载资产,而不是等待用户事件来完成。首先加载它们,然后只需将texture更改为与您希望显示的纹理对应的id。