GameMaker What is the most efficient way to make Multi-Height Level Tilemaps

Petrik33

Member
First of all, it is important to notice that the game I develop is made to be look like isometric. But it is done using tilesets and tutorial of Shaun Spalding and some fundamental functions of isometricity coordinates translation.
So the actual problem is until now I have been using Shaun's tutorial(
)
to create testing level, there he uses GameMakerStudio Tilemaps to create isometric tilemaps. But after a while I have decided to make a level editor and add verticallness to the game. To make it, the artist made isometric cubes, with the top side being a tile. So in this case what is the best way to implement tiles for my game if now I render them this way:
//Recieving TileData from TileMap draw in GMS Level Editor
GML:
global.theMap=ds_grid_create(MAP_W,MAP_H);

var tileMap=layer_tilemap_get_id("Map");
var colMap=layer_tilemap_get_id("Col");
for(var tX = 0; tX < MAP_W; tX++)
{
    
    for(var tY = 0; tY < MAP_H; tY++)
    {
        var tileX=TileToScreenX(tX,tY);
        var tileY=TileToScreenY(tX,tY)
        var tileMap_data = tilemap_get(tileMap,tX,tY);
        //Format: [tX,tY,screenX,screenY,Sprite,Z,Covered,Collision,Cursored...]
        var thisTile = [tX,tY,tileX,tileY,-1,0,false,false];
        thisTile[TILE.SPRITE_FRAME]=tileMap_data;
        thisTile[TILE.Z]=0;
        thisTile[TILE.COVERED]=noone;
        thisTile[TILE.COL]=tilemap_get(colMap,tX,tY);
        thisTile[TILE.CURSOR]=-1;
        
        global.theMap[# tX,tY]=thisTile;
    }
}
//Drawing Tiles In Step Event
GML:
/// @desc Isometric View + General Render
var tileData,viewX,viewY,tileIndex,tileZ,_tileCovered,_tileCursor;

for(var _tX=0;_tX < MAP_W; _tX++)
{
    for(var _tY=0; _tY < MAP_H; _tY++)
    {
        tileData=global.theMap[# _tX, _tY];
        viewX=TileToScreenX(_tX,_tY);
        viewY=TileToScreenY(_tX,_tY);
        
        _tileCursor=tileData[TILE.CURSOR];
        tileIndex=tileData[TILE.SPRITE_FRAME];
        tileZ=tileData[TILE.Z];
        
        if(tileIndex!=0)
        {
            draw_sprite(sStatic,tileIndex-1,viewX,viewY+tileZ);   
        }
        

        if(_tileCursor!=-1)
        {
            _tileCursor=DSListLastValue(tileData[@TILE.CURSOR]);
        }
                
        var _player=global.playerObject;
        
        //CURSOR DRAW
        if(_tileCursor!=-1) draw_sprite(spr_cursor,_tileCursor,viewX,viewY+tileZ-2);
        
    }
}

//Mouse Tile Cursor
if(tileCursorIsVisible)
{
    var mouse_tX=ScreenTo_tX(mouse_x,mouse_y);
    var mouse_tY=ScreenTo_tY(mouse_x,mouse_y);
    mouse_tX=clamp(mouse_tX,0,MAP_W-1);
    mouse_tY=clamp(mouse_tY,0,MAP_H-1);
    var _tile=global.theMap[# mouse_tX,mouse_tY];
    var _x=TileToScreenX(mouse_tX,mouse_tY);
    var _y=TileToScreenY(mouse_tX,mouse_tY);
    var object_on_tile = _tile[TILE.COVERED];
    var _tileCursor = CURSOR.MOUSE
    if (object_on_tile!=noone && object_get_parent(object_on_tile.object_index) = Pobj_enemy)
    {
        _tileCursor = CURSOR.ENEMY;
    }
    
    if(!_tile[TILE.COL]) draw_sprite(spr_cursor,_tileCursor,_x,_y+_tile[TILE.Z]-2)
}

//Possible Path Draw
for(var i=0;i<ds_list_size(possible_movement_path);i++)
{
    var tileData=possible_movement_path[| i];
    var _cur=CURSOR.POSSIBLE_PATH
    var _tX=TileToScreenX(tileData[TILE.tX],tileData[TILE.tY]);
    var _tY=TileToScreenY(tileData[TILE.tX],tileData[TILE.tY])
    draw_sprite(spr_cursor,_cur,_tX,_tY+tileData[TILE.Z]-2);
    if ( i=ds_list_size(possible_movement_path)-1 )
    {
        ds_list_clear(possible_movement_path);
    }
}
I have included some screenshots to help understand problem better:
1. General Game Screenshot
2. Highground tile, which we will sue for 2nd level tilemap
3. Typical 1st level tile.
4. What the sStatic is
5. what the spr_cursor is

I really hope for you, beacuse as a beginner I always have troubles when choosing from coding alternatives as I don't know which one of them is the most efficient.
And good luck to everyone who read this thread!:)
 

Attachments

Rob

Member
Hey - I've been working on this kind of thing for quite a while recently - 19 episodes into making an Isometric Tactics Battle system. Previously to that, I made an XCOM (original game) map creation editor, which needed to have:
  • maps that could be 12 tiles high
  • allow for different things to be on those tiles (like trees/people/walls/doors) etc
  • run smoothly during gameplay!
I settled on using a ds_grid for each "height" and every cell had a list that held data for that tile eg - what should the floor be, is there a wall on the West or North side, is there a tree there?

So that means 12 grids with lots of lists.

I made some pre-defined maps/levels so that I could combine them all into 1 big battle map as in the original game.

In the tutorial series, I just use one grid with lists, but that means you can't have buildings like in XCOM, as if one tile is set to a height of 12, the ground is drawn up to that height, rather than allowing for gaps. I guess you could have extra entries in the list to allow for blank spaces, but I don't like the idea of that because it just means really long lists.

I don't think I've really answered your question but I thought I could at least let you know how I did it.

For optimization, you can draw just what's on screen so I don't think that will be a problem.

This is the xcom map editor:

Tutorial series:
 
Last edited:

Petrik33

Member
Hey - I've been working on this kind of thing for quite a while recently - 19 episodes into making an Isometric Tactics Battle system. Previously to that, I made an XCOM (original game) map creation editor, which needed to have:
  • maps that could be 12 tiles high
  • allow for different things to be on those tiles (like trees/people/walls/doors) etc
  • run smoothly during gameplay!
I settled on using a ds_grid for each "height" and every cell had a list that held data for that tile eg - what should the floor be, is there a wall on the West or North side, is there a tree there?

So that means 12 grids with lots of lists.

I made some pre-defined maps/levels so that I could combine them all into 1 big battle map as in the original game.

In the tutorial series, I just use one grid with lists, but that means you can't have buildings like in XCOM, as if one tile is set to a height of 12, the ground is drawn up to that height, rather than allowing for gaps. I guess you could have extra entries in the list to allow for blank spaces, but I don't like the idea of that because it just means really long lists.

I don't think I've really answered your question but I thought I could at least let you know how I did it.

For optimization, you can draw just what's on screen so I don't think that will be a problem.

This is the xcom map editor:

Tutorial series:
Wow, that is very great stuff, I will research ASAP, hope it will help, and I actually have quite the same system so it should work with our game. Thank you!
 

Rob

Member
You're welcome man I love games that use an Isometric perspective so I'll enjoy seeing you guys progress with your game :)

[EDIT] I forgot to add - the reason I use grids/lists is because it's easy to save them (there are ds functions like ds_grid_read/write and ds_list_read/write - makes saving really easy!)
 
Last edited:
Top