Search Unity

Hexagon-based Strategy-Game: How to find possible places for buildings?

Discussion in 'Scripting' started by HeaDiii, Feb 3, 2018.

  1. HeaDiii

    HeaDiii

    Joined:
    May 18, 2015
    Posts:
    61
    Hey there,

    I'm currently developing an RTS Game with an underlying Hexagon-Grid. I want the player to be able to place buildings on that grid, dependant on what areas are offering enough free space for the selected building.

    The problem is: I don't know how to store the Building-Area-Information each building needs to have. I try to make it more clear with this picture:



    The green hexagons are displaying the places that are going to be occupied by that building. The outer blue hexagons are places that need to be free, but they are not going to be occupied by the building (i want to make sure that there is enough space for workers to walk between buildings). The orange hexagon represents the center-hexagon from which it is going to be calculated if the building fits to certain places.

    Since almost every building uses a different pattern, I want a decent solution to store such information and work with them.

    Any ideas?

    Here's a game that uses a similar approach:

     
  2. McDev02

    McDev02

    Joined:
    Nov 22, 2010
    Posts:
    664
    I did the same thing for a rectangular grid. You should store values within your grid. Either you have a class or struct for each tile or you use a seperate Array. For instance you have a two dimensional boolean array that stores wheather or not the tile is occupied or not.

    Then you also need an array for each building of it's local grid space that defines what type that tile should be. Think of it like a brush for painting software that will always be in the center of your building.
    You could use this: enum EGridType{ Empty, Free, Occupied }
    SO your blue tiles would be Free and your green tiles would be occupied. Empty could be used if a tile is not covered by your building.

    So here is what your local grid would look like, all i'ts content would be relative to its origin. For Hexagon this can be more complicated, maybe you use the center (yellow dot) as a reference. For a rectangular grid I choose the lower left corner as the root, maybe you can use the hexagon with the red dot.
    If you need rotation for your building than this becomes even more complicated and you have to swap data around first.
    grid.jpg

    Ss basically when you place the building on your map you also place that array of data over your map, offset by the root. You can then decide if you can place the building. We compare each grid inside the buildings rect and compare the Map with the local data of the building.

    StartTileX and StartTileY could be the coordinates of the red dot for instance.

    Code (CSharp):
    1. bool CanPlaceBuilding( ... )
    2. {
    3.     for (int x = 0; x <= BuildingTilesX; x++)
    4.     {
    5.         mapX = StartTileX + x; //Convert to global X coordinate
    6.         for (int y = 0; y <= BuildingTilesY; y++)
    7.         {
    8.             mapY = StartTileY + y; //Convert to global Y coordinate
    9.             //If just one tile is occupied and not "Free" in the local map the building can not be placed.
    10.             if (MapData[mapX, mapY]){  //MapData == true means it is occupied
    11.                 if (LocalMap[x, y] != EGridType.Empty) return false;
    12.             }
    13.         }
    14.     }
    15.     return true;
    16. }
    You can then use a similar code to actually set the map to be occupied or not for deletion.

    Hexagons are a bit more complicated than rectangular grids and maybe my example doesn't apply exactly. There are different methods to store grid data like cubic or axial coordinates. I hope I explained the idea and you can translate it to your system.
     

    Attached Files:

    • grid.jpg
      grid.jpg
      File size:
      141.3 KB
      Views:
      1,027
    Last edited: Feb 3, 2018
    HeaDiii likes this.
  3. HeaDiii

    HeaDiii

    Joined:
    May 18, 2015
    Posts:
    61
    Thanks, I managed to find a solution. Probably the most dirty one :)

    What i did was creating an int-array and an integer that says "fieldsPerLine". FieldsPerLine determines how many fields are in one line.
    My building needs a 6 by 5 area, so my array is of size 30. (6 fields per line, 5 lines) I gave the fields numbers from 0 to 3. 0 represents that it doesn't matter in what condition the field on the grid is. 1 is a field that is empty and not going to be occupied, 2 is a field that is going to be occupied and 3 is "one" field that represents the center of the building.

    My solution is to iterate through my entire cell-grid and on every cell on that grid I run 2 for-loops to check if the required building area is valid, starting from the current iteration-cell.

    This is what my "required-building-area" looks like:


    And here is my grid. The cells i marked red are valid build-positions, relative to the orange center-cell of my building:


    The "required-build-area" can be understood as some kind of stencil that is moved over every cell. If the stencil fits completely, the current cell is a valid build-area.

    So, thanks again :)
     
  4. McDev02

    McDev02

    Joined:
    Nov 22, 2010
    Posts:
    664
    Sounds similar to what I have suggested. The Grid layout is different from your first image, this can be treated like a rectangular grid mostly.
    May I ask how you generate the mesh? Is it your own algorithm or is that available somewhere?
     
  5. HeaDiii

    HeaDiii

    Joined:
    May 18, 2015
    Posts:
    61
    McDev02 likes this.