如何检查GLUT中是不是未按下键?

Posted

技术标签:

【中文标题】如何检查GLUT中是不是未按下键?【英文标题】:How to check if key not pressed in GLUT?如何检查GLUT中是否未按下键? 【发布时间】:2021-05-27 17:53:07 【问题描述】:

我在 OpenGL 中制作游戏,现在我的相机出现错误:

如果我按shift+lshift+k(移动相机),相机将一直移动,直到我按下另一个键。

要测试我的相机,请在 if 语句中的 playerCameraFunc() 函数之后的显示函数中添加 createKillerBlock(x, y)(例如,createKillerBlock(20, 20))。

这是我的代码:

#include <stdbool.h>

#include <GL/glut.h>

#define WINDOW_X 1920
#define WINDOW_Y 1080

#define DEFAULT_PLAYER_SPAWN_X 3.0
#define DEFAULT_PLAYER_SPAWN_Y 3.0

#define DEFAULT_CAMERA_X 0.0
#define DEFAULT_CAMERA_Y 0.0

#define UNKILLABLE_LOCATION 1.01

bool isGameStart = false;

int shiftLPresses = 0;
int shiftKPresses = 0;
int shiftXPresses = 0;
int shiftCPresses = 0;

char pressedKey1, pressedKey2;

float blockSize = 10;

float playerX = DEFAULT_PLAYER_SPAWN_X;
float playerY = DEFAULT_PLAYER_SPAWN_Y;

float playerR = 255;
float playerG = 255;
float playerB = 255;

float playerMoveSpeed = 0.7;

float cameraX = DEFAULT_CAMERA_X;
float cameraY = DEFAULT_CAMERA_Y;

float cameraMoveSpeed = 7.1;

float killerBlockX = UNKILLABLE_LOCATION;
float killerBlockY = UNKILLABLE_LOCATION;

float killerBlockR = 255;
float killerBlockG = 0;
float killerBlockB = 0;

void gameMenu()

    if (isGameStart == false)
    
        glBegin(GL_LINES);
        glColor3f(1.0, 1.0, 1.0);
        glVertex2f(-0.2, -0.2);
        glVertex2f(0.2, -0.2);
        glVertex2f(0.2, -0.2);
        glVertex2f(0.2, 0.2);
        glVertex2f(0.2, 0.2);
        glVertex2f(-0.2, 0.2);
        glVertex2f(-0.2, 0.2);
        glVertex2f(-0.2, -0.2);
        glEnd();
        glBegin(GL_POLYGON);
        glVertex2f(-0.1, -0.1);
        glVertex2f(0.1, 0.0);
        glVertex2f(-0.1, 0.1);
        glEnd();
    


void startGame()

    isGameStart = true;


void spawnPlayer()

    glBegin(GL_POLYGON);
    glColor3f(playerR / 255, playerG / 255, playerB / 255);
    glVertex2f(-1.0 + (playerX * (blockSize / WINDOW_X)), -1.0 + (playerY * (blockSize / WINDOW_Y)));
    glVertex2f(-1.0 + (playerX * (blockSize / WINDOW_X) + (blockSize / WINDOW_X)), -1.0 + (playerY * (blockSize / WINDOW_Y)));
    glVertex2f(-1.0 + (playerX * (blockSize / WINDOW_X) + (blockSize / WINDOW_X)), -1.0 + (playerY * (blockSize / WINDOW_Y) + (blockSize / WINDOW_Y)));
    glVertex2f(-1.0 + (playerX * (blockSize / WINDOW_X)), -1.0 + (playerY * (blockSize / WINDOW_Y) + (blockSize / WINDOW_Y)));
    glEnd();


void playerCameraFunc()

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glTranslatef(cameraX * (blockSize / WINDOW_X), cameraY * (blockSize / WINDOW_Y), 0);


void killPlayer()

    isGameStart = false;
    pressedKey1 = '\0';
    pressedKey2 = '\0';
    playerX = DEFAULT_PLAYER_SPAWN_X;
    playerY = DEFAULT_PLAYER_SPAWN_Y;
    cameraX = DEFAULT_CAMERA_X;
    cameraY = DEFAULT_CAMERA_Y;
    glutPostRedisplay();


void playerKillFunc()

    if (playerX >= killerBlockX - 1.0 & playerY >= killerBlockY - 1.0 & playerX < killerBlockX + 1.0 & playerY <= killerBlockY + 1.0)
    
        if (killerBlockX != UNKILLABLE_LOCATION & killerBlockY != UNKILLABLE_LOCATION)
        
            killPlayer();
        
    


void createKillerBlock(int x, int y)

    killerBlockX = x;
    killerBlockY = y;
    glBegin(GL_POLYGON);
    glColor3f(killerBlockR / 255, killerBlockG / 255, killerBlockB / 255);
    glVertex2f(-1.0 + (x * (blockSize / WINDOW_X)), -1.0 + (y * (blockSize / WINDOW_Y)));
    glVertex2f(-1.0 + (x * (blockSize / WINDOW_X) + (blockSize / WINDOW_X)), -1.0 + (y * (blockSize / WINDOW_Y)));
    glVertex2f(-1.0 + (x * (blockSize / WINDOW_X) + (blockSize / WINDOW_X)), -1.0 + (y * (blockSize / WINDOW_Y) + (blockSize / WINDOW_Y)));
    glVertex2f(-1.0 + (x * (blockSize / WINDOW_X)), -1.0 + (y * (blockSize / WINDOW_Y) + (blockSize / WINDOW_Y)));
    glEnd();
    playerKillFunc();


