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

use*_*185 5 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

这是主要功能:

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

我究竟做错了什么?

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

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);
}
Run Code Online (Sandbox Code Playgroud)

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

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 );
Run Code Online (Sandbox Code Playgroud)

Kos*_*Kos 8

你订单错了.

glutMouseFunc(mouseClicks);
Run Code Online (Sandbox Code Playgroud)

在这里注册单击鼠标时要调用的函数.

if(onMouse == 1) {
Run Code Online (Sandbox Code Playgroud)

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


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


dat*_*olf 5

我究竟做错了什么?

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

进入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();
}
Run Code Online (Sandbox Code Playgroud)

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