4
\$\begingroup\$

I'm trying to create a game with a fixed size map (2D Tile array). I suppose I can inherit other tiles from this base Tile, e.g.: a BankTile. Placing and removing tiles is all too easy, but forming rooms keeps me puzzled.

  • Rooms can only be formed by adjacent tiles (4-way: above, below, left and right)

This way, 2 tiles can form a 'room', e.g. a Bank with a maximum amount of resources it can hold (sum of both its tiles).

I am wondering on how I should be implementing this, if there are any existing (and optimal) solutions to this.

Some things I considered:

  • Tiles must keep a reference to the Room they are in AND rooms must keep a vector of all tiles they hold. So adding tiles and removing tiles becomes pretty efficient. Only obstacle this poses is the splitting of rooms: if 1 tile connects 2 rooms and this tile is removed, it should split the room and creating a new room for the split-off part.

  • Rooms will be 2D vectors with a begin-position (the room will be a surrounding square of the actual room polygon)

  • Rooms are 4-way linked lists of tiles

  • ?

What needs to be done with rooms:

  • tiles need to be added and removed
  • allowing rooms to merge and split
  • calculating size of a room
  • finding a room quickly on a map

This image clarifies what I need: enter image description here

Should I pick data structure 1? Rooms are 2D arrays with null-pointers for not-room-tiles. Or should I pick data structure 2? Rooms are 4-way linked lists of tiles. Or should I think of something else, e.g. vector of tiles = room? Given the operations I need to be able to perform on them, which is best?

\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

Just realized by looking at your image, it looks like it's more like " Data structure 1"

Edit:

I think you're looking for something like this then:

//In Your Game manager or whatever
public setRoom(Room r, startX, startY){

   Tile[][] tiles = r.getTiles();
   int sizeY = tiles.size();
   int sizeX = tiles[0].size();        

   for(int y=0; y < sizeY; y++)
      for(int x=0; x < sizeX; x++)
          //Adds the tile, for any empty tile you need additional checking
          worldGrid.setTile(tiles[y][0],startX+x,startY+y);
}
 //In Your worldGrid or whatever

  private Tile[][] grid;

 public function setTile(Tile t, x, y){

    grid[y][x] = t;
 }

Same can be applied for removing a room. Just make sure you don't overlap rooms. Unless you want that ( empty tiles should be able to overlap without problem). But it needs additional checking so keep that in mind.

In this scenario logic is applied by reading the tiles from worldgrid, whether it's passable, non-passable, other gamelogic etc. The Rooms simply hold the tiles which make up for the room. These tiles are translated to the grid:

enter image description here

You can keep track of the room by adding a member in your Tile:

Public class Tile(){
    {
       private int roomId= -1;

        public Tile(){
        }

        public int getRoomdId() {return roomId}
    }

So if you need any information on the Room you could just do currentTile.getRoomId(). For example this id could serve as an index position of your Room in an Array. A Room manager for instance that holds all the room objects.

Of course you could make it more complex by making managers for each aspect and keep track of what Tile belongs to what room. It's up to you.

Players position in the 2D array is as follows

int indexX = Math.floor(player.x / tileSize);
int indexY = Math.floor(player.y / tileSize);

This will give us the indices of the current tile in our worldgrid. --> grid[indexY][indexX]

As for merging rooms have a manager that couples Room objects together. If you go by my example you should be able to retrieve the Room object by Tile. You can then "ask" the RoomManager what room is merged with the current one and read its properties like: size, type etc.

Or should I pick data structure 2? Rooms are 4-way linked lists of tiles

If you go with a "world grid" as in my example you don't need to. Simply request the surrounding tiles and see if they are passable once the player overlaps with a tile. Unless you move from tile to tile, as in snapping to another tile, then it would be as easy as checking player input. When the player hits the down arrow key, you simply test if the tile below the current one; which is [y+1][x]; is passable. If not, nothing happens.

\$\endgroup\$
5
  • \$\begingroup\$ I created a little image to show you what I mean (check OP). Thanks for your input. \$\endgroup\$ Jan 12, 2013 at 7:20
  • \$\begingroup\$ So in that case the rooms are pretty much predefined. So what you could do is check where you place your room on the grid. Read out the tiles and merge them on the game grid. Keep track of which tile belongs to what room. So when the player is on a specific tile you can request the room. Your 2D arrays are fine. You just need to translate it to your "world" 2D array and manage which rooms occupies what tile position. You could predefine 2D arays to represent as room templates. You then just read them into your world but start at a specific point in your grid. \$\endgroup\$
    – Sidar
    Jan 12, 2013 at 7:58
  • \$\begingroup\$ @TheDudeAbides made an Edit. Hope that helps. \$\endgroup\$
    – Sidar
    Jan 12, 2013 at 8:20
  • \$\begingroup\$ I see, many thanks! Would it make much difference if I put the Room object in Tile? Create 1 room and "set" the Tiles to it (to access the room directly?). Because if I make 1 Room object and set it to the different tiles, would it use more memory than an integer id? \$\endgroup\$ Jan 12, 2013 at 10:42
  • \$\begingroup\$ It's a design choice and ultimately up to you. You can reference the Room object in your tile. It doesn't take up a lot of memory since you're pointing to an existing object. \$\endgroup\$
    – Sidar
    Jan 12, 2013 at 14:16

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .