游戏循环线程偶尔会变慢



对于我目前正在为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
    }
}

下面是 screen 类的代码(getCurrentScreen(( 方法返回一个 screen 对象(:

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(( 方法并且没有在其中放置任何代码时,记录器会不断触发消息:"游戏线程只更新更新方法,没有渲染任何内容"。这是什么巫术?!

非常感谢帮助!

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

这是因为您检查if(sleepTime > 0) ,因此如果渲染非常快且睡眠时间为零,则会收到该消息。只需将其更改为 if(sleepTime >= 0) .

最新更新