Help on a hexagon map[SOLVED]

Started by
14 comments, last by TalonSnow 18 years, 10 months ago
Ok, I assumed this would be easier before now trying it :) Here is what I came up with and what i tried. First, I thought you could make a 3 dimensional array and the map "sector" , meaning one unit on the map, would reside in on location in the array. Three dimensional and not 2 dimensional to hold multiple data for each hexagon. i.e. players located in this space, terrain info, etc.. It can be mapped where the hexagons to the north and south would be up and down respectively, but where tyo the north east would be to the right and south east would be down one and to the right one. This would be reversed going to the left. This would require extra space however, as you would be allocating memory for squares that would see no data around the edges. So, Second I decided on a linked list. Figured this would be much more practicle and easier to control. Where each node would have a link to each of its directions on the map, an array for players at that location, as well as properties for that hexagons image source, terrain info, etc.. However after starting to code this it is becoming much more complex then I intended. I am having to code each one by hand on how it links with the rest. My intentions was to just make a map in an editor, where it will import the data to a file that can be read by the engine and created into the appropriate linked list. I am not sure if i am just missing an obvious method or approach, any thoughts, suggestions, flames welcome :) (*here is a posting of just the sample I tried late last night, and quickly gave up on to find a better logic to create it*)
struct mapType;
typedef	mapType*	Mnode;
struct	mapType
{
	int			sectorPlayers[200];				// array to hold players currently in sector
	int			sectorType;						// type of terrain
	int			specialSector;					// placeholder for bases, outposts, bldgs, etc..
	char*		mapGraphic;						// image name to load for the sector
	Mnode		Nlink;							// links in directions that can be travelled
	Mnode		Slink;
	Mnode		NElink;
	Mnode		SElink;
	Mnode		NWlink;
	Mnode		SWlink;

};

//Name: MapList
//Function: holds the game map records are specific sectors that link to a linked list
class MapList
{
public:
	MapList();
	~MapList();
	void	loadMap(char* mapName);
private:
	mapType*	Mone;
	mapType*	Mtwo;
	mapType*	Mthree;
	mapType*	Mfour;
	mapType*	Mfive;
	mapType*	Msix;
	mapType*	Mseven;
	mapType*	Meight;
	mapType*	Mnine;
	mapType*	Mten;
	mapType*	Meleven;
	mapType*	Mtwelve;
	mapType*	Mthirteen;
	mapType*	Mfourteen;
	mapType*	Mfifteen;
	mapType*	Msixteen;
	mapType*	Mseventeen;
	mapType*	Meighteen;
};

MapList::~MapList()
{
}

MapList::MapList()
{
	Mone = NULL;
}

void MapList::loadMap(char* mapName)
{
	int mapNum = 1;
	char mapLine[45];
	char terrain[15];
	char special[15];
	char image[15];
	int Cswitch = 1;
	int Fswitch;
	int Sswitch;
	mapType	tempNode;
	ifstream inFile(mapName);
	if (inFile.fail())
	{
		WriteError("Failed to open file for creating map list");
	}
	while(!inFile.eof())
	{
		inFile.getline(mapLine, sizeof(mapLine));
		for(int test = 0;mapLine[test] != NULL;test++)
		{
			if(mapLine[test] == ',')
			{
				if(Cswitch == 1)
					Fswitch = test;
				else
					Sswitch = test;
				Cswitch++;
			}
			switch(Cswitch)
			{
			case 1:
				terrain[test]=mapLine[test];
				break;
			case 2:
				special[test-Fswitch]=mapLine[test];
				break;
			case 3:
				image[test-Sswitch]=mapLine[test];
				break;
			}
		}
		Mnode tempNode;
		tempNode = new mapType;
		tempNode->sectorType = (int)terrain;
		tempNode->specialSector = (int)special;
		tempNode->mapGraphic = image;

		switch(mapNum)
		{
		case 1:
			Mone = tempNode;
			break;
		case 2:
			Mtwo = tempNode;
			break;
		case 3:
			Mthree = tempNode;
			break;
		default:
			break;
		}
		mapNum++;
	}
	WriteError(Mone->mapGraphic);
	//WriteError(Mtwo->mapGraphic);
	//WriteError(Mthree->mapGraphic);
}

MapList	maptry; 

and yes it was late and i realise this would not work, but as i said i was playing with logic and trying to figure out how to approach this first. sincerely, Michael Hughes [Edited by - TalonSnow on June 16, 2005 8:49:39 AM]
<=- Talon -=>
Advertisement
It would be much easier to store the hex information in a single dimension array, or even better a vector. If you know the dimentions of your map and you know the coordinate system of the map, it becomes fairly easy to transform map coordinates to array/vector indices and visa versa. Neighboring hexes can be determined algorithmically also.
<span class="smallfont">That is not dead which can eternal lieAnd with strange aeons even death may die.   -- "The Nameless City" - H. P. Lovecraft</span>
yes but i don't desire this for several reasons ;) Though do correct me if im wrong.

(1) How would you easily access where the directions you can go are? hexagon map is not straight as in top to bottom and left to right as squares. It is not as simple as up down left and right. This is why you would need a tleast a 2 dimensional array or a linked list with nodes.

(2) The problem is the map will not be a specific size, but will be generated as stated int the original post by a level editor which will be able to make a map of any size.

(3) your options would not include any needed information on the details of the specific hexagon, as in texturing, players, etc..

