• 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!

GameMaker Creating a Tile in objects create event and then destroying object?

0

0Bennyman

Guest
So this worked perfectly find in GMS 1.4 with the simple
Code:
layer_tile_create(0,x-16,y-16,bcg_HouseWood1,32,32,32,32)
But of course that function is now obsolete so I'm wondering how I could go about doing this? The only solution I have found is having the tiles present in the level and visible and using that data to change the tile. Is there a way that the tiles are not visible in the level? I would rather just do it 1.4 style. I am creating a level editor for my game which is why I need this.

This is the code I got working using the documentation but I'd rather if it wasn't visible and I didn't have to put every single 32x32 tile onto the map.

Code:
global.back_layer = layer_create(10);
global.back_tiles = layer_tilemap_create("Tiles_Wall", 0, 0, bcg_HouseTiles2_tileset, 32, 32);
var lay_id = layer_get_id("Tiles_Wall");
var map_id = layer_tilemap_get_id(lay_id);
var data = tilemap_get_at_pixel(map_id, 0, 0);
data = tile_set_flip(data, true);
tilemap_set_at_pixel(map_id, data, x, y);
Is there a better way of doing this that I'm not seeing?

edit: Just added a bit extra to the bottom code that I missed
 
Last edited by a moderator:
S

Shawn Shipton

Guest
So this worked perfectly find in GMS 1.4 with the simple
Code:
layer_tile_create(0,x-16,y-16,bcg_HouseWood1,32,32,32,32)
But of course that function is now obsolete so I'm wondering how I could go about doing this? The only solution I have found is having the tiles present in the level and visible and using that data to change the tile. Is there a way that the tiles are not visible in the level? I would rather just do it 1.4 style. I am creating a level editor for my game which is why I need this.

This is the code I got working using the documentation but I'd rather if it wasn't visible and I didn't have to put every single 32x32 tile onto the map.

Code:
global.back_layer = layer_create(10);
global.back_tiles = layer_tilemap_create("Tiles_Wall", 0, 0, bcg_HouseTiles2_tileset, 32, 32);
var lay_id = layer_get_id("Tiles_Wall");
var map_id = layer_tilemap_get_id(lay_id);
var data = tilemap_get_at_pixel(map_id, 0, 0);
data = tile_set_flip(data, true);
tilemap_set_at_pixel(map_id, data, x, y);
Is there a better way of doing this that I'm not seeing?

edit: Just added a bit extra to the bottom code that I missed
Do you want the tileset to be moddable or are you ok with it being static?

For static there are some youtube tutorials on this, not to diminish any others, but my favorite channels are are GM Wolf and Shaun Spaulding, Shaun has done some tutorials for YoYo Games regarding the GMS2, check out that channel as well.

Tiles sets GMS2, GM Wolf -

For moddable, as in my case, the only way I know is to do it tile by tile, using loops or ds_grids.
I had a similar issue with this post,
https://forum.yoyogames.com/index.php?threads/external-sprite-files-for-tilesets-in-gml.26003/
one day I will post how I did it with loading tilesets when I get all the kinks out.
 
Last edited by a moderator:
0

0Bennyman

Guest
I need the tiles to be created on an objects position when it is created not done via the editor, he did mention it right at the end but not explain any of it. I'm pretty familiar with doing it in the editor but unfortunately that's not what I need since I'm making a level editor and need tiles created when certain objects are loaded. Not sure what you mean by loops or ds_grids, is there a way to store tiles in them and load them when needed?
 
S

Shawn Shipton

Guest
Not sure what you mean by loops or ds_grids, is there a way to store tiles in them and load them when needed?
I was referring to loading tilesets as sprites from external files and building your room tiles from that, which require looping through ds_grids or arrays to place each tile.

I have no prior experience with anything other than GMS2, so I can't be of much help in converting an obsolete way of doing things.

I do not know how your level editor works in GMS1.4 but the way I can picture doing it is almost exactly the way GMS2 does the tileset editor for the room and you could use ds_grid or a 2d array to store the tile_index, then save them to a file to be retrieved at will.

http://docs2.yoyogames.com/source/_..._reference/rooms/tilemaps/tile_get_index.html
 
0

0Bennyman

Guest
I was referring to loading tilesets as sprites from external files and building your room tiles from that, which require looping through ds_grids or arrays to place each tile.

I have no prior experience with anything other than GMS2, so I can't be of much help in converting an obsolete way of doing things.

I do not know how your level editor works in GMS1.4 but the way I can picture doing it is almost exactly the way GMS2 does the tileset editor for the room and you could use ds_grid or a 2d array to store the tile_index, then save them to a file to be retrieved at will.

