タイルの 2D グリッドがあるとします (これは 2D タイル ベースのゲーム用です)。ほとんどのタイルは 1 つのスポットを占有しますが、一部の大きな「オブジェクト」は複数のスポットを埋めることができます。配列でインデクサーを使用して、これらのオブジェクトをベース タイルに自動的に "参照" します。したがって、3,4 に 2x2 オブジェクトがあり、4,4 にアクセスすると、自動的にリダイレクトされ、3,4 でタイルが取得されます。ただし、正確なタイルを取得する必要がある場合は、引数を指定してこの機能を回避できます。(これについてのGameDevに関する私の古い質問についてのより良い説明)
別の見方をすると、ゲームの世界のドア オブジェクトです。ユーザーはドアの任意の場所をクリックして開くことができますが、個々のパーツには、さまざまな背景や照明の値など、他のプロパティを含めることができます。
注: 私は趣味のプログラマーなので、これは正しくない可能性があります (なぜ私はあなたのアドバイスを求めているのですか)。各「特大」タイルは、そのベース タイルへの参照をX,Y
位置の形式で格納します (これは代わりに参照である必要があります)。メモリ内の実際のオブジェクトに?)
public class TileWrapper
{
public int Width = 0;
public int Height = 0;
private Tile[] tiles; //Backing Store
public TileWrapper()
{
tiles = new Tile[Width * Height];
}
public TileWrapper(int width, int height)
{
Width = width;
Height = height;
tiles = new Tile[Width * Height];
}
/// <summary>
/// Accessor for tiles
/// </summary>
/// <param name="x">X Position</param>
/// <param name="y">Y Position</param>
/// <param name="overide">Bool to "override" the get, if true, it wont get the reference tile and will bypass the checks</param>
public Tile this[int x, int y, bool override = false]
{
get
{
//If we do not want to bypass the checks, AND the current tile is > than 1x1
if (!override && tiles[y * Width + x].IsLarge)
return tiles[tiles[y * Width + x].refY * Width + tiles[y * Width + x].refX]; //Use the reference positions to get the main position of the tile
//If we want to bypass the checks or the tile wasn't large, get the absolute position
else
return tiles[y * Width + x];
}
set
{
//Same thing for SET
if (!override && tiles[y * Width + x].IsLarge) //Set base tile if the large tile has a reference
tiles[tiles[y * Width + x].refY * Width + tiles[y * Width + x].refX] = value;
else //Set absolute tile
tiles[y * Width + x] = value;
}
}
2D から 1D への変換で読みにくい場合は申し訳ありませんが、いくつかのテストを行った後、内部で 1D 配列を使用する方が少し速いようです。
IsLarge
タイルが大きい (1x1 より大きい) かどうかを単純にチェックするプロパティです。
大きなタイルが配置されたときに隣接するタイルの参照を埋め、それに応じてそれらを削除するロジックは既に用意されています。
ゲームのプロファイリング中に、タイルの get アクセサーが大量の CPU を消費し、ライティング、レンダリング、衝突などのためにフレームごとに何百回もタイルを取得していることがわかりました。
このコードのパフォーマンスと効率を改善するにはどうすればよいですか?
ベンチマーク(Intel Quad Core i7 2670QM での 30,000 回の反復の平均)
Tile t = tiles[100, 100];
- 2D 内部アレイで 160 ns および 175 ns
Tile t = tiles[100, 100, true];
- 137 ns および 264 ns WITH 2D 内部アレイ (奇数)
100,100
は大きなタイルではありませんが、これらのタイルはあまり一般的ではないことに注意してください。画面に家があった場合、いくつかの大きなタイル (ドア、テーブル) が表示されますが、土/石/木がたくさんあります。