Java 限制我的游戏的FPS

Java 限制我的游戏的FPS,java,frame-rate,Java,Frame Rate,好的,我正在做一个小游戏,我需要限制我的FPS,因为当我在我速度非常快的电脑上玩的时候,我有大约850 FPS,游戏会变得非常快,当我切换到我的旧电脑时,它会慢很多,所以我需要限制我的FPS来获得正确的效果。如何限制我的FPS? 我的主要游戏循环: public void startGame(){ initialize(); while(true){ drawScreen(); drawBuffer(); plyMove()

好的,我正在做一个小游戏,我需要限制我的FPS,因为当我在我速度非常快的电脑上玩的时候,我有大约850 FPS,游戏会变得非常快,当我切换到我的旧电脑时,它会慢很多,所以我需要限制我的FPS来获得正确的效果。如何限制我的FPS? 我的主要游戏循环:

    public void startGame(){
    initialize();
    while(true){
        drawScreen();
        drawBuffer();
        plyMove();

        //FPS counter
        now=System.currentTimeMillis(); 
        framesCount++; 
        if(now-framesTimer>1000){
            framesTimer=now; 
            framesCountAvg=framesCount; 
            framesCount=0; 
        }

        try{
            Thread.sleep(14);
        }catch(Exception ex){}
    }
}
我如何画屏幕,以及画所有其他东西,球员,球等等。 顺便说一句,这个游戏是乒乓球翻拍的

    public void drawBuffer(){
    Graphics2D g = buffer.createGraphics();
    g.setColor(Color.BLACK);
    g.fillRect(0,0,600,500);
    g.setColor(Color.GREEN);
    g.fillRect(ply1.getX(),ply1.getY(),ply1.getWidth(),ply1.getHeight());
    g.setColor(Color.RED);
    g.fillRect(ply2.getX(),ply2.getY(),ply2.getWidth(),ply2.getHeight());
    g.setColor(Color.WHITE);
    g.fillOval(ball1.getX(),ball1.getY(),ball1.getWidth(),ball1.getHeight());
    g.drawString("" + framesCountAvg,10,10);
}

public void drawScreen(){
    Graphics2D g = (Graphics2D)this.getGraphics();
    g.drawImage(buffer,0,0,this);
    Toolkit.getDefaultToolkit().sync();
    g.dispose();
}
一种方法是使用

try {
    Thread.sleep(20);
} catch(InterruptedException e) {}

在主循环的末尾。根据您的需要调整数字。

不要限制您的FPS,而是在FPS较高时,使游戏不会进行得太快


假设您有代码在每帧中执行某些操作,例如,如果按下按钮,则向前移动角色。相反,您要做的是根据自上一帧以来经过的时间量向前移动角色。

这听起来像是您的显示器与游戏引擎绑定在一起。确保这两个连接已断开。无论帧速率是多少,您都希望游戏以相同的速度运行。如果您的快速计算机重新绘制屏幕的速度更快,那么如果引擎使游戏以恒定速度进行,这是正常的。

如上所述,您需要在游戏核心的某个位置将显示循环与更新循环分开,可能有类似的情况

while (1)
{
    drawscene();
    update();
}
在更新中,您将时间提前一个固定的量,例如0.17秒。如果以60fps的速度绘图,则动画将实时运行,以850fps的速度,所有速度都将加快14倍(0.17*850),为防止出现这种情况,您应该使更新时间依赖于此。e、 g

elapsed = 0;
while (1)
{
   start = time();
   update(elapsed); 
   drawscene();
   sleep(sleeptime);
   end = time();

   elapsed = end - start;
}

描述我在评论中的意思。在您的方法中
plyMove()我怀疑有类似

plyMove() {
    ply1.x += amountX;
    ply1.y += amountY;
}
而是根据经过的时间进行移动

plyMove(double timeElapsed) {
    ply1.x += amountX * timeElapsed;
    ply1.y += amountY * timeElapsed;
}
从主循环内的时差计算
timeappeased
,并相应地缩放它以获得一个像样的运动

double timePrev = System.currentTimeMillis();
while(true) {
    double timeNow = System.currentTimeMillis();
    double elapsed = timeNow - timePrev;

    drawScreen();
    drawBuffer();
    plyMove(0.001 * elapsed);

    timePrev = timeNow;
}

如果你真的想要固定时间的游戏,你可以这样做:

float timer = 0;
float prevTime= System.currentTimeMillis();
while(true)
{
    draw();

    float currentTime = System.currentTimeMillis();
    timer += currentTime - prevTime;

    while (timer > UPDATE_TIME) // To make sure that it still works properly when drawing takes too long
    {
        timer -= UPDATE_TIME;
        update();
    }
}

更新时间是以毫秒为单位的更新间隔。

如果游戏的速度取决于FPSE的数量,那么整个设计就相当。。。不好。除了限制FPS,你还可以让你的游戏代码真正考虑所用的时间(例如,如果你的FPS高,则移动得少,如果FPS低,则移动得多)。这可以通过从实际帧到上一帧的
System.nanoTime()
差来获得。这是的重复吗?我看了一下,但这并没有完全解决我的问题,我不知道如何使它工作这会降低两台机器上的游戏速度。这不是OP想要的。好吧,这修正了游戏的速度,它的速度是60 FPS,但它在我另一台速度较慢的计算机上运行会不会较慢?我有点困惑于如何做到这一点。我创建了一个主游戏循环,我将把它放到OP中。@Stan,你的主游戏循环将根据时间而不是周期进行移动/更改。我将如何根据周期进行移动/更改?如果我删除Thread.sleep,它将达到大约850FPS,我不希望这样。它基于一个循环。相反,要根据时间进行更改。因此,游戏引擎的计算速度比绘画速度快/慢。更重要的是,你可能希望渲染发生在不同于游戏处理的线程中。游戏处理生成用于渲染的内容,然后渲染引擎可以选择渲染多少数据。这是非常低效的。更新应异步进行渲染。