GameLoop Thread偶尔会变慢

时间:2012-05-18 14:08:25

标签: java android multithreading

对于我目前正在为Android设备编写的游戏,我有一个名为RenderView的类,它是一个Thread并更新并呈现所有内容。有时,类会记录消息“游戏线程只是更新更新方法而不呈现任何内容”。我的nexus游戏以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()方法并且不在其中放置任何代码时,记录器会不断触发消息:“游戏线程只更新更新方法并且不呈现任何内容”。这是什么样的巫术?!

非常感谢帮助!

1 个答案:

答案 0 :(得分:0)

据我所知,从您更新的帖子中,实际上没有渲染问题。相反,您的代码错误地打印了该消息。

这是因为你检查if(sleepTime > 0),所以如果渲染非常快并且sleepTime为零,你就会得到那条消息。只需将其更改为if(sleepTime >= 0)