Java Android游戏循环:如何达到平均每秒60帧?

Java Android游戏循环:如何达到平均每秒60帧?,java,android,loops,frame-rate,Java,Android,Loops,Frame Rate,我在HTC Wildfire S上看到过游戏飞机疯狂以60 FPS的恒定平均速度渲染屏幕。我一直试图在同一部智能手机上模拟结果,但我就是不明白为什么我的程序平均只能达到15 FPS 你可能会问,我怎样才能看到《疯狂飞机》的帧速率?在设置中有一个切换FPS计数器的选项。我将我的设置为启用 这是我的密码。这是我的游戏循环。这有一些有趣的结果: public void run() { // Average FPS for Android is 15 on Test Phone

我在HTC Wildfire S上看到过游戏飞机疯狂以60 FPS的恒定平均速度渲染屏幕。我一直试图在同一部智能手机上模拟结果,但我就是不明白为什么我的程序平均只能达到15 FPS

你可能会问,我怎样才能看到《疯狂飞机》的帧速率?在设置中有一个切换FPS计数器的选项。我将我的设置为启用

这是我的密码。这是我的游戏循环。这有一些有趣的结果:

    public void run() {
        // Average FPS for Android is 15 on Test Phone is 13 through 15.
        // Max FPS is 20.
        // Occasional bursts of FPS60 may occur.
        long now, lastTime = System.nanoTime();
        double process = 0.0;
        final double NSperTick = 1000000000.0 / 60.0;
        while (running) {
            now = System.nanoTime();
            process += (now - lastTime) / NSperTick;
            lastTime = now;
            boolean ticked = false;
            while (process >= 1) {
                process -= 1;
                tick();
                ticked = true;
            }
            if (ticked) {
                render();
            }
            swap();
            try {
                Thread.sleep(2);
            }
            catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
有人能告诉我我做错了什么,需要改进什么,等等,这样我的平均帧速率才能达到60 FPS吗?这个游戏循环,在Java(而不是Android)中运行时,运行几乎很好,所以我不确定是什么逻辑部分影响了我智能手机的帧速率

提前谢谢


编辑:看来我需要让人知道所有的功能

private void render() {
    synchronized (holder) {
        if (holder.getSurface().isValid()) {
            Canvas c = holder.lockCanvas();
            c.drawRGB(0x44, 0x55, 0xff);
            ball.render(c);
            holder.unlockCanvasAndPost(c);
        }
    }
}

private void swap() {
}

private void tick() {
    float[] values = {meter.X, meter.Y, meter.Z};
    ball.tick(values);
    handler.tick(ball);
}
下面是我检查游戏平均FPS的方法:

public void run() {
    // Average FPS for Android is 15 on Test Phone is 13 through 15.
    // Max FPS is 20.
    // Occasional bursts of FPS60 may occur.
    long now, lastTime = System.nanoTime();
    int frames = 0;
    double process = 0.0;
    long frameTime = System.currentTimeMillis();
    final double NSperTick = 1000000000.0 / 60.0;
    while (running) {
        now = System.nanoTime();
        process += (now - lastTime) / NSperTick;
        lastTime = now;
        boolean ticked = false;
        while (process >= 1) {
            process -= 1;
            tick();
            ticked = true;
        }
        if (ticked) {
            //render();
            frames++;
        }
        swap();
        try {
            Thread.sleep(2);
        }
        catch (InterruptedException e) {
            e.printStackTrace();
        }
        if (frameTime <= System.currentTimeMillis() - 1000)
        {
            Log.d("FrameRate", Integer.toString(frames));
            frameTime += 1000;
            frames = 0;
        }
    }
}
编辑2:有更多信息:

我在render()函数中注释掉了以下代码:

synchronized (holder)

但是,我仍然只能达到14到15 FPS。这是我无法突破的限制吗?

你是否尝试渲染更少的图像/纹理或其他东西?也许你的手机太弱了,或者你可以试着在几毫秒的睡眠时间里玩一玩。

我强烈建议你使用游戏框架,比如。有大量的示例和教程将使您的应用程序受益。没有提到你会轻而易举地把它移植到桌面或HTML5上。

我不明白你为什么要在渲染循环中同步。这是一种糟糕的形式,因为它可能会锁定渲染线程,导致应用程序在由于任何原因无法立即获得锁定时出现冻结。获取锁也需要时间

如果数据的组织方式需要锁定渲染线程,则需要重构设计


永远不要在UI线程中同步

如果不调用
render()
,它的行为如何?很明显,您似乎忽略了一件事,那就是您的渲染可能需要比您更多的时间。如果不了解tick()、render()和swap()方法中的内容,我们将无法帮助您。@unwind我为tick()、render()和swap()添加了更多信息。我注意到在render()中,我调用了一个对象球。我是否应该扩展顶部的函数?您可能希望尝试繁忙等待,而不是使用
sleep()
。游戏循环是一种可能需要繁忙等待的情况,因为
sleep()
不能保证在醒来前的最长睡眠时间。@JasonNichols我添加了一些详细信息。我目前正在将1个位图和1个蓝色背景渲染到SurfaceView的画布上。我没有运行任何可能使用OpenGL ES的东西。此外,我的手机可以以平均每秒60帧的速度运行“飞机疯狂”,我相信这是在OpenGL中实现的。也就是说,我的手机没那么弱。我确实使用了Thread.sleep()函数,但这一点都不重要/我不得不拒绝那个提议。我无论如何都不允许使用游戏框架:/创建一个新线程,然后使用该线程来同步保持器,这算是同步UI线程吗?您好,我刚刚添加了一点更多的信息。移除同步(保持架)根本无法解决问题:/
synchronized (holder)