Legacy GM Help with ds_grid tiles



  • Ultimately, I'm wanting to be able to change a circular selection of tiles in a ds_grid using a function like "ds_grid_set_disk". I have not been able to get this to work. The method I have been using is to manually select all the tiles that I want to change, and if I'm wanting to destroy tiles in a circle that is bigger than the one I currently have, I have to code it together - this takes forever!
  • So any help with getting the "ds_grid_set_disk" function working would be appreciated!
  • I currently have randomly generated levels that are made using a ds_grid. It all works as I would like it to. It works just about the same as the random level generation tutorial by HeartBeast.

So, I have an object "obj_level", with this code in its Create event (which all works fine):

///obj_level Create

//Resize the room
room_width = (CELL_WIDTH/8) * 360
room_height = (CELL_HEIGHT/8) * 360

//Set the grid
var width = room_width div CELL_WIDTH;
var height = room_height div CELL_HEIGHT;

//Create the grid
grid = ds_grid_create(width, height);

//Fill the grid with empty/air cells
ds_grid_set_region(grid, 0, 0, width, height, bk_air);

//Randomize the world

//Create the controller on the side of the grid
var cx = 0;
var cy = height div 2;

//The odds of changing direction
var odds = 1;

//The odds of going up or down
//Up = 1
//Down = 0
var updown = 1;

//Create the earth
    ds_grid_set(grid, cx, cy, bk_block_dirt);
    if (irandom(odds) = 1)
        cx ++;
    } else {
        if (irandom(updown) = 1)
            cx ++;
            cy ++;
    } else {
            cx ++;
            cy --;

//Fill the crust with dirt tiles
    for(var yy = 1; yy < height; yy ++)
        for(var xx = 0; xx < width; xx ++)
            if (grid[# xx, yy] == bk_block_dirt)
                grid[# xx, yy + 1] = bk_block_dirt;

//Draw the level using the grid
for(var yy = 0; yy < height; yy ++)
    for(var xx = 0; xx < width; xx ++)
        if (grid[# xx, yy] != bk_air)
            tile_add(ds_grid_set(grid, cx, cy, bk_block_dirt), 0, 0, CELL_WIDTH, CELL_HEIGHT, xx * CELL_WIDTH, yy * CELL_HEIGHT, 0)   
  • I'm wanting to be able to destroy the dirt blocks (bk_block_dirt) in a circle of a certain radius, and leave behind nothing (bk_air). So far, I've only been able to get this working with a very time consuming and clunky method, shown below.
This code is in the object "obj_level" Step event:

    var tile_above = tile_layer_find(0, mouse_x, mouse_y - CELL_HEIGHT);        
    var tile_above_left = tile_layer_find(0, mouse_x - CELL_WIDTH, mouse_y - CELL_HEIGHT);  
    var tile_above_right = tile_layer_find(0, mouse_x + CELL_WIDTH, mouse_y - CELL_HEIGHT);
    var tile = tile_layer_find(0, mouse_x, mouse_y);                                           
    var tile_left = tile_layer_find(0, mouse_x - CELL_WIDTH, mouse_y);     
    var tile_right = tile_layer_find(0, mouse_x + CELL_WIDTH, mouse_y);  

    var tile_below = tile_layer_find(0, mouse_x, mouse_y + CELL_HEIGHT);         
    var tile_below_left = tile_layer_find(0, mouse_x - CELL_WIDTH, mouse_y + CELL_HEIGHT);     
    var tile_below_right = tile_layer_find(0, mouse_x + CELL_WIDTH, mouse_y + CELL_HEIGHT); 

if mouse_check_button(mb_left)
    //Center row
    if tile_exists(tile) { tile_delete(tile); }
    if tile_exists(tile_left) { tile_delete(tile_left); }
    if tile_exists(tile_right) { tile_delete(tile_right); }
    //Top row
    if tile_exists(tile_above) {  tile_delete(tile_above); }
    if tile_exists(tile_above_left) { tile_delete(tile_above_left) }
    if tile_exists(tile_above_right) { tile_delete(tile_above_right) }
    //Bottom row
    if tile_exists(tile_below) { tile_delete(tile_below); }
    if tile_exists(tile_below_left) { tile_delete(tile_below_left) }
    if tile_exists(tile_below_right) { tile_delete(tile_below_right) }
  • So, if I wanted to create a circle in the terrain that was any bigger than the circle created here, I'd have to add more variables, such as "var tile_above_above_above_left", etc. This takes forever.
I tried using "ds_grid_set_disk" in the "obj_level" Step event, instead of the method I mention above. For the life of me I cannot get it to work. I must be doing something wrong. Here's the code I used:

///obj_level Step
radius = 5
var gx = scr_mx_to_gx(mouse_x);
var gy = scr_my_to_gy(mouse_y);
if mouse_check_button_pressed(mb_left)
        ds_grid_set_disk(grid, gx, gy, radius, bk_air)
        for(yy = 0 ; yy < height ; yy ++)
        for(xx = 0; xx < width ; xx ++)
            if (grid[# xx, yy] == bk_air)
                if tile_exists(bk_block_dirt) { tile_delete(bk_block_dirt) }

  • I'm aware that once you left click that it goes through the whole grid again. In the end, I'd want it to just look at the grid co-ordinates near where the left click was made. For now, I'm just trying to get it working.

The two variables gx and gy are used to get the x and y of the grid. They use these scripts:


var gx = argument0;

var xcell = gx div CELL_WIDTH;

return xcell;

var gy = argument0;

var ycell = gy div CELL_HEIGHT;

return ycell;

Any help getting circles made in the terrain with something like the function "ds_grid_set_disk" would be appreciated.

I hope this isn't too long and makes sense...



You problem seems less complicated that what you wrote! ;)

An idea:
1- Create a tmp_grid. ds_clear it with 0.(A grid that fits the room!)
2-Select the cell where you want a circle and use ds_grid_set_disk, insert value of 1.
2- Read cell by cell all your room and look for a tile of dirt using tile_layer_find only on cell of your tmp_grid where it's equal to 1.
3- Delete the tile.
4-Destroy the tmp_grid.