Hey everyone!

I'm attempting to make a mechanic where the player (and other things) can fracture a tile. That fractured tile will check the nearby tiles, and if any of those are already fractured, they will break and fracture will travelâ€”checking every tile around those tiles, and so on.

That's where my issues lies. I have difficulty looping this without the program freezing.

Example code:

``````func set_tile_effect(tile, effect_name) -> void:

grid[tile.x][tile.y][1] = effect_name

match effect_name:
"GROUND":
pass
"FRACTURE":

set_cellv(tile, tile_frac)

# we check the surrounding tiles four (no diagonals)

# remove the first member, since it is the orig tile

# check if these tiles are already frac'ed and append them
var tile_state = check_tile_state(available_tile)
if tile_state == "FRACTURE":
``````

So this is the basic mechanic. My problem lies in what to do after appending those tiles.
Is there a way I can run this method again on each of the tiles we've stored?
So that it checks the exact same logic for each tile, and continuing until there are no more tiles to spread to.

I hope this is enough, but if more info is needed feel free to comment.

in Engine

I hope this is enough [information]

Well, it would certainly help to know when and where `set_tile_effect` is called, what the `reachable_tiles_mapped`- or `check_tile_state`-methods do or if you're only checking the direct neighbor cells or consider diagonal neighbors ones as well.

That being said, as long as you don't keep a list of visited tiles you'll always end up with an endless loop and your game freezing. Here's an example for direct neighbors:

``````extends TileMap

const directions = [
Vector2.UP,
Vector2.RIGHT,
Vector2.DOWN,
Vector2.LEFT
]

const BROKEN_TILE_ID = -1
const FRACTURED_TILE_ID = 1

var cells_to_check = []

var cell = Vector2(2, 2)
fracture_tile(cell)

func fracture_tile(cell : Vector2):
set_cellv(cell, FRACTURED_TILE_ID)

while not cells_to_check.empty():

cells_already_visited = [] # reset in the end

for direction in directions:
var neighbor_cell = cell + direction
cells_to_check.push_back(neighbor_cell)

if get_cellv(cell) == FRACTURED_TILE_ID:
set_cellv(cell, BROKEN_TILE_ID)
``````
by (10,247 points)

Hey Njamster!

I will have to give this code a try! I had come to my own ... less than efficient solution in the mean time.

``````func set_tile_effect(map_pos, effect_name) -> void:

grid[map_pos.x][map_pos.y][1] = effect_name

match effect_name:
"GROUND":
pass
"FRACTURE":
set_cellv(map_pos, tile_type.FRACTURE)

check_surrounding_tiles(map_pos, 1, "FRACTURE")
``````

So that was very straight forward, just check the effect name given when the method is called and check those again the two (and later more) effects.

Then I call `check_surrounding_tiles()`, which is how I tried to append things. It .. works actually but looking at yours, this is probably far from the best way of resolving this.

``````func check_surrounding_tiles(tile, reach, tile_eff) -> void:
# we check the surrounding tiles

# remove the first member, since it is the orig tile

# check if these tiles are already frac'ed and append them
var tile_state = check_tile_state(available_tile)
if tile_state == tile_eff:

var tile_state = check_tile_state(i)
if tile_state == tile_eff:

``````

And then `check_surrounding_tiles()` calls `set_multi_tile_effect` which is nearly a carbon copy of the first method settileeffect() but one that allows looping and destroys the tiles instead of fracturing them.

``````func set_multi_tile_effect(tiles, effect_name) -> void:
for tile in tiles:

grid[tile.x][tile.y][1] = effect_name

match effect_name:
"GROUND":
pass
"FRACTURE":
remove_tile(tile)
``````

result can be seen here:
https://media.giphy.com/media/RNQRRtR4YiFUFlgQ1S/giphy.gif

I've run into an entirely new problem, which has to do with my grid array. When I try to target tiles that sit along the left bottom or upper right edge the program crashes saying that my array doesn't hold a certain number.
My grid code must have some hilarious mistakes in it because it works different based on if my playing field is set on top of the origin point in godot, or to the right of it, or even further to the right and down slightly.

I thought the tilemap methods (and my own) only considered the tilemap as it stood, not it's location relative to the origin point. Put for some reason it messes greatly with the arrays I generate.

Anyway that's a totally different problem, it only popped up when I ''fixed'' my fracturing problem.
Thanks for the help again :)