I making a game in OpenGL and now, I have a bug in my camera:
shift+l
or shift+k
(move camera), camera will move until I press another key.To test my camera, add createKillerBlock(x, y)
in display function after playerCameraFunc()
function in if
statement (For example, createKillerBlock(20, 20)
).
Here is my code:
#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();
}
Edit
I want to move camera if shift+l
or shift+k
keys pressed, but stop moving camera if shift+l
or shift+k
not pressed.
Upgrade to a GLUT 4+ implementation like FreeGLUT & register a glutKeyboardUpFunc()
/glutSpecialUpFunc()
callback to get notified when a key is released:
Several new callbacks have been added and several callbacks which were specific to Silicon Graphics hardware have not been implemented. Most or all of the new callbacks are listed in the GLUT Version 4 "glut.h" header file but did not make it into the documentation. The new callbacks consist of regular and special key release callbacks, a joystick callback, a menu state callback (with one argument, distinct from the menu status callback which has three arguments), a window status callback (also with one argument), and a window position callback. Unsupported callbacks are the two Tablet callbacks. If the user has a need for an unsupported callback he should contact the freeglut development team.