K
Kululu17
Guest
Hello All,
I was curious which ways our community has found to handle map information (as in a territorial map, not a ds_map), specifically how you store map information from a data perspective, and how you do things like edge detection. I have solutions for both of these, which I am happy to share with the community, but they are not very “elegant”, and I am wondering if there are better solutions out there.
Let’s start with how to set up storing map data – would I would think applies to a lot of games with a top down view that need to store some kind of information about each square of the map. For my example I am showing the player’s view, which has detailed information about the quadrant they are in (shown in text on the GUI above), “rough” information about the surrounding quadrants, and zero information about the quadrants further out (typical “fog of war”).
I have three maps set up, one with the detailed information on each quadrant, on showing what the player sees, and one showing what the NPC sees. Each time the player or NPC moves, it updates their respective maps. In the next screenshot we see the player has moved south, and detected an NPC village.
Since game maker don’t seem to support 3 dimensional arrays, I set up the main reference point as the quadrant number (basically one dimensional map “key”), and if X and Y coordinates are needed, you can pull them from the map information array. Anyway, I haven’t really settled on using exclusively X and Y, or quadrant math (where you need to subtract to calculate rows and columns to handle movement) for everything. Here is how the global map is laid out:
Below is a sample of using “quadrant math” to update the view that the player sees – not yet accounting for edge correction, discussed below.
Questions:
How do you set up the data for these types of maps.
Does anyone have an elegant way to handle edges/corners. For example if you are on the left edge, you can’t update the exploration map further to the left, because it doesn’t exist. You can tell that you are on the left edge either using the X coordinate, or using the rows and columns concept, and either way, you could use a really nasty-looking nested IF logic to determine if you are on one of the edges, or a corner, etc... and it gets even worse if you are looking two quadrants out rather than just one. But you would need to duplicate this for every situation where you were worried about an edge – and there are a lot of them – from preventing the player to moving off the edge of the map, to updating what the player sees, etc. So, just wondering if anyone has a “clean looking” code for this
Below is my "messy" code that handles one specific situation where you need to avoid edges and corners:
Note the above uses a combination of X and Y, versus Column and Row math. Which way do you typically set up maps?
I was curious which ways our community has found to handle map information (as in a territorial map, not a ds_map), specifically how you store map information from a data perspective, and how you do things like edge detection. I have solutions for both of these, which I am happy to share with the community, but they are not very “elegant”, and I am wondering if there are better solutions out there.
Let’s start with how to set up storing map data – would I would think applies to a lot of games with a top down view that need to store some kind of information about each square of the map. For my example I am showing the player’s view, which has detailed information about the quadrant they are in (shown in text on the GUI above), “rough” information about the surrounding quadrants, and zero information about the quadrants further out (typical “fog of war”).
I have three maps set up, one with the detailed information on each quadrant, on showing what the player sees, and one showing what the NPC sees. Each time the player or NPC moves, it updates their respective maps. In the next screenshot we see the player has moved south, and detected an NPC village.
Since game maker don’t seem to support 3 dimensional arrays, I set up the main reference point as the quadrant number (basically one dimensional map “key”), and if X and Y coordinates are needed, you can pull them from the map information array. Anyway, I haven’t really settled on using exclusively X and Y, or quadrant math (where you need to subtract to calculate rows and columns to handle movement) for everything. Here is how the global map is laid out:
Code:
g.Global_Map[(Quad_Number),GMap_X] = Quad_X; //XCoordinate
g.Global_Map[(Quad_Number),GMap_Y] = Quad_Y; //YCoordinate
g.Global_Map[(Quad_Number),GMap_Hills] = irandom(9)+1; //Terrain type
g.Global_Map[(Quad_Number),GMap_Water_Static] = irandom(9)+1; //Static Water
g.Global_Map[(Quad_Number),GMap_Water_Flowing] = irandom(9)+1; //Flowing Water
//The next stuff is set via the script based on above values (production may preset the above)
g.Global_Map[(Quad_Number),GMap_Woods] = 0; //Woods vs Fields
g.Global_Map[(Quad_Number),GMap_N_Food] = 0; //Native food
g.Global_Map[(Quad_Number),GMap_Fertility] = 0; //Soil Fertility
g.Global_Map[(Quad_Number),GMap_Passability] = 0; //Passability
g.Global_Map[(Quad_Number),GMap_Stone] = 0; //Stone
g.Global_Map[(Quad_Number),GMap_Clay] = 0; //Clay
g.Global_Map[(Quad_Number),GMap_Iron] = 0; //Metal - Iron
g.Global_Map[(Quad_Number),GMap_Special_1] = 0; //Specials (Alien Stuff)
//End initialization
Below is a sample of using “quadrant math” to update the view that the player sees – not yet accounting for edge correction, discussed below.
Code:
if Quad_X >= 2 && Quad_X <= g.Map_Width -1 && Quad_Y >= 2 && Quad_Y <= g.Map_Height -1{
//now need to do map subtraction/addition
UL = Player_Quad - g.Map_Height -1;
CL = Player_Quad - g.Map_Height;
BL = Player_Quad - g.Map_Height +1;
UC = Player_Quad - 1;
BC = Player_Quad + 1;
UR = Player_Quad + g.Map_Height -1;
CR = Player_Quad + g.Map_Height;
BR = Player_Quad + g.Map_Height +1;
if g.Player_Map[(UL),3] == 0 {g.Player_Map[(UL),3] = 1}
if g.Player_Map[(CL),3] == 0 {g.Player_Map[(CL),3] = 1}
if g.Player_Map[(BL),3] == 0 {g.Player_Map[(BL),3] = 1}
if g.Player_Map[(UC),3] == 0 {g.Player_Map[(UC),3] = 1}
if g.Player_Map[(BC),3] == 0 {g.Player_Map[(BC),3] = 1}
if g.Player_Map[(UR),3] == 0 {g.Player_Map[(UR),3] = 1}
if g.Player_Map[(CR),3] == 0 {g.Player_Map[(CR),3] = 1}
if g.Player_Map[(BR),3] == 0 {g.Player_Map[(BR),3] = 1}
}
How do you set up the data for these types of maps.
Does anyone have an elegant way to handle edges/corners. For example if you are on the left edge, you can’t update the exploration map further to the left, because it doesn’t exist. You can tell that you are on the left edge either using the X coordinate, or using the rows and columns concept, and either way, you could use a really nasty-looking nested IF logic to determine if you are on one of the edges, or a corner, etc... and it gets even worse if you are looking two quadrants out rather than just one. But you would need to duplicate this for every situation where you were worried about an edge – and there are a lot of them – from preventing the player to moving off the edge of the map, to updating what the player sees, etc. So, just wondering if anyone has a “clean looking” code for this
Below is my "messy" code that handles one specific situation where you need to avoid edges and corners:
Code:
//Assume that the original variables are reused for the horizontal "strip" - new variables for the four new "corners"
var Map_Key = argument0;
var Map_X = g.Global_Map[(Map_Key),GMap_X];
var Map_Y = g.Global_Map[(Map_Key),GMap_Y];
var Vert_Position = "Center";
if Map_Y <= 2 {Vert_Position = "Top"}
if Map_Y > g.Map_Height - 2 {Vert_Position = "Bottom"}
var Horiz_Position = "Center";
if Map_X <= 2 {Horiz_Position = "Left"}
if Map_X > g.Map_Width - 2 {Horiz_Position = "Right"}
//This corners are a maximum of +/- 1 on the vert, so only need to check right/left alignment
if Horiz_Position == "Left" {//you need to add or subtract a column, so multiply by column length
CL = Map_Key + (g.Map_Height*3);
UL = Map_Key + (g.Map_Height*3) -1;
BL = Map_Key + (g.Map_Height*3) +1;
}
else {
CL = Map_Key - (g.Map_Height*2);
UL = Map_Key - (g.Map_Height*2) -1;
BL = Map_Key - (g.Map_Height*2) +1;
}
if Horiz_Position == "Right" {
CR = Map_Key - (g.Map_Height*3);
UR = Map_Key - (g.Map_Height*3) -1;
BR = Map_Key - (g.Map_Height*3) +1;
}
else {
CR = Map_Key + (g.Map_Height*2);
UR = Map_Key + (g.Map_Height*2) -1;
BR = Map_Key + (g.Map_Height*2) +1;
}//you need to add or subract a column, so multiply by column length
//now the single quads - can easily add in the new corners later, but have to define them first
if Vert_Position == "Top" {
UC = Map_Key + 3;
UUL = Map_Key - g.Map_Height + 3;
UUR = Map_Key + g.Map_Height + 3;
}//cant explore to the top, so explore even further to the bottom
else {//this is the "normal" case, not near an edge - just keep going out in all directions
UC = Map_Key -2;
UUL = Map_Key - g.Map_Height - 2;
UUR = Map_Key + g.Map_Height -2;
}
if Vert_Position == "Bottom" {
BC = Map_Key - 3;
BBL = Map_Key - g.Map_Height - 3;
BBR = Map_Key + g.Map_Height - 3;
}//cant explore to the bottom, so explore even further to the top
else {//this is the "normal" case, not near an edge - just keep going out in all directions
BC = Map_Key + 2;
BBL = Map_Key - g.Map_Height + 2;
BBR = Map_Key + g.Map_Height + 2;
}
Last edited by a moderator: