0

私が現在 Android デバイス用に作成しているゲームでは、スレッドであり、すべてを更新およびレンダリングする RenderView というクラスがあります。時折、クラスは「ゲーム スレッドは更新メソッドを更新するだけで、何もレンダリングしていません」というメッセージをログに記録します。nexus s でゲームを 30 fps で実行しています。そして、セッション中に数回メッセージを受け取ります。クラスを最適化する方法、または何かを忘れている場合、またはそれが完全に正常であることを誰かに教えてもらえますか?

これが私のコードです:

public class RenderView extends SurfaceView implements Runnable {

    public final String classTAG = this.getClass().getSimpleName();
    Game game;
    Bitmap framebuffer;
    Thread gameloop;
    SurfaceHolder holder;
    boolean running;

    int sleepTime;
    int numberOfFramesSkipped;
    long beginTime;
    long endTime;
    long lastTime;
    int differenceTime;
    int framePeriod;
    Canvas canvas;
    int frameCount;
    WSLog gameEngineLog;

    public RenderView(Game game, Bitmap framebuffer) {
        super(game);
        this.game = game;
        this.framebuffer = framebuffer;
        this.holder = getHolder();
        framePeriod = 1000/game.getFramesPerSecond();
        lastTime = System.currentTimeMillis();
        gameEngineLog = game.getGameEngineLog();
    }

    @Override
    public void run() {
        while(running == true) {
            if(holder.getSurface().isValid()) {

                beginTime = System.currentTimeMillis();
                numberOfFramesSkipped = 0;

                game.getCurrentScreen().update();
                game.getCurrentScreen().render(); // Draw out everything to the current virtual screen (the bitmap)
                game.getGraphics().renderFrameBuffer(); // Actually draw everything to the real screen (combine both bitmaps)

                canvas = holder.lockCanvas();
                if(canvas != null) { // Fix for mysterious bug ( FATAL EXCEPTION: Thread)
                    // The viewing area of our virtual screen on our real screen
                    canvas.drawBitmap(framebuffer, null, game.getWSScreen().getGameScreenextendeddst(), null);
                    holder.unlockCanvasAndPost(canvas);
                }
                else {
                    gameEngineLog.e(classTAG, "Surface has not been created or otherwise cannot be edited");
                }

                endTime = System.currentTimeMillis();;
                differenceTime = (int) (endTime - beginTime);
                sleepTime = (int) (framePeriod - differenceTime);

                if(sleepTime > 0) {
                    try {
                        Thread.sleep(sleepTime);
                    } catch (InterruptedException exception) {
                        exception.printStackTrace();
                    }
                }
                else {
                    while(sleepTime < 0 && numberOfFramesSkipped < game.getMaxFrameSkippes()) {
                        gameEngineLog.d(classTAG, "Game thread is only updating the update method and is not rendering anything");
                        try {
                            Thread.sleep(5);
                        } 
                        catch (InterruptedException exception) {
                            exception.printStackTrace();
                        }
                        game.getCurrentScreen().update();
                        sleepTime += framePeriod;
                        numberOfFramesSkipped++;
                    }
                }

             // Frame Per Second Count
                frameCount++;

                if(lastTime + 1000 < System.currentTimeMillis()) {
                    game.getGameEngineLog().d(classTAG, "REAL FPS: " + frameCount);
                    lastTime = System.currentTimeMillis();
                    frameCount = 0;
                }

            }
        }

    }

    public void resume() { 
        running = true;
        gameloop = new Thread(this);
        gameloop.start();         
    }   

    public void pause() { 
        running = false;                        
        while(running == true) {
            try {
                gameloop.join();
                running = false;
            } 
            catch (InterruptedException e) {
            }
        }
        gameloop = null;
    }

}

Graphics クラスのコードは次のとおりです (getGraphics() はグラフィックス オブジェクトを返すだけです)。

public class Graphics {

    public final String classTAG = this.getClass().getSimpleName();
    Game game;
    Canvas frameBuffer;
    Canvas canvasGameScreenextended;
    Canvas canvasGameScreen; // Used for customeScreen
    Bitmap gameScreenextended;
    Bitmap gameScreen;
    Rect gameScreendst;
    Rect gameScreenextendeddst;
    WSLog gameEngineLog;

    Graphics(Game game, Bitmap framebuffer, Bitmap gameScreen) {
        this.game = game;
        // Initialize canvases to render to
        frameBuffer = new Canvas(framebuffer);
        canvasGameScreen = new Canvas(gameScreen);
        // Initialize images to be rendered to our composition
        this.gameScreen = gameScreen;
        // Set up the Log
        gameEngineLog = game.getGameEngineLog();
    }

    public void resetCanvasGameScreenextended() {
        // This method has to be called each time the screen scaling type changes
        canvasGameScreenextended = new Canvas(game.getWSScreen().getGameScreenextended());
        gameScreenextended = game.getWSScreen().getGameScreenextended();
    }

    public Canvas getCanvasGameScreenextended() {
        return canvasGameScreenextended;
    }

    public Canvas getCanvasGameScreen() {
        return canvasGameScreen;
    }

    public void renderFrameBuffer() {
        // Composition
        // First layer (bottom)
        frameBuffer.drawBitmap(gameScreen, null, game.getWSScreen().getGameScreendst(), null);
        // Second layer (top)
        frameBuffer.drawBitmap(gameScreenextended, null, game.getWSScreen().getGameScreenextendeddst(), null);
    }

    public void clearFrameBuffer() {
        canvasGameScreen.drawColor(Color.BLACK);
        //canvasGameScreenextended.drawColor(Color.BLACK);
        gameScreenextended.eraseColor(Color.TRANSPARENT); // Make top layer transparent
    }

}

画面クラスのコードは次のとおりです (getCurrentScreen() メソッドは画面オブジェクトを返します)。

public class Screen {

    public final String classTAG = this.getClass().getSimpleName();
    protected final Game game;
    protected final Graphics graphics;

    protected Screen(Game game) {
        this.game = game;
        this.graphics = game.getGraphics();
        //game.getInput().reset();
    }

    public void update() {

    }

    public void render() {

    }

    /** Initialize all the sensory that should be used within this screen.*/

    public void resume() {

    }

    public void pause() {
        game.getInput().useAccelerometer(false);
        game.getInput().useKeyboard(false);
        game.getInput().useTouchscreen(false);
    }

    public void onDispose() {
        game.getGraphics().clearFrameBuffer();
    }

    public void setScreenResizeType(int screenResizeType) {

    }

Screen クラスが拡張され、render() メソッドは次のようなメソッドで隠蔽されます。

graphics.getCanvasGameScreen().drawRect(play, red);

面白いことに、render() メソッドをオーバーライドしてコードを何も配置しないと、ロガーが常に起動し、「ゲーム スレッドは更新メソッドのみを更新しており、何もレンダリングしていません」というメッセージが表示されます。これは何の魔法なの!?

ヘルプは大歓迎です!

4

1 に答える 1

0

更新された投稿からわかる限り、実際にはレンダリングの問題はありません。代わりに、コードは誤ってそのメッセージを出力します。

これは、 をチェックしているためです if(sleepTime > 0)。したがって、レンダリングが非常に高速で、sleepTime がゼロの場合、そのメッセージが表示されます。に変更するだけ if(sleepTime >= 0)です。

于 2012-05-18T15:55:44.633 に答える