OpenGL/C++ 中“2D”相机的移动
Posted
技术标签:
【中文标题】OpenGL/C++ 中“2D”相机的移动【英文标题】:Movement of '2D' camera in OpenGL/C++ 【发布时间】:2019-03-26 11:27:48 【问题描述】:我已经检查了此站点上的所有其他相关问题,但没有一个解决方案对我有用。我只是想跟随我的矩形,它在 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
,它会使我的屏幕变黑。
【问题讨论】:
只是出于好奇,你为什么要学习 20 多年的 API? @Quimby 你的问题让我有点不安。 OpenGL 可能已经过时了,但它已经过时了吗?什么是当代的替代品?到目前为止,我还不是专家,但我认为 opengl 和 directx 是该类别中仅有的两个竞争对手... @Olli OpenGL 绝不过时,但 OP 使用的是 1992 年发布的 1.0 版,现已弃用。此 API 并不真正适合现代 GPU,缺乏许多功能,因此应该使用现代版本 - 通常在 3.3+ 左右。目前最新版本是 2017 年的 4.6。OpenGL 可能会逐渐被 Vulkan 取代,但那是几年后的事了。 【参考方案1】:首先请注意,几十年来,glBegin
/glEnd
序列和固定函数矩阵堆栈的绘图已被弃用。请参阅Fixed Function Pipeline 和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 );
// ...
【讨论】:
谢谢你,兔子。将glLoadIdentity();
移到更新循环之外修复了它。以上是关于OpenGL/C++ 中“2D”相机的移动的主要内容,如果未能解决你的问题,请参考以下文章