2016-05-18 53 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メソッドは2秒ごとに呼び出されているが画面は黒いままです。どのような問題が起きる可能性がありますか? (私はラインsetWillNotDraw(false)をコメント解除した場合の方法により長方形が一度描かれたが、動いていない)...

答えて

1

私は、キャンバスキャンバスを描画するためにonDraw(キャンバスキャンバス)オーバーライド関数を変更しました。

4

あなたはいつもの問題があります:あなたはonDraw()をオーバーライドしている、表示部に描画します。だからあなたは非常に高価なカスタムビューが正しく動作しません。ビューを描画させると、一度描画されますが、invalidate()にはコールしないので、再び表示されません。私の推測では、あなたのレイアウトに背景色を設定し、Viewを不透明にしています。なぜなら、Surface上に何が描画されているのかを見ることができないからです。

キャンバスレンダリングの場合は、SurfaceViewではなくcustom Viewを使用する方がよい場合があります。私はそのアプローチをお勧めします。

実際にSurfaceViewを使用する場合は、onDraw()を別のもの(など)に変更し、レンダリングスレッドから呼び出します。 ViewパートではなくSurfaceパートを描画するので、SurfaceViewのサブクラスを作成する必要はありません(また、独立したクラスにすることで、落としたような一般的な落とし穴を避けることができます)。問題が発生するさまざまな方法があるので、SurfaceView and Activity interactの仕組みを理解してください。

また、game loopを構成するための推奨方法をお読みください。

関連する問題