我正在使用OpenGL和C++创建一个2D游戏。
我想让游戏在不同的计算机上以相同的速度运行,目前我的游戏在我的台式机上运行得比我的笔记本电脑快(即我的玩家在我的台式机上移动得更快)
有人告诉我QueryPerformanceCounter(),但我不知道如何使用它。
我该如何使用它,或者是否有更好/更简单的方法?
我的显示功能
void display()
{
static long timestamp = clock();
// First frame will have zero delta, but this is just an example.
float delta = (float)(clock() - timestamp) / CLOCKS_PER_SEC;
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
createBackground();
int curSpeed = (player.getVelocity()/player.getMaxSpeed())*100;
glColor3f(1.0,0.0,0.0);
glRasterPos2i(-screenWidth+20,screenHeight-50);
glPrint("Speed: %i",curSpeed);
glRasterPos2i(screenWidth-200,screenHeight-50);
glPrint("Lives: %i",lives);
glRasterPos2i(screenWidth-800,screenHeight-50);
glPrint("Heading: %f",player.getHeading());
for(int i = 0;i<90;i++){
if (numBullets[i].fireStatus == true){
numBullets[i].updatePosition(player);
if (numBullets[i].getXPos() > screenWidth || numBullets[i].getXPos() < -screenWidth || numBullets[i].getYPos() > screenHeight || numBullets[i].getYPos() < -screenHeight ){
numBullets[i].fireStatus = false;
numBullets[i].reset(player);
numBullets[i].~Bullet();
}
}
}
player.updatePosition(playerTex,delta);
glFlush();
timestamp = clock();}
我的Update positiom方法
void Player::updatePosition(GLuint playerTex, float factor){
//draw triangle
glPushMatrix();
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBindTexture(GL_TEXTURE_2D, playerTex);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTranslatef(factor*XPos, factor*YPos, 0.0);
glRotatef(heading, 0,0,1);
glColor3f(1.0,0.0,0.0);
glBegin(GL_POLYGON);
glTexCoord2f(0.0, 1.0); glVertex2f(-40,40);
glTexCoord2f(0.0, 0.0); glVertex2f(-40,-40);
glTexCoord2f(1.0, 0.0); glVertex2f(40,-40);
glTexCoord2f(1.0, 1.0); glVertex2f(40,40);
glEnd();
glDisable(GL_BLEND);
glDisable(GL_TEXTURE_2D);
glPopMatrix();
XPos += speed*cos((90+heading)*(PI/180.0f));
YPos += speed*sin((90+heading)*(PI/180.0f));
}发布于 2010-02-21 03:58:28
通常,您希望基于时间增量执行所有游戏计算,即自上一帧以来经过的时间量。这将使所有机器的速度标准化。除非您想要极高的精度,否则可以使用clock() (来自<ctime>)来获取当前时间戳。
示例:
void main_loop() {
static long timestamp = clock();
// First frame will have zero delta, but this is just an example.
float delta = (float)(clock() - timestamp) / CLOCKS_PER_SEC;
calculate_physics(delta);
render();
timestamp = clock();
}
void calculate_physics(float delta) {
// Calculate expected displacement per second.
applyDisplacement(displacement * delta);
}
void render() {
// Do rendering.
}编辑:如果你想要更高的精度,你应该使用你的操作系统计时器功能。在Windows上,最精确的方法是使用QueryPerformanceCounter()。示例
#include <windows.h>
void main_loop(double delta) {
// ...
}
int main() {
LARGE_INTEGER freq, last, current;
double delta;
QueryPerformanceFrequency(&freq);
QueryPerformanceCounter(&last);
while (1) {
QueryPerformanceCounter(¤t);
delta = (double)(current.QuadPart - last.QuadPart) / (double)freq.QuadPart;
main_loop(delta);
last = current;
}
}发布于 2010-02-21 03:55:44
大多数游戏都使用帧时间缩放因子。基本上,你找到你的物理和移动设置的帧的长度,并将其除以游戏正在运行的帧的实际长度(1/fps)。这产生了一个标量因子,您可以将其乘以移动的变化,以保持所有移动的一致性,同时保持增加FPS的好处。
here.就是一个很好的例子
发布于 2010-02-23 21:53:10
问题的最佳解决方案是每10毫秒(或类似的情况)仅更新一次对象的位置,但应尽可能频繁地渲染对象。这就是所谓的“固定时间步长”,因为你只能以固定的时间间隔更新游戏状态。这要求您将呈现代码与更新代码解耦(这无论如何都是一个好主意)。
基本上(在psudoe代码中),你会这样做:
accumulatedTimeSinceLastUpdate = 0;
while(gameIsRunning)
{
accumulatedTimeSinceLastUpdate += timeSinceLastFrame();
while(accumulatedTimeSinceLastUpdate >= 10) // or another value
{
updatePositions();
accumulatedTimeSinceLastUpdate -= 10;
}
display();
}这意味着,如果您的计算机正在运行超级复制程序,快速显示()将被调用很多次,并且会时不时地调用updatePositions()。如果您的计算机速度极慢,则每次调用display()时,可能会多次调用updatePositions。
这是另一个很好的读物(除了Mason Blier的):
https://stackoverflow.com/questions/2303440
复制相似问题