2013-04-19 20 views
5

Jestem początkującym w OpenGL i staram się stworzyć grę, w której jako tło mam surowy obraz. Po uruchomieniu gry wyświetlam ten obraz i chcę go kliknąć, a następnie wyświetlić inny obraz. Próbowałem użyć funkcji glutMouseFunc, ale kiedy próbuję uruchomić program, pojawia się komunikat, że program przestał działać. Oto niektóre części mojego kodu: Mam zmienną globalną onMouse; jeśli kliknę przycisk myszy, zmienna przyjmuje wartość 1 i jeśli ma wartość 1, próbuję załadować drugi obraz.wykrywanie kliknięć myszy w OpenGL C++

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

I to jest główna funkcja:

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

Co robię źle?

EDYCJA Dokonałem pewnych zmian w kodzie, ale obraz w tle nadal się nie zmienia. Oto nowy Główną funkcją:

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); 
} 

I to jest funkcja wyświetlania, w którym mapowanie tekstury quad:

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); 
+0

Twoje pytanie dotyczy GLUT, a nie OpenGL. – derpface

Odpowiedz

7

Masz rozkaz złego.

glutMouseFunc(mouseClicks); 

Tutaj rejestruje się funkcję, która ma zostać wywołana po kliknięciu myszą.

if(onMouse == 1) { 

Natychmiast sprawdzić, czy kliknięto myszą. Niemożliwe jest kliknięcie myszą w krótkim okresie między tymi dwoma liniami, a glutMainLoop nie zostało jeszcze wprowadzone, więc Twój program nie miał nawet szansy na wysłuchanie zdarzeń myszy.


Jeśli chodzi o awarię, nie mogę pomóc w debugowaniu za pomocą kodu, który podałeś. Spróbuj debuggera i sprawdź, która linia powoduje awarię.

+0

Zmieniłem kolejność i teraz mam glutMouseFunc (mouseClicks) pomiędzy funkcjami DisplayFunc() i KeyboardFunc() i po wywołaniu glutMainLoop() Sprawdzam, czy onMouse ma wartość 1; program wciąż nie zmienia obrazu, ale przynajmniej teraz się nie psuje – user1956190

5

Co robię źle?

Oczekujesz, że glutMouseFunc zaczeka na kliknięcie myszą. Nie tak działa GLUT (GLUT nie jest częścią OpenGL BTW). Innym wywoływanym zadaniem zwrotnym jest funkcja rysowania (zwykle nazywana display w programach opartych na GLUT).

Po wejściu do głównej pętli GLUT (glutMainLoop()) zdarzenia użytkownika są przetwarzane i jeśli wymagana jest opcja wyświetlenia na czerwono, wywoływana jest funkcja wyświetlania.

Więc oto co robisz (w uproszczonej Pseudokod)

// 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(); 
} 

Można oczywiście użyć innego rodzaju struktury chcesz przekazać stanu przycisku myszy między częściami programu. Wolę takie maski bitowe. Inne osoby mogą preferować tablice (osobiście nie lubię tablic do zadań takich jak ta, ponieważ nie są tak łatwe do patrzenia w debuggerze, niż proste bitfield).

1

glutMouseFunc rejestruje wywołanie zwrotne: funkcję, która ma zostać wywołana przy określonych zdarzeniach (tutaj zdarzenia myszy).Zdarzenia te są gromadzone przez glutMainLoop, która nie została jeszcze wywołana podczas testowania onMouse.

Inną rzeczą, chociaż nie mogę powiedzieć na pewno, z fragmentu kodu, który podasz, jest to, że lepiej załadować zasoby od początku programu, zamiast czekać na zdarzenie użytkownika, aby to zrobić. Załaduj je najpierw i po prostu zmień texture na dowolny id odpowiadający teksturze, którą chcesz wyświetlić.

Powiązane problemy