3

我在我的 HTC Wildfire S 上看到游戏 Airplane Madness 以恒定的平均 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)中运行时,它实际上运行得很好,所以我不确定哪些逻辑部分会影响我智能手机的帧速率。

提前致谢。


编辑:看起来我需要让 Man 知道所有功能。

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;
        }
    }
}

以下是 DDMS 的结果:

03-12 14:29:21.008: D/FrameRate(3533): 14
03-12 14:29:22.061: D/FrameRate(3533): 15
03-12 14:29:23.048: D/FrameRate(3533): 14
03-12 14:29:24.033: D/FrameRate(3533): 14
03-12 14:29:25.018: D/FrameRate(3533): 14
03-12 14:29:26.000: D/FrameRate(3533): 14
03-12 14:29:27.056: D/FrameRate(3533): 15
03-12 14:29:28.047: D/FrameRate(3533): 14
03-12 14:29:29.026: D/FrameRate(3533): 14
03-12 14:29:29.995: D/FrameRate(3533): 14
03-12 14:29:31.037: D/FrameRate(3533): 15
03-12 14:29:32.015: D/FrameRate(3533): 14

编辑2:还有更多信息:

我已经在 render() 函数中注释掉了这段代码:

synchronized (holder)

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

4

3 回答 3

2

我不明白为什么您在渲染循环中进行同步。这是一种不好的形式,因为它可能会锁定您的渲染线程,如果由于任何原因无法立即获取锁定,则会导致应用程序似乎冻结。获取锁也需要时间。

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

永远不要在 UI 线程中同步!

于 2012-05-10T13:15:24.463 回答
0

您是否尝试渲染较少的图像/纹理或某事?也许你的手机有点太弱了,或者你可以试着玩一下毫秒来睡觉。

于 2012-05-10T11:39:39.560 回答
0

我强烈建议您使用诸如libgdx 之类的游戏框架。有大量的示例和教程可以使您的应用程序受益。更不用说你会轻而易举地将它移植到桌面或 HTML5。

于 2012-05-10T11:48:52.577 回答