http://docs2.yoyogames.com/source/_..._reference/rooms/tilemaps/tile_get_index.html
For GMS1 I was literally just using that top code and it would work fine. I'm guessing I would need to draw the tiles(Put them in via the editor) first and then save the data on those tiles, I could then hide the tiles and just use what was stored in the ds_grid? I'd rather not have a whole chunk of code though just for 1 32x32 tile considering I have 20+ tilesets with atleast 10 in each, it's odd that you can't just create the tile anymore, bit disappointing but I guess if it has to be done then it has to be done.
 
S

Shawn Shipton

Guest
For GMS1 I was literally just using that top code and it would work fine. I'm guessing I would need to draw the tiles(Put them in via the editor) first and then save the data on those tiles, I could then hide the tiles and just use what was stored in the ds_grid? I'd rather not have a whole chunk of code though just for 1 32x32 tile considering I have 20+ tilesets with atleast 10 in each, it's odd that you can't just create the tile anymore, bit disappointing but I guess if it has to be done then it has to be done.
You wouldn't have to hide the tiles just replace the tile_index id; if you are just changing a couple tiles or what the user wants to change then I wouldn't use a grid, maybe a ds map instead and name the key x_y; there is direct file saving functions with ds_map too.
I kinda do something similar with saving/loading chunks but I have to store the x_y of each tile located in the external tileset bitmap, that anyone can mod, and I use buffers instead, since I have to load and place all tiles.

http://docs2.yoyogames.com/source/_..._reference/data_structures/ds maps/index.html
 
0

0Bennyman

Guest
You wouldn't have to hide the tiles just replace the tile_index id; if you are just changing a couple tiles or what the user wants to change then I wouldn't use a grid, maybe a ds map instead and name the key x_y; there is direct file saving functions with ds_map too.
I kinda do something similar with saving/loading chunks but I have to store the x_y of each tile located in the external tileset bitmap, that anyone can mod, and I use buffers instead, since I have to load and place all tiles.

http://docs2.yoyogames.com/source/_build/3_scripting/4_gml_reference/data_structures/ds maps/index.html
Hey Shawn sorry for this late reply, I've been trying to figure out how to properly do that (Never used ds_maps before or tried saving tiles) was wondering if you could help me out a bit if possible, no tutorials online seem to show how to do this and nothing I do seem to save the tile and then load it, I tried pretty much reusing the script I used initially but adding the map to it but I can't seem to get it to work. I think the answer is yes to this but I'm gonna ask anyway, can this be saved globally and then called? Or does it have to be in the room? Thanks for the help so far.
 
S

Shawn Shipton

Guest
Hey Shawn sorry for this late reply, I've been trying to figure out how to properly do that (Never used ds_maps before or tried saving tiles) was wondering if you could help me out a bit if possible, no tutorials online seem to show how to do this and nothing I do seem to save the tile and then load it, I tried pretty much reusing the script I used initially but adding the map to it but I can't seem to get it to work. I think the answer is yes to this but I'm gonna ask anyway, can this be saved globally and then called? Or does it have to be in the room? Thanks for the help so far.
Because I am still in the learning stages of GML, I am not sure if my solution qualifies for "Properly do that" definition but it seems to work for me. In my solution the world can be somewhat infinite, not limited to memory (currently it runs at 112MB of ram) but only by hard drive space; my concept came from Minecraft world generation, chunking and loading.

Explanation:
Tilemap is 2048 x 2048 px containing 64 x 64 32px tiles
Biome size is 64 x 64 tiles
Main room is 2 x 2 Biomes and the tiles are held in a ds_grid (128 x 128 tiles) that is updated based on the player's location in the world.
The room wraps vertically and horizontally; I have a little issue I am trying to work out that when the player wraps the room it flickers once during transition to the other side of the room, but otherwise it is pretty clean.
The biomes are saved in binary files with the x_y of the biome that it belongs to as the name (biome_0_0.dsg) for example, with each 16 bit entry holding the tile location of the tilemap 8 bits for x coordinate and the last 8 for y with a capability of 256 x 256 tilemap grid, starting at the 0,0 and wrapping too 64, 64 which is 64 * 64 * 2 bytes with the file size being 8192; you can add whatever you like as far as other data too and just increase the byte count.

The meat and potatoes:
In this example I created the whole world in a ds_grid of tiles because I was playing with and learning cellular automata to create a random world with water and sand on a grass generated world.
Because this example takes 1GB of ram and 2 minutes to save the world to biome files for 128 x 128 biomes, I have started working on a smaller approach that is generated while playing the game, getting even closer to the Minecraft concept.
Also, some of the value are still hard coded or as GMWolf likes to refer as "Magic Numbers", later on a config file will be created/used based on user preferences; it is very incomplete, because I have only been working on this a little over a month with a 40-60hr per week regular job taking up most of my time.