void timer1()

    glutTimerFunc(1000 / 60, timer1, 0);
    switch (pressedKey1)
    
        case 'w':
            if (isGameStart == true)
            
                playerY += playerMoveSpeed / (60 * (shiftXPresses + 1) / (shiftCPresses + 1));
            
            break;
        case 'a':
            if (isGameStart == true)
            
                playerX -= playerMoveSpeed / (60 * (shiftXPresses + 1) / (shiftCPresses + 1));;
            
            break;
        case 's':
            if (isGameStart == true)
            
                playerY -= playerMoveSpeed / (60 * (shiftXPresses + 1) / (shiftCPresses + 1));
            
            break;
        case 'd':
            if (isGameStart == true)
            
                playerX += playerMoveSpeed / (60 * (shiftXPresses + 1) / (shiftCPresses + 1));
            
            break;
    
    glutPostRedisplay();


void timer2()

    glutTimerFunc(1000 / 60, timer2, 0);
    switch (pressedKey2)
    
        case 76:
            if (isGameStart == true)
            
                cameraX -= cameraMoveSpeed / (60 * (shiftLPresses + shiftKPresses + 1));
                playerX += cameraMoveSpeed / (60 * (shiftLPresses + shiftKPresses + 1));
            
            break;
        case 75:
            if (isGameStart == true)
            
                cameraX += cameraMoveSpeed / (60 * (shiftKPresses + shiftLPresses + 1));
                playerX -= cameraMoveSpeed / (60 * (shiftKPresses + shiftLPresses + 1));
            
            break;
    
    glutPostRedisplay();


void display()

    glClear(GL_COLOR_BUFFER_BIT);
    gameMenu();
    if (isGameStart == true)
    
        spawnPlayer();
        playerCameraFunc();
    
    glFlush();


void keyboard(unsigned char key, int x, int y)

    switch (key)
    
        case 'w':
            if (isGameStart == true)
            
                pressedKey1 = 'w';
                pressedKey2 = '\0';
                timer1();
            
            break;
        case 'a':
            if (isGameStart == true)
            
                pressedKey1 = 'a';
                pressedKey2 = '\0';
                timer1();
            
            break;
        case 's':
            if (isGameStart == true)
            
                pressedKey1 = 's';
                pressedKey2 = '\0';
                timer1();
            
            break;
        case 'd':
            if (isGameStart == true)
            
                pressedKey1 = 'd';
                pressedKey2 = '\0';
                timer1();
            
            break;
        case 76:
            if (isGameStart == true)
            
                shiftLPresses += 1;
                pressedKey2 = 76;
                timer2();
            
            break;
        case 75:
            if (isGameStart == true)
            
                shiftKPresses += 1;
                pressedKey2 = 75;
                timer2();
            
            break;
        case 88:
            if (isGameStart == true)
            
                shiftXPresses += 1;
                pressedKey2 = '\0';
                timer1();
            
            break;
        case 67:
            if (isGameStart == true)
            
                shiftCPresses += 1;
                pressedKey2 = '\0';
                timer1();
            
            break;
        case 13:
            if (isGameStart == false)
            
                startGame();
                timer1();
            
            break;
        default:
            pressedKey2 = '\0';
    
    glutPostRedisplay();


int main(int argc, char **argv)

    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE);
    glutCreateWindow("OpenAttack1");
    glutFullScreen();
    glutDisplayFunc(display);
    glutKeyboardFunc(keyboard);
    glutSetCursor(GLUT_CURSOR_NONE);
    glutMainLoop();

编辑

如果按下shift+lshift+k 键,我想移动相机,但如果未按下shift+lshift+k,则停止移动相机。

【问题讨论】:

你为什么在playerCameraFunc()之前调用spawnPlayer() 我尝试在playerCameraFunc() 之后拨打spawnPlayer()。但什么都没有改变。 您正在增加名称为shiftKPresses 的变量,但我看不到它们在哪里减少或设置为零。我猜这就是事情失控的原因。 @TimRandall 我认为您没有完全阅读我的代码。你读过吗?这个 (cameraX -= cameraMoveSpeed / (60 * (shiftLPresses + shiftKPresses + 1));) 行? @TimRandall 我的问题不是速度。我的问题是除非我按另一个键,否则相机不会停止移动。 【参考方案1】:

升级到 GLUT 4+ 实现,例如 FreeGLUT 并注册 glutKeyboardUpFunc()/glutSpecialUpFunc() 回调以在释放键时获得通知:

3.4.4 Changes to Callbacks

添加了几个新的回调,并且几个特定于 Silicon Graphics 硬件的回调尚未实现。大多数或所有新回调都列在 GLUT 版本 4“glut.h”头文件中,但未将其纳入文档。 新的回调包括常规和特殊的按键释放回调、一个操纵杆回调、一个菜单状态回调(一个参数,不同于具有三个参数的菜单状态回调)、一个窗口状态回调(也一个参数)和一个窗口位置回调。不支持的回调是两个 Tablet 回调。如果用户需要不支持的回调,他应该联系 freeglut 开发团队。

Usage example.

【讨论】:

以上是关于如何检查GLUT中是不是未按下键?的主要内容,如果未能解决你的问题,请参考以下文章

Opengl/Glut 键盘输入问题

如何检查 C# 中是不是正在按下某个键(控制台应用程序)

javaScript 中如何实现 随意按下一个键 ,然后返回按下键上面对应的字符

如何检查按钮是不是被按下

如何检查是不是已在 Ruby 和 Windows 控制台中按下箭头键

如何检查 AVPlayerViewController 快进控制是不是被按下?