タイルの間にある壁を保管する


8

私はc ++でアイソメトリックエンジンを書いています。次の図に示すように、より現実的なアプローチを採用し、壁を1つのタイル全体ではなく2つのタイルの間のスペースに配置することにしました(シムズの場合と同様)。

達成したいことの概念図

私の問題は、タイルマップ関連のデータをグリッドではないものに保存する方法がわからないことです。この状況では、それをA *フレンドリーにする必要があると思うので、壁で分割されていないタイル間にノードとエッジがあります。ここに私が達成したいことを示す別の写真があります:

だからここに質問があります:

どうすればよいですか:

  • タイルと壁の両方のマップ全体を保存する
  • レンダリング用に最適化する
  • A *やその他のアルゴリズムに使用して、単純なグリッドに実装するのはかなり簡単ですが、壁(エッジ)を使用して可視性や衝突などを決定しますか?

さまざまな角度から見ることができる必要がありますか?もしそうなら、同じ壁の反対側に異なるテクスチャを適用しますか?片側にEGピンクの壁紙、反対側に青?
jzx

地図を回転させたり、壁の両側でさまざまな種類の絵の具や素材を使用したりする必要があります。壁の上部にも壁の内側のマテリアル(コンクリート、レンガ、木材など)が
表示されているはずです

回答:


7

座標系から開始します。グリッドの位置の座標は(x、y)ですが、Kromが別の答えで述べたように、壁の場合、グリッドの位置ごとに最大2つの壁が存在できます。これは、タイル間のエッジの 2番目の座標系につながります。で、この記事エッジが(X、Y、西)または(X、Y、南)することができますが、あなたは限り、あなたしている一貫としてとして2を選ぶことができますので、私は西と南を使用しました。

正方グリッドのエッジ座標

これら2つの座標系(グリッドタイルとエッジ)は関連しています。あなたは尋ねたいでしょう:どれ。タイルを囲む4つのエッジはどれですか。

タイルを囲むエッジ

パスファインディングの場合、A *は現在のタイル(A)の隣接(B)であるタイルを知りたいと考えています。隣接する4つのタイルすべてを返す代わりに、4つのエッジを確認できます。AとBの間に壁がない場合にのみ、タイルBをネイバーとして含めます。

Kromが示唆するように、タイルごとに2つの壁を保存する代わりに、通常は壁を個別のデータ構造(一連のエッジ座標)に保持します。A *がBがAの隣接セルであるかどうかを知りたい場合は、そのエッジがセット内にあるかどうかを確認します。もしそうなら、私はBを返しません。

A *の場合はおそらくこれは必要ありませんが、他の場合は、2つのタイルがどのエッジに接続されているかを知りたい場合があります。

エッジを囲むタイル

これら2つの演算の計算については、ページの「アルゴリズム」セクションを参照してください。

また、一部のタイプのマップでは、一方向の移動をサポートできるように、実際にはグリッドタイルごとに4つのエッジを保存する必要があります。


4

各タイルには、北と東にある壁を格納できます。このようにして、各タイルは2つ以上のブール値(または壁タイプを保存する場合はint)を保存するだけで済みます。欠点は、南端と西端に沿ったタイルは、それらを含む非表示のタイルの行を1行追加しない限り、南と西に壁を持つことができないことです。


2

各タイルには、アクセスできるネイバー(または接続)を格納できます。おそらくビットマップとして。壁は、2つの隣接するタイルが接続されていない場所です。これはA *と非常に友好的です。

2番目のアプローチは、タイルの接続を列挙として格納することです。たとえば、完全に開いたタイルは0、北が壁で残りが開いているタイルは1、南が壁で残りが開いているタイルは2で、すべての可能な組み合わせをカバーするまで続きます。


インターフェース(「隣接するタイルは?」)が実装(「タイルストアネイバー」)と一致する必要があることを想定しているため、「A *に優しい」というコメントは実際には当てはまらないと思います。たとえば、amitpが示唆するように壁に個別のデータ構造を使用する場合、2つは異なる場合があります。
congusbongus 2015年

1

うまくいけば、このC#は大丈夫です-私のc ++は非常に錆びています:

abstract class MapFeature
{
    public void Draw();
    public bool IsWall();
}
enum Direction
{
    North, South, East, West
}
class Wall : MapFeature
{
    public bool IsWall() { return true; }
    public Tile Front, Back; // Tiles on either side of the wall, otherwise null.

    #region Implementation of MapFeature

    public void Draw()
    {
        // Wall specific drawing code...
    }

    #endregion
}
class Tile : MapFeature
{
    public bool IsWall() { return false; }

    public MapFeature North, South, East, West; // Tiles/Walls on each side, otherwise null

    public bool CanGo(Direction direction)
    {
        switch (direction)
        {
            case Direction.North:
                return !North.IsWall();
            case Direction.South:
                return !South.IsWall();
            case Direction.East:
                return !East.IsWall();
            case Direction.West:
                return !West.IsWall();
            default:
                throw new ArgumentOutOfRangeException("direction");
        }
    }

    #region Implementation of MapFeature

    public void Draw()
    {
        // Tile specific drawing code...
    }

    #endregion
}

壁固有の情報をWallクラスに、タイル固有の情報をTileクラスに追加し、「CanGo」メソッドで条件をさらに絞り込むことができます。たとえば、壁が実際にロックされたドアである場合-たとえば、ドアクラス。

これを描画するには、任意のタイルから始めます。たとえば、現在のカメラ位置の中央にあるタイルと言います。次に、タイルのサイズに応じて、カメラに向かって左に移動します。次に、IMapFeatureノードの幅優先トラバーサルを行い、各壁/タイルを出現順に描画します。

A *はこの構造で機能しますが、ロックされたドアのようなものを処理するには、明らかにいくつかの変更が必要になります。

必要に応じて、カメラの境界内にあるタイルを見つけるために、暗黙的に壁を含むタイルの空間インデックスを維持することもできます。

それでも、開始タイルと、タイルサイズに基づいてトラバースする距離を選択するだけで済みます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.