#How to get better experience when we create a hex map

16 messages · Page 1 of 1 (latest)

gray plaza
#

Hello, if I want to create a hex map, should I create a tile storage for storing tile hex pos, or I spawn the entity with tile hex pos directly?
I found more and more lib created a tile storage for storing tile hex pos. I think spawning the entity with tile hex pos directly is not very good.
For example, When we want to get a tile's neigbors, we should do:

  1. Get neighbors hex pos.
  2. Iter all entity with tile hex pos and check == to get neigbors entities. That may be very expensive.

If we use a Vec to store tile hex pos. we can get neighbors indices according neighbors hex pos. And then getting neigbors is very easy.

dim dagger
gray plaza
#

@dim dagger Do you think it is the best implement?

raw flare
#

@gray plaza

Depending on how big your tilemap is, you can create a TileNeighbors resource that maps HexPos to Vec<HexPos>:

#[Derive(Resource)]
pub struct TileNeighbors {
    pub map: HashMap<HexPos, Vec<HexPos>>
}

This way you can get the neighbors of any hex position in O(1) time, as long as you request this resource in whatever systems you need it.

I think spawning the tiles with HexPos components is good too, that way you can query for their positions on the tilemap if you need to.

dim dagger
#

It allows you to do the lookups you mentioned.

gray plaza
#

@raw flare Creating TileNeighbors is not a good way. In fact, we want to tackle with more and more situations, getting neighbor entitys, getting tiles in 3 radius of current tile, e.g.
I want to spawn the entity directly, because spawning other entity (water, mountain, forest, likes Civilization V) is very easy. But tackling with the situation (getting neighbors) is a hard work.

dim dagger
#

That lib handles neighbors for you

#

So I guess my suggestion is: really dig into the existing options before trying to rewrite it all yourself. Their implementations may serve as guides/reference/etc. even if you roll your own, you may use something from them.

gray plaza
#

@dim dagger I have read redblobgames, thank you.

raw flare
#

@gray plaza

I see, I believe at the end of the day it's going to be a trade-off with either calculating neighbors on-the-fly (which is more time-intensive) or storing neighbors as a resource (which is more space-intensive). For example that radius thing you mentioned I think will probably need to be on-the-fly if you plan on making the radius variable.

I have a TileNeighbors resource in my game (radius = 1), which especially helps with A* pathfinding (you don't need to spend time calculating the neighboring nodes at every step). But perhaps that might not be best for your use case.

I think I'm also misunderstanding what you're trying to convey when you say that you "want to spawn the entity directly".

gray plaza
#

@dim dagger @raw flare about bevy_ecs_tilemap:

  1. it spawns the entity with tile hex pos directly.
  2. Create a struct only for looking up and tackling with the situation what I have said.
 pub struct TileStorage {
    tiles: Vec<Option<Entity>>,
    pub size: TilemapSize,
}

If you want to get entity according to tile hex pos, you can use get(&self, tile_pos: &TilePos) directly. That doesn't need to iter all entities.👍

cinder pilot
#

In my project, I've ended up with a Map resource that contains essential tile data.

#

Random access to various tiles by coordinates is pretty common. Seemed sensible to keep that out of entities.

#

For things on the map, I use normal entities.