[SOLVED] Deleting individual background tile / removing 'wall' tile

C

Carcophan

Guest
Hello everyone!

Not sure I am wording this properly, so I am sorry in advance for any confusion.

I am looking to delete a single 'background tile' from a room, through mouse click.

I can already successfully delete that part of the instance layer, when clicking the mouse, but it does not delete the portion of the background layer UNDER the instance layer too. Meaning - I can delete a 'wall' from the game but not the background image/tile that is auto-tiled under the 'wall' image/sprite/tile. (Hence my problem with naming and wording causing confusion - not sure the finite wording of this).


There is a Tile Layer (called "WallTiles") which is populated with a tileset (called "ts_Walls"). There is also a background layer ("Background"), which is auto-tiled horizontally and vertically throughout the room from a "spr_floor_tile".


I am able to use "tilemap_set(map_id, 0, mx, my);" to delete the ts_Walls from the game room, but I cannot seem to 'move' the character through that new emptied space after I delete it.

I want to be able to make a new 'path' by deleting walls. Note that none of walls the are actually 'wall objects'. The only objects I have in the game are a 'level' object and a 'player' object (where the click/delete action originates), so no collisions are done with walls.

Code:
 A few of the examples that I have tried:
    //ds_grid_set(grid_, mx, my, -1);
    //layer_background_index(back_id, 0);
    //grid_[# mx, my] = FLOOR;
    //ds_grid_set(grid_, mx, my, VOID);
    //ds_grid_set(grid_, mx, my, FLOOR);
    //ds_grid_set(grid_, mx, my, 0);
    //tilemap_set_at_pixel(map_id, tileIndexOfMouse, mx, my);
    //tilemap_set_at_pixel(grid_, tileIndexOfMouse, mx, my);
    //tile_set_index(map_id, 0)
    //tile_set_index(grid_, 0)
    //tile_set_empty(tileIndexOfMouse);
    //tilemap_set(map_id, VOID, mx, my);
    //draw_sprite_ext(spr_floor_tile, 0, mx, my, CELL_WIDTH, CELL_HEIGHT, 0, c_white, 0);       
    //sprite_collision_mask(0, false, 2, 0, 0, 0, 0, 0, 255);
*UPDATED CODE BELOW TO BE MORE INCLUSIVE*
Code:
 The portion of the code that makes the tiles themselves in the room:
//This is the object_Level create event
randomize();
shadow_surface_ = noone;
////get the tile layer maps id
var _wall_map_id = layer_tilemap_get_id("WallTiles");
width_ = room_width div CELL_WIDTH;
height_ = room_height div CELL_HEIGHT;
grid_ = ds_grid_create(width_, height_);
ds_grid_set_region(grid_, 0, 0, width_, height_, VOID);
//create the controller - will set floor tiles as it goes
var _controller_x = width_ div 2
var _controller_y = height_ div 2
var _controller_direction = irandom(3);
var _steps = 400;  //smaller this number the smaller the level (less floor tiles drawn)
var _player_start_x = _controller_x * CELL_WIDTH + CELL_WIDTH / 2;
var _player_start_y = _controller_y * CELL_HEIGHT + CELL_HEIGHT / 2;
instance_create_layer(_player_start_x, _player_start_y, "Instances", obj_Player01);
var _direction_change_odds = 1;
repeat(_steps){  //do 400 times/tiles
  
    grid_[# _controller_x, _controller_y] = FLOOR;
  
    //random the direction
    if(irandom(_direction_change_odds) == _direction_change_odds){
        _controller_direction = irandom(3);  
    }
  
    //move controller around the 'map' to draw auto tiles
    var _x_direction = lengthdir_x(1, _controller_direction * 90);
    var _y_direction = lengthdir_y(1, _controller_direction * 90);
    _controller_x += _x_direction;
    _controller_y += _y_direction;
  
    //ensure the controller didnt go outside the bounds/grid of the room
    if(_controller_x < 2 || _controller_x >= width_ - 2) {
        _controller_x += _x_direction * 2;
    }
    if(_controller_y < 2 || _controller_y >= height_ - 2) {
        _controller_y += _y_direction * 2;
    }
}
//for loop to loop through the grid
for (var _y = 1; _y < height_ - 1; _y++) {
    //no more tiles in this direction, so stop drawing floor tile/grid
    for (var _x = 1; _x < width_ - 1; _x++){
        if(grid_[# _x, _y] != FLOOR){
      
            var _north_tile        = grid_[# _x, _y-1]        == VOID;
            var _west_tile        = grid_[# _x-1, _y]        == VOID;
            var _east_tile        = grid_[# _x+1, _y]        == VOID;
            var _south_tile        = grid_[# _x, _y+1]        == VOID;
      
            //var _tile_index = NORTH * _north_tile + WEST * _west_tile + EAST * _east_tile + SOUTH * _south_tile + 1;
            _tile_index = NORTH * _north_tile + WEST * _west_tile + EAST * _east_tile + SOUTH * _south_tile + 1;
                //removes 'single tile holes' from the random room generation code
                if(_tile_index == 1) {
                    grid_[# _x, _y] = FLOOR;
                  
                }
        }
    }
}  
  
  
  
for (var _y = 1; _y < height_ - 1; _y++) {
    for (var _x = 1; _x < width_ - 1; _x++){
        if(grid_[# _x, _y] != FLOOR){
      
            var _north_tile        = grid_[# _x, _y-1] == VOID;
            var _west_tile        = grid_[# _x-1, _y] == VOID;
            var _east_tile        = grid_[# _x+1, _y] == VOID;
            var _south_tile        = grid_[# _x, _y+1] == VOID;
      
            //var _tile_index = NORTH * _north_tile + WEST * _west_tile + EAST * _east_tile + SOUTH * _south_tile + 1;
            _tile_index = NORTH * _north_tile + WEST * _west_tile + EAST * _east_tile + SOUTH * _south_tile + 1;
          
            tilemap_set(_wall_map_id, _tile_index, _x, _y);
              
        }
    }
}      
  
//from the object_Level draw event:
if not surface_exists(shadow_surface_){
  
    shadow_surface_ = surface_create(room_width, room_height);
  
    surface_set_target(shadow_surface_);
    draw_clear_alpha(c_black, 0);
  
    for (var _y = 0; _y < height_ -1; _y++){
        for(var _x = 0; _x < width_ -1; _x++){
            if grid_[# _x, _y] == FLOOR && grid_[# _x, _y - 1] == VOID {
                draw_sprite_ext(spr_Player01_shadow, 0, _x * CELL_WIDTH, _y * CELL_HEIGHT, 1, 1, 0, c_white, 0.5);  
            }
        }
    }
    surface_reset_target();
}
draw_surface(shadow_surface_, 0, 0);
The end goal here would be to see the 'other' background image, under the primary background. So deleting the primary background would allow us to see through the layer to the pink sub-background image in place.
 
Last edited by a moderator:

TheouAegis

Member
If m x & m y are the coordinates of a mouse and those are what you're using to find the tile, then those same coordinates should not be the coordinates in the grid. Your grid should be something like mx / 32 and my / 32. The mouse position is defined by pixels, the grid coordinates are defined by cells. So if MX is a mouse coordinate, that means it's a pixel value and not a cell value.
 
C

Carcophan

Guest
Thanks, as always, Theou. I tried a few logical variations, changing mouse MX/MY values to just X/Y and also trying things like X/32, Y/32, etc, but I am not getting any further.

Any hints on which of the examples I provided above is the 'right' one I should be experimenting with? I understand (better now) the concepts of mouse pixel versus tile locations and that the different commands would offer different results. And that one is a background tiled image while the other is a tile itself.

I am just confused why 'tilemap_set(map_id, 0, mx , my );' works correctly for the Tile Layer, but I can't get things like "ds_grid_set(grid_, mx / 32, my / 32, 0);" to get rid of the background tile ((This seems like the most logical of the options to me)).
 
C

Carcophan

Guest
All of the syntax that makes sense, is 'depreciated' at this point, and is listed under 'Obsolete Code' in the manual. I have updated my original post to include a larger code sample than what was previously there.

tile_layer_find() and tile_exists for example. It seems that this is all I should need to achieve by goal, but I can't use it because it isn't a valid command and longer:

Code:
 sample from docs1 manual, versus docs2:
  
    var tile = tile_layer_find();
  
    var tile = tile_layer_find(-1000, mouse_x, mouse_y);
   if tile_exists(tile)
   {
       tile_delete(tile);
       }
 
Last edited by a moderator:

TheouAegis

Member
div is the better option instead of /

The 32 is obviously CELL_WIDTH

grid_[#mx div CELL_WIDTH,my div CELL_HEIGHT] = VOID

Setting a tile to 0 like you did is the proper way to delete a tile in GMS2.

And then if none of that works, your issue is elsewhere. Maybe you duplicated the grid and are using the wrong grid for calculating collisions? I don't know. But like I said, if mx and my are just the coordinates of the mouse in the room, then the above code should work.
 
Last edited:
C

Carcophan

Guest
By the way, not sure if you want this, but there's a free package on the marketplace for autotiling which has a function that lets you set/delete a tile from a tilemap and it does the autotiling for the neighboring tiles automatically for you. https://marketplace.yoyogames.com/assets/5055/grid-auto-tile-47
I actually ran across this add-on during my research for a solution. I figured this was a 'last resort' to reverse engineer something like this, versus fixing the tutorial code I had accumulated so far.

I think TheouAegis is right (again) in that it is a duplication of grid components somewhere, just need to poke around some more. I updated the trigger with your suggestion, which makes sense, but still doesn't work, so I will look into both the duplication of grid code - and the add on as a next-step.

EDIT: After downloading and trying out the add-on, this looks pretty much like exactly what I was hoping to achieve. This is awesome. I just have to figure out how to combine the two sets of code so that this code 'procedurally generates' a map like the code listed above, and I am set I think.
 
Last edited by a moderator:

nesrocks

Member
In my game I check for collision directly against the tilemap, there's no extra data or instances.
Code:
if tilemap_get(mytilemap, x, y) != 0
{
    // code here
}
 

nesrocks

Member
Interesting, nice catch. I never set that on collision tiles because in my game objects only collide with autotiled tiles. I only flip/rotate on merely graphical tiles.
 
C

Carcophan

Guest
Thank you all for your continued feedback.

I keep experimenting and getting no where, and it occurred to me that maybe the code IS working... I just didn't know it and it is because I haven't explained my issue/set up correctly.

I have a Background Layer, Instances Layer and a Tile Layer.

I have two objects, the Player and the Level itself, both added to the instance layer. The walls are procedural generated on to the Tile layer and the code I am implementing is successfully removing the tiles from the tile layer, but nothing from the background layer (which my original problem/concern).


But if I just have a Background layer, with an image set to Horizontal and Vertical Tile throughout the room... then there is nothing there that 'built' that background in the code... the background is just a property which happens to have an image horizontally and vertically tiled. So in reality, there is nothing there for the code to delete, right? The background images aren't on their own grid that I can interact with, hence why I am getting no where.


Is this as basic as removing the tiled background and making a different TILE LAYER with the background image??
 
C

Carcophan

Guest
So I think I figured it out!! The bbox of the character was set to check a value that was not being changed when the tile sprite/index itself was being changed. So basically, you were all right!!

I haven't fixed the issue yet, but I am confident that is what the problem is now. Thank you again so much.
 
Top