Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nice way to do this in modern OO C-like language?

I have Tiles which represent the tiles in a game's 2-dimensional world. The tiles can have walls on any number of their 4 sides. I have something like this at the moment:

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

Somewhere else I also have 16 images, one for each possible tile wall configuration. Something like this:

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

I want to write a

static Image getWallImage(Tile tile)

What I'd like to avoid is the torture of going through the possibilities like

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

Does anyone know a cuter way to do this?

like image 763
jjujuma Avatar asked May 26 '09 11:05

jjujuma


People also ask

Can you do OO in C?

The purpose of object oriented programming (OOP) is to produce well designed reusable code. In principle OOP can be done in any language, even assembly. This is because all OO language compilers/assemblers (e.g. C++) ultimately translate the high level constructs of the language into machine language.

What is modern C language?

C is extraordinarily modern for a 50-year-old programming language. Whether you're writing embedded code, low-level system routines, or high-performance applications, C is up to the challenge. This unique book, based on the latest C standards, exposes a modern perspective of this tried-and-true language.

What is nice programming language?

Nice is a research programming language. It demonstrates how the powerful ML-Sub type system can be used in practice. Nice is an object-oriented language, with parametric, polymorphic types, higher-order functions, and more. It combines the advantages of object-orientation and functional programming.


3 Answers

Go go gadget bitmasks. Use a 4 bit mask for each tile, stating which side has a wall.

A B C D

Bit A indicates a wall on the top, B the right, C the bottom, D the left. Define constants to help you that you can just logically intersect with the mask, i.e.

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

For finding the image, this 4 bit mask produces the 16 possibilities. Use it as an index into an images "array", so you can directly find the correct image without any effort.

like image 135
Adam Wright Avatar answered Oct 11 '22 08:10

Adam Wright


Do the tile objects have any other properties? If not (or if you can factor out those), you could make the tile objects themselves into an enumeration of 16 constants with a Tile.getImage() method that returns a fixed image passed to the constructor. This is known as the Flyweight pattern:

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
}

In Java, you could even implement this as a "real" enum.

For a map that consists of tiles, you could either have a simple 2-dimensional array of Tile references, or if you need other data for individual tiles, have another SpecificTile class that contains the "other data" and a reference to one of the Tile objects above.

like image 43
Michael Borgwardt Avatar answered Oct 11 '22 08:10

Michael Borgwardt


I suggest creating a bit flag enum like the following.

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

Then you can use a dictionary to map from the wall locations to the images.

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);
// ....

At least in C# you could also extend the enum definition with all 16 cases.

[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
}
like image 28
Daniel Brückner Avatar answered Oct 11 '22 10:10

Daniel Brückner