• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

Legacy GM Best Way of Organizing Map Information

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:

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}
    }
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:

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;
        }
Note the above uses a combination of X and Y, versus Column and Row math. Which way do you typically set up maps?
 
Last edited by a moderator:
D

DevNorway

Guest
Consider learning for loops, and adapt that to this code. Only thing I can come up with now.
 
K

Kululu17

Guest
Thanks! I guess the main question I had, is what is the "best" way (or what way do you use) to:

A. Look up information from a map (the player is in location Z and you need to look up terrain parameters)

B. Perform calculations based on a location (move to the north-east, or look 2 squares in every direction to see if there is a mountain nearby, etc)

I have done both of these by looking up a single reference key (each "square" is an array entry), or by looking up X,Y in the same array. Neither seems very satisfactory. Is there another way?
 
Top