Creating/Saving the world
Code:
//create world grid with grass tiles
var grid  = ds_grid_create(8192, 8192); //grid is created and destroyed in this script to prevent memory leaks.
var val = 17 + (18 << 8); //grass tile at tilemap grid 17,18
ds_grid_set_region(grid, 0, 0, 8192, 8192, val);

//use cellular automata to add water, sand, etc based on biome types.

//save world to files
var worldBiomes_1d = global.worldBiomes_1d;
var biomeTiles_1d = global.biomeTiles_1d;
var biomeTiles_2d = power(biomeTiles_1d, 2) * 2;
var bfr = buffer_create(biomeTiles_2d, buffer_fixed, 2);
for (var by = 0; by < worldBiomes_1d; by++)
{
    for (var bx = 0; bx < worldBiomes_1d; bx++)
    {
        buffer_seek(bfr, buffer_seek_start, 0);
        for (var ty = 0; ty < biomeTiles_1d; ty++)
        {
            for (var tx = 0; tx < biomeTiles_1d; tx++)
            {
                buffer_write(bfr, buffer_u16, ds_grid_get(grid, tx + (bx * biomeTiles_1d), ty + (by * biomeTiles_1d)));
            }
        }
         var fn = "biomes/biome_" + string(bx) + "_" + string(by) + ".dsg";
        buffer_save(bfr, fn);
    }
}
buffer_delete(bfr);
ds_grid_destroy(grid);
Loading/drawing the world
terrain object, you can put this in the player obj and save on some processor time for global variable accessing but I like to split things up as my player obj is pretty hefty in itself.

Create Event
Code:
bmTls_1d = global.biomeTiles_1d;
tl_px_1d = global.tileSize_px_1d;
bfrDataBytes = global.bufferDataSizeBytes;
terrain_spr = global.terrain_sprMap;
plyr_x = global.player_x; //updated in obj_player
plyr_y = global.player_y; //updated in obj_player

gridTiles = bmTls_1d * 2;
roomGrid  = ds_grid_create(gridTiles, gridTiles);
bufSize = power(bmTls_1d, 2) * bfrDataBytes;
step = 0;
Step event
Code:
if (alarm[0] == -1)
{
    alarm[0] = room_speed;
    var h = step >> 1;
    var w = step & 1;
    // the room size is 2x squared biome chunks
    var bx = global.biome_x + w; //set in obj_player
    var by = global.biome_y + h; //set in obj_player
    var fn = "biomes/biome_" + string(bx) + "_" + string(by) + ".dsg";
    if (file_exists(fn))
    {
        var buffer = buffer_load(fn);
        if (buffer_get_size(buffer) == bufSize)
        {
            //loop thru buffer and pop room tile grid
            for (var i = 0; i < (bufSize / 2); i++)
            {
                var tile = buffer_read(buffer, buffer_u16);
                ds_grid_set(roomGrid, (i % 64) + (w * 64), (i div 64) + (h * 64), tile);
            }
        }
        buffer_delete(buffer);
    }

    step = (step >= 3) ? 0 : step + 1;
}
Draw event
Code:
plyr_x = global.player_x;
plyr_y = global.player_y;

var plyr_tile_x = plyr_x div 32;
var plyr_tile_y = plyr_y div 32;

//draw 2 tiles around the camera as buffer
var draw_tiles_width = (cam_w div tl_px_1d) + 4;
var draw_tiles_height = (cam_h div tl_px_1d) + 4;

var px_x = (plyr_tile_x * tl_px_1d) - (cam_w div 2) - (tl_px_1d * 2);
var px_y = (plyr_tile_y * tl_px_1d) - (cam_h div 2) - (tl_px_1d * 2);

var tx = px_x div tl_px_1d;
var ty = px_y div tl_px_1d;

for (var i = 0; i < draw_tiles_height; i++)
for (var j = 0; j < draw_tiles_width; j++)
{
    var val = ds_grid_get(roomGrid, tx + j, ty + i);
    var tpx_x = (val & $00FF) * tl_px_1d;
    var tpx_y = (val >> 8) * tl_px_1d;

    draw_sprite_part(terrain_spr, 0, tpx_x, tpx_y, tl_px_1d, tl_px_1d, px_x + (j * tl_px_1d), px_y + (i * tl_px_1d));
}

This all works well but plenty of room for optimization and clean up; like I said I am just learning GML and getting use to it's library and doing a lot of playing with ideas so you will see a lot of inconsistencies but hopefully you get the fundamental idea on how I did it.

EDIT:

As an after thought, the ds_grids could easily be replaced with 2d arrays and then you not need to worry about the global issue with ds_grid and memory leaks; like I said optimization is needed.
 
Last edited by a moderator:
Top