2009-05-26 8 views
5

私はゲームの2次元世界のタイルを表すTileを持っています。タイルは、その4辺の任意の数に壁を持つことができます。現代のOO Cのような言語でこれを行う良い方法は?

interface Tile { 
    boolean isWallAtTop(); 
    boolean isWallAtRight(); 
    boolean isWallAtLeft(); 
    boolean isWallAtBottom(); 
} 

どこか私も16枚、それぞれの可能なタイル壁の設定のための1つを持っている:私は、現時点ではこのようなものを持っています。このような何か:

static final Image WALLS_ALL_AROUND = ... 
static final Image WALL_ON_TOP_AND_RIGHT = ... 
/* etc etc all 16 possibilities */ 

私は回避

if (tile.isWallTop && tile.isWallRight 
    && !tile.isWallBottom && !tile.isWallLeft) { 
    return WALL_ON_TOP_AND_RIGHT; 
} 

のような可能性を通過するの拷問は誰をいているしたいのですがどう

static Image getWallImage(Tile tile) 

を書きたいですこれを行うためのより控えめな方法を知っていますか?

答えて

15

go go gadget bitmasks。各タイルに4ビットのマスクを使用し、どちらの面に壁があるかを示します。

ビットAは、上の壁、右のB、下のC、左のDを示します。あなただけの論理的に、マスクで画像を見つけるための、すなわち

if (tile.Walls & (WALL_LEFT | WALL_RIGHT)) 
    // Do stuff 

と交差することができ、あなたを助けるために、定数を定義し、この4ビットのマスクが16の可能性を生成します。これを画像「配列」のインデックスとして使用すると、手間をかけずに正しい画像を直接見つけることができます。

+0

OMG!私は、if(tile.Walls&(WALL_LEFT | WALL_RIGHT))のような手動テストではなく、メソッド(またはC#のプロパティ)を使用することを強くお勧めします。 – jrharshath

+5

ビットマスクはIMOの間違った解決策です(一般的には醜いハックです)。OPのコードは純粋に手続き的なもので、彼はOOソリューションを求めています。 –

+0

ビットマスクはかなりです素敵なハックですが、静的メソッド(JITはインラインになります)として必要な述語を記述してください。 – plinth

0

フラグの列挙型で何かできませんか?

0

壁構成を1つの変数に置き、この変数のタイル画像へのマッピングを作成する必要があります。

4

タイルオブジェクトには他のプロパティがありますか?そうでない場合(またはそれらを除外することができる場合)、コンストラクタに渡される固定イメージを返すTile.getImage()メソッドを持つ16個の定数の列挙型に、タイルオブジェクト自体を作成できます。これはFlyweight patternとして知られている:Javaでは

class Tile { 
    public final boolean isWallAtTop; 
    public final boolean isWallAtRight; 
    public final boolean isWallAtLeft; 
    public final boolean isWallAtBottom; 
    public final Image image; 

    private Tile(boolean top, boolean right, boolean left, 
       boolean bottom, Image image) 
    { 
     this.isWallAtTop = top; 
     this.isWallAtRight = right; 
     this.isWallAtLeft = left; 
     this.isWallAtBottom = bottom; 
     this.image = image; 
    } 

    public static final Tile WALLS_ALL_AROUND = 
     new Tile(true, true, true, true, new Image("allWalls.png")) 
    // more constants here, plus other methods that work with 
    // only the wall data 
} 

、あなたも「本物」列挙型としてこれを実装することができます。

タイルで構成されるマップの場合、タイル参照の単純な2次元配列を持つことができます。または、個々のタイルに他のデータが必要な場合は、別のSpecificTileクラスに「その他のデータ」と上記のTileオブジェクトの1つを参照してください。

+0

編集後でさえより良くなります。それが可能なら私からの+2 :) – willcodejavaforfood

2

次のようなビットフラグ列挙型を作成することをお勧めします。

[Flags] 
public enum WallLocations 
{ 
    None = 0, 
    Left = 1, 
    Right = 2, 
    Top = 4, 
    Bottom = 8 
} 

次に、辞書を使用して壁の場所から画像にマッピングすることができます。

Dictionary<WallLocations, Image> map = new Dictionary<WallLocations, Image>(); 

map.Add(WallLocations.None, image0000); 
map.Add(WallLocations.Left, image1000); 
map.Add(WallLocations.Right, image0100); 
map.Add(WallLocations.Top, image0010); 
map.Add(WallLocations.Bottom, image0001); 
map.Add(WallLocations.Left | WallLocations.Right, image1100); 
// .... 

少なくともC#では、16個すべてのケースで列挙型の定義を拡張することもできます。代わりWALLS_ALL_AROUND画像を作る

[Flags] 
public enum WallLocations 
{ 
    None = 0, 

    Left = 1, 
    Right = 2, 
    Top = 4, 
    Bottom = 8, 

    LeftAndRight = Left | Right, 
    LeftAndTop = Left | Top, 
    LeftAndBottom = Left | Bottom, 
    RightAndTop = Right | Top, 
    RightAndBottom = Left | Bottom, 
    TopAndBottom = Top | Bottom, 

    AllExceptLeft = Right | Top | Bottom, 
    AllExceptRight = Left | Top | Bottom, 
    AllExceptTop = Left | Right | Bottom, 
    AllExceptBottom = Left | Right | Top, 

    All = Left | Right | Top | Bottom 
} 
0

、その画像、また許容動きやその他もろもろに対処するために必要な他の任意の論理を含むオブジェクト作ります。 Locationオブジェクトでは、wallsプロパティをWALLS_ALL_AROUNDに設定することができます。これを使用して、イメージを照会し、他の壁関連ロジックを処理できます。

イメージのセットごとにこれらの(不変の)オブジェクトを16個だけ必要とするため(1セットのイメージしかない場合はおそらくTileのシングルトンサブクラスです)、メモリも保存します。

0

まともなOO解決策にはおそらくStrategy Patternが含まれます。可能な実装の1つは、WallConfigurationクラスとWallFactoryを作成することです。タイルにはWallConfigurationが含まれます。実装(C++スタイル)は、このようになります。これには興味深い利点の

class Tile 
{ 
private: 
    WallConfiguration walls; 
    // Other Tile data 

public: 
    enum Walls 
    { 
     TOP, 
     BOTTOM, 
     LEFT, 
     RIGHT, 
     TOP_RIGHT, 
     TOP_LEFT 
     // Fill in the rest 
    }; //Enums have a place! 
    Tile(Walls wall) 
    { 
     walls = WallFactory.getConfiguration(wall); 
    } 

一つは、あなたが壁を爆破(と召し上がれする機能を追加したときに、今、...あなたはあなたを知っているということです」もう一度やり直してください)、WallConfigurationクラスにその責任を追加することができます。WallConfigurationクラスは、たとえば、左の壁を吹き飛ばしたときに、自分自身の適切なインスタンスを取得する方法を知っています。

関連する問題