2017-08-03 6 views
0

私は、Abelian Sandpiles(2Dセルラーオートマトンの一種)を構築するAndroidのプロジェクトに取り組んでいます。私は小さなセルで始まり、後に成長するセルのグリッドがあり、グリッド上に四角形(または円)を描いて各セルの状態を示しています。各ステップでは、通常、細胞の30%未満を更新します。Android:多くの小さな図形を効率的かつ正確に細かく描画する

私の基本的なアプローチは、この記事から取られる:Android: How to get a custom view to redraw partially?

私はキャンバスに、すべての図形を描画して、各ステップで私が更新を必要とする細胞のみを更新し、ビットマップとしてキャッシュし、その結果をキャッシュ繰り返してください。グリッドがかなり小さく(50 x 50未満)、グリッドサイズが増加するにつれてますます不満足なものになっても十分に機能します。問題は、アップデートの数が高くなると

1)それは遅すぎるということです

2)それがスムーズに実行しても、描画がきれいに見えていません - 例えば、小さな長方形のラインが非常に見えます不安定で矛盾しています(画像参照)。

choppy artifacts from drawing small rectangles

私はこの問題にアプローチするより良い方法がなければならないことを確信しています。大きなグリッド(150 x 150など)では、幅が〜2.33の矩形または円を描画していますが、これは最適ではありません。パフォーマンスや画質を改善するためのアドバイスはありますか?

@Override 
    protected void onDraw(Canvas canvas) { 
     super.onDraw(canvas); 
     if (ready) { 
      if (needsCompleteRedraw) { 
       this.cachedBitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888); 
       cacheCanvas = new Canvas(this.cachedBitmap); 
       doInitialDrawing(cacheCanvas); 
       canvas.drawBitmap(this.cachedBitmap, 0, 0, null); 
       needsCompleteRedraw = false; 
      } else { 
       canvas.drawBitmap(this.cachedBitmap, 0, 0, null); 
       doPartialRedraws(cacheCanvas); 
      } 
     } 
    } 

    private void doInitialDrawing(Canvas clean) { 
     for (int i = 0; i < pile.gridHeight; i++) { 
      for (int j = 0; j < pile.gridWidth; j++) { 
       int state = pile.getGridValueAtPoint(new Point(j, i)); 
       clean.drawRect(j * cellSize, i * cellSize, (j + 1)* cellSize, (i + 1) * cellSize, paints[state]); 
      } 
     } 
    } 

    private void doPartialRedraws(Canvas cached) { 
     for (Point p : pile.needsUpdateSet) { 
      int state = pile.getGridValueAtPoint(p); 
      cached.drawRect(p.x * cellSize, p.y * cellSize, (p.x + 1)* cellSize, (p.y + 1) * cellSize, paints[state]); 
     } 
     pile.needsUpdateSet = new HashSet<Point>(); 
    } 

と私のペイントオブジェクトは真としてアンチエイリアスで設定されている、と私はFILLとFILL_AND_STROKEの両方にスタイルを設定しようとしました: 簡素化された描画コードはこちらです。

ご提案いただければ幸いです。

+0

画面上のセルが多くなればなるほど、ゲームを書くことに近づく(さまざまなリソースをオンラインで検索する)。あるいは、他のオープンソースのGame of Life型プロジェクトが画面のパフォーマンスをどのように扱うかを見てみることもできます。 –

+0

また、Androidのドキュメント(開発 - APIガイド - アニメーションとグラフィックス - キャンバスとドロワブル)を参照し、別のスレッドを使用して描画したSurfaceViewを使用することもできます。これは非常に効率的で、問題が解決すると確信しています。 – Zelig63

答えて

0

ここにいくつかの問題があります。

1)onDrawでキャンバスを作成しないでください。必要と思われる場合は、図面コードを正しく設計していません。

2)キャッシュビットマップへの描画のポイントは、onDrawでキャッシュを描画するのではなく、独自のスレッドで行うか、少なくとも描画時ではありません。

オンデマンドでキャッシュされたビットマップに描画し、ビューのpostInvalidate()を呼び出す2番目のスレッドが必要です。 onDraw関数は、キャッシュされたビットマップを画面に描画するdrawBitmapの呼び出しでなければなりません。

関連する問題