3

42フレームで構成された大きなスプライトシート(3808x1632)があります。これらのフレームを使用してアニメーションを表示し、スレッドを使用してすべてのフレームを含むビットマップ配列をロードし、スプラッシュ画面が終了するのを待ちます。私はSurfaceView(およびキャンバスの描画機能)を使用していません。メインレイアウトのImageViewにフレームごとにロードするだけです。私のアプローチは、スプライトシートから多数の画像をロードするのと似ています 。完了には実際には約15秒かかりますが、受け入れられません。

私はこの種の関数を使用します:

for (int i=0; i<TotalFramesTeapotBG; i++) {
            xStartTeapotBG = (i % framesInRowsTeapotBG) * frameWidthTeapotBG; 
            yStartTeapotBG = (i / framesInRowsTeapotBG) * frameHeightTeapotBG;
            mVectorTeapotBG.add(Bitmap.createBitmap(framesBitmapTeapotBG, xStartTeapotBG, yStartTeapotBG, frameWidthTeapotBG, frameHeightTeapotBG));
        }

frameBitmapTeapotBGは大きなスプライトシートです。もっと深く見てみると、おそらくスプライトシートが大きすぎるために、createBitmap関数に時間がかかることをlogcatで読みました。rect関数とcanvasを使用して、配列にロードする小さなビットマップを作成して、大きなスプライトシートにウィンドウを作成できる場所を見つけましたが、実際には明確ではありませんでした。私はその投稿について話している:ビットマップの一部を切り取る

私の質問は、スプライトシートのカットをどのように高速化できるかということです。

編集:私はこのアプローチを使おうとしていますが、最終的なアニメーションを見ることができません:

    for (int i=0; i<TotalFramesTeapotBG; i++) {
        xStartTeapotBG = (i % framesInRowsTeapotBG) * frameWidthTeapotBG; 
        yStartTeapotBG = (i / framesInRowsTeapotBG) * frameHeightTeapotBG;
        Bitmap bmFrame = Bitmap.createBitmap(frameWidthTeapotBG, frameHeightTeapotBG, Bitmap.Config.ARGB_8888);
        Canvas c = new Canvas(bmFrame); 
        Rect src = new Rect(xStartTeapotBG, yStartTeapotBG, frameWidthTeapotBG, frameHeightTeapotBG); 
        Rect dst = new Rect(0, 0, frameWidthTeapotBG, frameHeightTeapotBG);  
        c.drawBitmap(framesBitmapTeapotBG, src, dst, null);         
        mVectorTeapotBG.add(bmFrame);
    }

おそらく、ビットマップbmFrameが正しく管理されていません。

4

4 に答える 4

6

簡単な答えは、より良いメモリ管理です。

ロードしているスプライトシートは巨大で、それをコピーして小さなビットマップの束にします。スプライトシートをこれ以上小さくすることはできないと仮定すると、次の2つのアプローチのいずれかを使用することをお勧めします。

  1. 個々のビットマップを使用します。これにより、メモリコピーが削減され、Dalvikがヒープを拡張する必要がある回数も削減されます。ただし、これらの利点は、ファイルシステムから1つだけではなく、多くの画像をロードする必要があるために制限される場合があります。これは通常のコンピューターの場合ですが、Androidシステムはフラッシュメモリで実行されるため、異なる結果が得られる場合があります。
  2. スプライトシートから直接ブリットします。描画するときは、のようなものを使用してスプライトシートからまっすぐに描画しCanvas.drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint)ます。これにより、ファイルの負荷が1つの大きな割り当てに削減されます。これは、アクティビティの存続期間中に1回だけ発生する必要があります。

2番目のオプションは、メモリシステムで簡単になり、GCでの作業が少なくなるため、おそらく2つのうちの方が優れていると思います。

于 2011-09-07T22:23:42.130 に答える
3

提案をしてくれたstevehbのおかげで、私はついにそれを手に入れました:

for (int i = 0; i < TotalFramesTeapotBG; i++) {
    xStartTeapotBG = (i % framesInRowsTeapotBG) * frameWidthTeapotBG; 
    yStartTeapotBG = (i / framesInRowsTeapotBG) * frameHeightTeapotBG;
    Bitmap bmFrame = Bitmap.createBitmap(frameWidthTeapotBG, frameHeightTeapotBG, Bitmap.Config.ARGB_8888);
    Canvas c = new Canvas(bmFrame);  
    Rect src = new Rect(xStartTeapotBG, yStartTeapotBG, xStartTeapotBG+frameWidthTeapotBG, yStartTeapotBG+frameHeightTeapotBG); 
    Rect dst = new Rect(0, 0, frameWidthTeapotBG, frameHeightTeapotBG);  
    c.drawBitmap(framesBitmapTeapotBG, src, dst, null);         
    mVectorTeapotBG.add(bmFrame);
}

計算時間は信じられないほど短くなります!:)

于 2011-09-09T10:20:01.533 に答える
1

LevelListDrawableを使用します。スプライトを個々のフレームにカットし、描画可能なリソースディレクトリにドロップします。プログラムで、またはxmlベースのレベルリストドローアブルを使用して、ドローアブルを作成します。次に、ImageView.setImageLevel()を使用してフレームを選択します。

于 2011-09-07T22:16:47.110 に答える
1

行と列に基づいてスライスする方法を使用します。ただし、スプライトシートはかなり巨大です。そのシート全体をメモリに入れていると考える必要があります。3808x1632x4は、メモリ内の画像のサイズです。

とにかく、私がしていることは、画像(たとえば、128x128)を取得し、Sprite(bitmap、4、2)コンストラクターに4つの列と2つの行があることを伝えます。次に、それに基づいてスライスしてさいの目に切ることができます。ビットマップ.getWidth()/4など...かなり単純なもの。ただし、実際の作業を行いたい場合は、OpenGLを使用してテクスチャを使用してください。

ああ、私はまた、起こる必要があるいくつかのonDrawのものがあることを言及するのを忘れました。基本的に、インデックスカウンターを保持し、ビットマップから長方形をスライスして、ソースの長方形からキャンバス上の宛先の長方形に描画します。

于 2012-07-18T21:34:32.517 に答える