(just to add more info so I am not misunderstood, this is being used in a multiplayer game. I want to control player locations within the player structs themselves (already done) as well as the map for quick access to who else is sharing space with the player without doing lookups.)
<=- Talon -=>
Did you read this article? It's a pretty nice intro to hex maps. It mostly covers evaluating mouse events, but the second image should help you.
Quote:Original post by TalonSnow
(1) How would you easily access where the directions you can go are? hexagon map is not straight as in top to bottom and left to right as squares. It is not as simple as up down left and right. This is why you would need a tleast a 2 dimensional array or a linked list with nodes.

Given a hex with known coordinates (x,y) it can be determined algorthmically what the coordinates of the six surrounding hexes are. You don't need to store what can be calculated at run-time, and in the long run you'll probably be saving yourself from a lot of unnecessary record keeping that can easily result in bugs.

Quote:Original post by TalonSnow
(2) The problem is the map will not be a specific size, but will be generated as stated int the original post by a level editor which will be able to make a map of any size.

Arrays and vectors don't have to fixed size either. Once you know the dimentions of the map (at creation), you create an array or vector to accomidate the size of the map. The algorithms to transform hex coordinate to array indices and back again can be written to account for different map sizes.

Quote:Original post by TalonSnow
(3) your options would not include any needed information on the details of the specific hexagon, as in texturing, players, etc..

How so? I didn't say anything about what had to be stored in each element of the array/vector.
<span class="smallfont">That is not dead which can eternal lieAnd with strange aeons even death may die.   -- "The Nameless City" - H. P. Lovecraft</span>
Heh.

Here's some info on my current project.

paths                        paths   units  |                            |    /game --- worlds --- maps --- tiles *-projects  |                                 \ players                              buildings  |empires


Where the main line there forms into a common tree. Game objects contain multiple world objects, which contain multiple map objects, which [so on...].

Each tile object itself will hold x,y coords, as well as its parent [always a map], which can/will act as a third dimension. Maps though contain the actual orientation info. x,y coords can be arranged into square maps, hex maps [in various ways], or others. Maps also contain a hash_map of the tiles it contains [hashed on the x,y values], to allow for quick lookup. Linked lists are not so good in that regard.

So how does a tile know of it's neighbors? Well those path objects is how. The global list of paths from one tile to another is stored in the root game object. This is kinda needed to allow for paths between [logical] worlds. The tile's list of paths are simply pointers to those made objects.

The path object defines two tiles, and rules for moving between them. Such rules are often things like travel time, uni/bi-directional, added disorientation, movement restrictions or requirements... Usually it's just "basic land travel", but this makes for an arbitrary number of paths from a tile. Adding or destroying a path [like building a teleporter] is pretty trivial.

Most importantly though, it allows you to make maps of arbitrary size and shape by having the explicit list of neighbors rather than assuming 6, and that the travel between them will be uniform.

I'm not sure this is ideal, since the advantages aren't necissary everywhere, but it should at least provide some ideas :]
thank you both for your prompt repsonses, and micro for the corrections ;)

that link is very helpful as well.

So let me make sure I understand right. You make a vector that stores a struct that consists of the appropriate data per hex. Then you find the size you ned to allocate when you read in the file. You allocate the memory, then proceed to pull in the data putting it in the vector in order it is retrieved. Whne you go to render a specific hex, you scan through the vector seeking the specific one you need, or if rendering the entire map just use the alg on the linked page to plot everyone.

Only thing I am confused is on the time it would take to scan through every time trying to find the specific hex it is looking for, or would this be irrelevant on the client side?

thank you for your help so far! it sure is helping.
<=- Talon -=>
I was going to implement a game with hexes as well. I think at most, a 2D array should suffice. I think the problem is, you're treating a hex map like it's something special, and yeah, it kinda is, but for all intents and purposes, you can just treat it like a square-grid-based map.

I mean, really, hexes are practically just like square grid maps, except each space has 2 lefts and 2 rights instead of just one of each. See where I'm going with this?

And yeah if you really wanted to, as microdot suggested, 2D arrays can be mapped to 1D arrays quite easily with the right algorithm.

As for terrain info, etc, I could be wrong 'cuz I'm still a noob as well, but I don't think you should use an extra dimension for that info. You might want to try a "hex" or "terrain" class/object and slap that into the 2d or 1d array/vector.
ok looks like we posted same time so i missed your data in my last post.

So i create an additional hash table with allt eh x,y variables for the quick lookup?

And I like the path system, as it allows alot more flexability in traveling from one to another. However, i do not quite understand how you globally control it all. From what I understand of it, every path is stored in one area on a global level? So when you are in a certain hex it looks up all possible path structs to determine movement options?

Or is all path structs from one hex stored locally inside each hex?

Anoymnous Poster: I missed your post as well :) You guys sure are posting fast! Can barely keep up lol. I know i can do a 2d array, but dont want to waste the extra space that wouldn't be needed that would be all arodun the edges. This wouldn;t be so bad in a smalel rmap, but it will continually grow with wasted space the bigger the map grows.
<=- Talon -=>
To get from a 2d coordinate to an index you can simply do this.

index = ( y * width ) + x

Where width is the width of the map. If your coordinates start with one instead of zero, you do this.

index = ( ( y - 1 ) * width ) + ( x - 1 )

No need for lookup tables. This assumes that you're storing the map in the array row major.
<span class="smallfont">That is not dead which can eternal lieAnd with strange aeons even death may die.   -- "The Nameless City" - H. P. Lovecraft</span>

This topic is closed to new replies.

Advertisement