3

HTC Wildfire S でゲーム Airplane Madness が一定の平均 60 FPS で画面をレンダリングしているのを見たことがあります。同じスマートフォンで結果を真似ようとしてきましたが、私のプログラムが 15 しか上がらない理由がわかりません。 FPS平均?

飛行機の狂気のフレーム レートを表示するにはどうすればよいですか? 設定で FPS カウンターを切り替えるオプションがあります。私はENABLEDに設定しました。

これが私のコードです。これが私のゲームループです。このことから、いくつかの興味深い結果が得られます。

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

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

少ない画像/テクスチャまたは sth をレンダリングしようとしましたか? 多分あなたの電話はちょっと弱すぎるか、ミリ秒で少し遊んでみることができます。

于 2012-05-10T11:39:39.560 に答える
0

libgdxなどのゲーム フレームワークを使用することを強くお勧めします。アプリケーションに役立つサンプルとチュートリアルがたくさんあります。デスクトップや HTML5 に簡単に移植できることは言うまでもありません。

于 2012-05-10T11:48:52.577 に答える