2012-05-18 3 views
0

Для игры, которую я сейчас пишу для устройств Android, у меня есть класс под названием RenderView, который является Thread и обновляет и отображает все. Иногда класс регистрирует сообщение «Игровой поток только обновляет метод обновления и ничего не делает». Игра работает со скоростью 30 кадров в секунду. И я получаю сообщение пару раз на протяжении всего сеанса. Может ли кто-нибудь сказать мне, как я могу оптимизировать класс, или если я что-то забываю или что это абсолютно нормально?GameLoop Thread изредка медленный

Вот мой код:

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) { 

    } 

Класс экрана расширен, d визуализации() метод слежка с помощью методов, таких как:

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

Самое смешное, когда я переопределить метод визуализации() и не размещать любой код в нем, регистратор пожары постоянно с сообщением: «Игровой поток обновляет только метод обновления и ничего не делает». Что это за колдовство?!

Помощь очень ценится!

+0

Можете ли вы подробнее рассказать о методах 'game.getCurrentScreen(), game.getGraphics(), render(), update()' и 'renderFramBuffer()'. Еще лучше вы можете разместить на них какой-то код. –

+0

Я добавил еще код. Ваша помощь приветствуется. :) –

ответ

0

Насколько я понимаю из вашего обновленного сообщения, на самом деле проблема с рендерингом отсутствует. Вместо этого ваш код ошибочно печатает это сообщение.

Это потому, что вы проверяете if(sleepTime > 0), поэтому если рендеринг очень быстрый, а sleepTime - ноль, вы получите это сообщение. Просто измените его на if(sleepTime >= 0).

+0

Извините, приятель, все еще не решает этот трюк. –

+0

Может ли это иметь что-то с тем, как я разработал свой игровой цикл? –