0

ゲームはタイルベースですが、タイルは実際には地形とパスファインディングの目的でのみ使用されます。スプライトの動きは自由形式です(つまり、プレイヤーはタイルの途中にいることができます)。

このゲームのマップは非常に大きいです。通常のズームタイルは32*32ピクセルで、マップサイズは2000x2000以上(400万タイル!)になる可能性があります。現在、マップはタイルの配列であり、タイルオブジェクトは次のようになります。

public class Tile {

    public byte groundType;
    public byte featureType;
    public ArrayList<Sprite> entities;

    public Tile () {
        groundType = -1;
        featureType = -1;
        entities = null;
    }
}    

ここで、groundTypeはテクスチャであり、featureTypeはタイル全体(木や大きな岩など)を占めるマップオブジェクトです。これらのタイプの機能は非常に一般的であるため、タイル上のオブジェクト(アイテム、クリーチャーなど)のリストであるエンティティに格納するのではなく、独自の変数にすることを選択しました。エンティティは、パフォーマンス上の理由からタイルに保存されます。

私が抱えている問題は、エンティティがnullに初期化されていない場合、Javaのヒープスペースが不足することです。しかし、それをnullに設定し、何かがタイルに移動したときにのみ初期化することは、私には悪い解決策のように思えます。クリーチャーが空のタイルを横切って移動している場合、リストは常に初期化され、nullに戻される必要があります。これは貧弱なメモリ管理ではありませんか?より良い解決策は何でしょうか?

4

1 に答える 1

2
  • すべてのスプライトを含む単一の構造(ArrayListで始まる)を用意します。
  • ゲームループを実行してスプライトリストを循環している場合、たとえば、30〜50秒に1回、最大200のスプライトがある場合、この構造自体からパフォーマンスが低下することはありません。
  • 後で、衝突検出などの他の目的のために、単一のArrayListの構造を修正する必要があるかもしれません。ゲームロジックを整理するためのシンプルでうなずくようなソリューションから始めて、必要に応じて最適化することをお勧めします。
  • タイルの場合、スペースが問題になる場合は、特別な「タイル」オブジェクトを使用するのではなく、タイルごとの特定の情報が実際にはあまり必要ない場合は、各タイルの情報を1バイト(shortまたはint)にパックすることを検討してください。作成するすべてのJavaオブジェクトにはいくらかのオーバーヘッドがあることに注意してください(議論のために、VMおよび32ビットと64ビットのプロセッサに応じてオブジェクトあたり24〜32バイトの順序で言います)。400万バイトの配列は「たった」4MB、400万intは「たった」16MBです。
  • タイルの仕様を単一のプリミティブにパックすることが実用的でない場合のタイルデータの別の解決策は、大きなByteBufferを宣言し、各タイルに16バイトのデータが必要な場合は各タイルのデータをインデックス(たとえば)tileNo*16に格納することです。
  • 実際にすべてのタイルをメモリに保存しないことを検討できます。これが適切かどうかは、ゲームによって異なります。2000x2000はまだ領域内にあり、個々のタイルが多くのデータを必要としない場合は、データ全体をメモリに適切に保持できます。

最後の2、3のポイントがオブジェクト指向言語のポイント全体を打ち負かすと考えているなら、そうです。したがって、ヒープスペースを節約するために「極端な」ソリューションを選択する時点、またはプログラミングパラダイムを改善するためにより多くのメモリを使用して「逃げる」ことができるかどうかを検討する必要があります。タイルごとにオブジェクトがあると、(たとえば)数百メガバイトのオーダーが使用される可能性があります。ばかげているいくつかの環境で。数ギガバイトが利用可能な他の場所では、それは完全に合理的かもしれません。

于 2012-12-03T18:05:01.213 に答える