2016-05-18 84 views
0

我有以下類:Android的帆布SurfaceView黑屏

public class GameView extends SurfaceView implements SurfaceHolder.Callback { 

public static final int WIDTH = 860; 
public static final int HEIGHT = 480; 

int x = 0; 

GameLoop gameLoop; 

public GameView(Context context) { 
    super(context); 
    getHolder().addCallback(this); 
    setFocusable(true); 
} 

public GameView(Context context, AttributeSet attrs) { 
    super(context, attrs); 
    getHolder().addCallback(this); 
    setFocusable(true); 
} 

public GameView(Context context, AttributeSet attrs, int defStyleAttr) { 
    super(context, attrs, defStyleAttr); 
    getHolder().addCallback(this); 
    setFocusable(true); 
} 

@Override 
public void surfaceCreated(SurfaceHolder holder) { 
    //setWillNotDraw(false); 

    gameLoop = new GameLoop(this); 

    gameLoop.start(); 
} 

@Override 
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { 

} 

@Override 
public void surfaceDestroyed(SurfaceHolder holder) { 

} 

@Override 
protected void onDraw(Canvas canvas) { 
    super.onDraw(canvas); 

    if(canvas != null) { 
     Paint paint = new Paint(); 
     paint.setColor(Color.WHITE); 
     canvas.drawRect(x, 0, 200, 200, paint); 
     canvas.drawRect(200, 200, 400, 400, paint); 
     Log.v("TEST", "Drawing into canvas"); 
     Log.v("TEST", "x := " + x); 
    } 
} 

public void update() { 
    x += 5; 
} 

和遊戲循環看起來像這樣:

public class GameLoop extends Thread { 
public static final int REFRESH_TIME = 2; 
private static final int LOG_FPS_AFTER_FRAMES = 30; 

public static Canvas canvas; 

private double averageFPS; 

private GameView gameView; 

private boolean running; 

public GameLoop(GameView gamePanel) { 
    this.gameView = gamePanel; 
} 

@Override 
public void run() { 
    super.run(); 

    running = true; 

    long startTime; 
    long timeMillis; 
    long waitTime; 
    long totalTime = 0; 
    int frameCount = 0; 
    long targetTime = 1000*REFRESH_TIME; 

    while(running) { 
     startTime = System.nanoTime(); 
     canvas = null; 

     try { 
      canvas = gameView.getHolder().lockCanvas(); 

      synchronized (gameView.getHolder()) { 
       gameView.update(); 
       gameView.draw(canvas); 
      } 


     } catch(Exception e) {} 
     finally { 
      if(canvas != null) { 
       try { 
        gameView.getHolder().unlockCanvasAndPost(canvas); 
       } catch(Exception e) {} 
      } 
     } 


     timeMillis = (System.nanoTime() - startTime)/1000000; 
     waitTime = targetTime - timeMillis; 

     try { 
      this.sleep(waitTime); 
     } catch(Exception e) {} 

     totalTime += System.nanoTime() - startTime; 
     frameCount++; 

     if(frameCount == LOG_FPS_AFTER_FRAMES) { 
      averageFPS = 1000/((totalTime/frameCount)/1000000); 
      frameCount = 0; 
      totalTime = 0; 
      Log.v("FPS", Double.toString(averageFPS)); 
     } 

    } 

} 

@Override 
public void interrupt() { 
    super.interrupt(); 

    running = false; 
} 

public boolean isRunning() { 
    return running; 
} 

public void setRunning(boolean value) { 
    this.running = value; 
} 

}

的OnDraw方法被調用每兩秒鐘但屏幕仍然是黑色的。任何想法可能是什麼問題? (順便說一句,如果我取消註釋行setWillNotDraw(false)矩形繪製一次,但不移動)...

回答

1

我只是改變了覆蓋函數onDraw(畫布畫布)繪製(畫布畫布),它的工作原理!

4

你有一個通常的問題:你覆蓋onDraw(),其中使用視圖部分。所以你有一個非常昂貴的自定義視圖,這不正確。如果你讓視圖繪製,它會畫一次,但你不打電話invalidate(),所以它不會再發生。我的猜測是你在佈局中設置了一個背景顏色,使得視圖不透明,這就是爲什麼你不能看到Surface上正在繪製什麼。

對於Canvas渲染,通常最好使用custom View,而不是SurfaceView。我會推薦這種方法。

如果您確實想使用SurfaceView,請將onDraw()更改爲其他內容(如doDraw()),然後從渲染線程調用它。既然你將繪製Surface部分,而不是View部分,你不需要子類SurfaceView(不應該,因爲使它成爲一個獨立的類將避免常見的陷阱,如你陷入)。確保你瞭解如何SurfaceView and Activity interact,因爲有各種方式惹上麻煩。

您還應該閱讀推薦的方法來構造game loop