2012-02-28 2 views
3

これまでのところ〜200個のPNG(合計14 MB)で動作するゲームを作成しています。サイズは250x150から600x400までです(これらは現在xhdpiのドロアブルです私はアンドロイドに低いdpiのためのサイズ変更をさせている)。Androidゲームのリソース読み込みでメモリが不足している

問題は、ゲームを開始するときにすべてをロードすると、エミュレータ(1 GB RAM)とGalaxy Sデバイス(512 MB RAM)の両方で約20秒後にメモリ不足エラーが発生する)。

私は、はるかに大きなリソースを持つゲームを見てきましたが、何百MBもありました。これらは、メモリの制約を超えずにリソースを高速にロードする方法をどのように処理しますか? 14 MBはそれほど多くないはずです。

今私はBitmapFactory.decodeResource()を使用して、ゲームの開始前にいくつかのループ内のすべてのビットマップを読み込みます。また、inSampleSizeを4に設定したBitmapFactory.Optionsを試してみましたが、メモリ不足問題​​は修正されましたが、遅いローディングは修正されず、約20秒かかります。私は画像を4倍小さくすると、hdpiとxhdpiの画面の会計処理にはほとんど意味がないため、品質が大幅に悪化するため、これを行う必要はありません。私もgetDrawable()を使ってみましたが、違いはありませんでした。

私も(ゲームが開始された後に)それを必要とするよう各リソースをロードすると考えられるが、:

  1. が、これは遅いと思いませんか? - 現在、システムは各ロード間でかなりのメモリを割り当てています。これは100〜300ミリ秒かかります。これにより、フレームレートが大幅に低下します。
  2. 各画像をキャッシュして一度だけロードすると、最終的には同じレベルですべての画像が必要になるため、メモリ不足エラーは修正されません。

私はビットマップがディスク上のPNGよりも多くのメモリを必要とすることを知っています。約40 MBを割り当てるとエラーが発生します。 14 MBをメモリにロードし、必要に応じてビットマップを構築する方法や、少し速いスピードを与える方法(これはかなり基本的な2番目のゲームなので、実際には多くの処理を必要としませんパワーか最大のfps)より多くの自由な記憶と引き換えに?

また、約10-16フレームの小さなアニメーションがたくさんあります。それぞれは別々のファイルです。それらを1つのファイルにマージして読み込むことに何らかの利点があるでしょうか?私はそれがメモリ使用に役立つのを見ることができませんが、それは時間を読み込むのに役立つことができますか?

更新:コードを変更して各フレームを読み込み、表示してからリサイクル()しました。これは私が言うことができるのは< 5FPSなので、私はこれを行うことができないと思います。

+0

ゲームのすべての瞬間にこれらの画像がすべて必要ですか? – Egor

+0

@ Egor - それらは、大部分が同時に約10個の別個のオブジェクトのフレームであるため、同時に画面に表示されることはありません。しかし、2〜3秒の間隔で、すべてが表示されない場合は、非常に良いチャンスがあります。 – IVlad

+0

主な問題は、多くのデバイス(とエミュレータ、私は信じている)、ヒープサイズはわずか16 MBです。 BitmapFactoryを使用して14MBのイメージをメモリに読み込むと、各イメージはビットマップにデコードされ、割り当てられた16MBのメモリをはるかに上回ります。あなたは本当にこのような大規模なイメージを持っている必要がある場合、あなたは彼らが必要とされる場でそれらを解放/ロードする方法を見つける必要があります。それ以外の場合は、より小さなビットマップで作業する必要があります。また、小さいサイズの画像を読み込むのは大容量の画像を読み込むよりもずっと速く、Androidはそれらの画像を縮小することを覚えておいてください。 –

答えて

0

ビットマップのSoftReferenceキャッシュでオプション(2)を拡張してみてください。そうすれば、ビットマップを一度だけロードすることができますが、VMのメモリが不足している場合は、これが解放される最初の候補になります。このようなもの:

public class MemoryCache { 
    private HashMap<String, SoftReference<Bitmap>> cache=new HashMap<String, SoftReference<Bitmap>>(); 

    public Bitmap get(String id){ 
     if(!cache.containsKey(id)) 
      return null; 
     SoftReference<Bitmap> ref=cache.get(id); 
     return ref.get(); 
    } 

    public void put(String id, Bitmap bitmap){ 
     cache.put(id, new SoftReference<Bitmap>(bitmap)); 
    } 

    public void clear() { 
     cache.clear(); 
    } 
} 
関連する問題