限制不同计算机上的游戏速度 我用OpenGL和C++来创建一个2D游戏。
我想让游戏在不同的电脑上以相同的速度运行,此时我的游戏在我的桌面上运行的速度比我的笔记本电脑快(即,我的玩家在我的桌面上移动得更快) 有人告诉我QueryPerformanceCounter(),但我不知道如何使用它 我如何使用它,或者有更好/更简单的方法吗 我的显示功能限制不同计算机上的游戏速度 我用OpenGL和C++来创建一个2D游戏。,c++,opengl,performance,C++,Opengl,Performance,我想让游戏在不同的电脑上以相同的速度运行,此时我的游戏在我的桌面上运行的速度比我的笔记本电脑快(即,我的玩家在我的桌面上移动得更快) 有人告诉我QueryPerformanceCounter(),但我不知道如何使用它 我如何使用它,或者有更好/更简单的方法吗 我的显示功能 void display() { static long timestamp = clock(); // First frame will have zero
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();
大多数游戏使用帧时间比例因子。基本上,您可以找到物理和运动设置的帧长度,并将其除以游戏运行时帧的实际长度(1/fps)。这将生成一个标量因子,您可以将该因子乘以运动的变化,以保持所有运动的一致性,同时保持增加FPS带来的好处
一个很好的例子是通常,您希望根据时间增量(即自上一帧以来经过的时间)进行所有游戏性计算。这将使所有机器的速度标准化。除非您需要极高的精度,否则可以使用
clock()
(来自
)获取当前时间戳
例如:
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;
}
}
#包括
空主回路(双三角){
// ...
}
int main(){
大整数频率,最后一个,当前;
双三角洲;
QueryPerformanceFrequency(&freq);
QueryPerformanceCounter(&last);
而(1){
QueryPerformanceCounter(¤t);
delta=(双精度)(current.QuadPart-last.QuadPart)/(双精度)freq.QuadPart;
主回路(三角洲);
last=当前值;
}
}
解决问题的最佳方法是每10毫秒(或类似时间)只更新一次对象的位置,但要尽可能频繁地渲染对象。这被称为“固定时间步长”,因为您只在固定的时间间隔更新游戏状态。这需要将渲染代码与更新代码分离(这是一个好主意)
基本上(在psudoe代码中),您将执行以下操作:
accumulatedTimeSinceLastUpdate = 0;
while(gameIsRunning)
{
accumulatedTimeSinceLastUpdate += timeSinceLastFrame();
while(accumulatedTimeSinceLastUpdate >= 10) // or another value
{
updatePositions();
accumulatedTimeSinceLastUpdate -= 10;
}
display();
}
这意味着,如果您的计算机正在运行super duper fast display(),它将被多次调用,并且会时不时地调用updatePositions()。如果您的计算机更新速度非常慢,则每次调用display()时,可能会多次调用位置
下面是另一本好书(除了梅森·布利尔的):
accumulatedTimeSinceLastUpdate = 0;
while(gameIsRunning)
{
accumulatedTimeSinceLastUpdate += timeSinceLastFrame();
while(accumulatedTimeSinceLastUpdate >= 10) // or another value
{
updatePositions();
accumulatedTimeSinceLastUpdate -= 10;
}
display();
}