Движение «2D» камеры в OpenGL / C ++ - PullRequest
1 голос
/ 26 марта 2019

Я проверил все остальные связанные вопросы на этом сайте, но ни одно из решений не помогло мне.Я просто пытаюсь следовать моему прямоугольнику, который перемещается влево и вправо при нажатии клавиш в OpenGL.Вот моя очень простая программа:

/*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*/

Движение клавиатуры работает отлично, однако:

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

внутри моей функции keyboard() ничего не делает.И если я попробую сделать это с GL_PROJECTION, мой экран станет черным.

1 Ответ

3 голосов
/ 26 марта 2019

Прежде всего, обратите внимание, что рисование с помощью glBegin / glEnd последовательностей и набора матриц фиксированных функций устарело с десятилетий. См. конвейер с фиксированными функциями и Legacy OpenGL .


Упростите вещи.

Добавление событий клавиатуры для клавиш вверх и вниз (glutKeyboardFunc / glutKeyboardUpFunc). Эта функция только изменяет скорость игрока. Скорость устанавливается при нажатии кнопки и устанавливается на 0, когда кнопка отпущена:

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

Событие таймера просто меняет положение игрока:

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

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

В draw установлена ​​матрица модели и нарисован прямоугольник:

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

Установить функции обратного вызова в main:

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

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

    // ...
}
...