简体   繁体   中英

Movement of '2D' camera in OpenGL/C++

I've checked every other related question on this site but none of the solutions have worked for me. I'm simply trying to follow my rectangle, which moves left and right with key presses in OpenGL. Here's my very simple program:

/*Begin useful backend functions/vars*/
/*************************************/
//Window size and refresh rate (60 fps)
int width = 500;
int height = 500;
int interval = 1000 / 60;

//Used to draw rectangles
void drawRect(float x, float y, float width, float height) {
    glBegin(GL_QUADS);
    glVertex2f(x, y);
    glVertex2f(x + width, y);
    glVertex2f(x + width, y + height);
    glVertex2f(x, y + height);
    glEnd();
}
/***********************************/
/*End useful backend functions/vars*/


/*Game vars*/
/***********/
//keycodes
#define keyA 0x41
#define keyD 0x44

//player
int playerWidth = 30;
int playerHeight = 50;
int playerSpeed = 3;

//player starting position
float playerX = width / 2;
float playerY = 25.0f;
/***************/
/*End game vars*/


/*Game specific functions*/
/*************************/
void keyboard() {
    //Move player (and camera) on key presses
    if (GetAsyncKeyState(keyA)) {
        playerX -= playerSpeed;
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        glTranslatef(-playerSpeed,0,0);
    }
    if (GetAsyncKeyState(keyD)) {
        playerX += playerSpeed;
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        glTranslatef(playerSpeed, 0, 0);
    }
}
/********************/
/*End game functions*/


/*Draw and update for window*/
/****************************/
void draw() {
    //Initialliy clear
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();

    //Draw player
    drawRect(playerX, playerY, playerWidth, playerHeight);

    //Swap buffers to end
    glutSwapBuffers();
}

void update(int value) {
    // input handling
    keyboard();  

    // Call update() again in 'interval' milliseconds
    glutTimerFunc(interval, update, 0);

    // Redisplay frame
    glutPostRedisplay();
}
/*****************/
/*End draw/update*/


/*Main function*/
/***************/
int main(int argc, char** argv) {
    // initialize opengl (via glut)
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(width, height);
    glutCreateWindow("My Game");

    // Register callback functions   
    glutDisplayFunc(draw);
    glutTimerFunc(interval, update, 0);

    // setup scene to be 2d
    glViewport(0, 0, width, height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0, width, 0, height);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    //set draw color to white
    glColor3f(1.0f, 1.0f, 1.0f);

    //start the whole thing
    glutMainLoop();
    return 0;
}
/*************/
/*End of main*/

The keyboard movement works perfectly, however:

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(-playerSpeed,0,0);

inside my keyboard() function, does nothing. And if I try it with GL_PROJECTION , it turns my screen black.

First of all note, that drawing by glBegin / glEnd sequences and the fixed function matrix stack is deprecated since decades. See Fixed Function Pipeline and Legacy OpenGL .


Simplify things.

Add a the keyboard events for key up and down ( glutKeyboardFunc / glutKeyboardUpFunc ). This functions only modifies the speed of the player. The speed is set when a button is pressed and is set 0, when a button is release:

int playerSpeed = 0;
void keyboardDown(unsigned char key, int x, int y)
{
    if (key == 'a')
        playerSpeed -= 3;
    else if (key == 'd')
        playerSpeed = 3;
}

void keyboardUp( unsigned char key, int x, int y )
{
    playerSpeed = 0;
}

The timer event just modifies the position of the player:

void update(int value)
{
    playerX += playerSpeed;

    glutTimerFunc(interval, update, 0);
    glutPostRedisplay();
}

In draw the model matrix is set and the rectangle is drawn:

void draw()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glTranslatef(playerX, playerY, 0);

    //Draw player
    drawRect(0, 0, playerWidth, playerHeight);

    //Swap buffers to end
    glutSwapBuffers();
}

Set the callback functions in main :

int main(int argc, char** argv) 
{
    // ...

    glutDisplayFunc(draw);
    glutTimerFunc(interval, update, 0);
    glutKeyboardFunc( keyboardDown );
    glutKeyboardUpFunc( keyboardUp );

    // ...
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM