TileMap and line of sight for tile based game

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By timbone316

I am using this tutorial (https://www.youtube.com/watch?v=vQ1UGbUlzH4&t=1273s) for Field of View implementation, but I’m having an issue. Once I come to a door that is closed, and try to “move” into it, I instead use the turn to open the door, changing the tile using

map.set_cellv(hero_tile,open_door_tile)

but when I do, my LOS calculation goes haywire for a turn, showing me a ton of empty walls I shouldn’t be able to see. Once I move again, it is fixed. This happens if I change it to any tile id, regardless on whether or not the new tile id is colideable or not. It does NOT howeever happen if I set the tile to the same tile_id, so set_cellv itself is not the issue. Any ideas f what might be happening? Here is my calc_los code:

func calc_los():
#get field of view tilemap reference
var fov_tiles:TileMap=self.map.get_parent().get_node("fov")

#set all cells to black
for tile in self.map.get_used_cells():
    fov_tiles.set_cellv(tile,0)

#capture phsyics state for collisions
var space_state=get_world_2d().direct_space_state

for tile in self.map.get_used_cells():
    #this gets the nearest corner for testing
    var x_dir=1 if tile.x<self.tile.x else -1
    var y_dir=1 if tile.y<self.tile.y else -1
    var test_point=tile_to_px_center(tile.x,tile.y)+Vector2(x_dir,y_dir)*self.map.cell_size/2
    #var test_point=tile_to_px_center(tile.x,tile.y)
    var occlusion=space_state.intersect_ray(tile_to_px_center(self.tile.x,self.tile.y),test_point)

    #if there is no occlusion
    if !occlusion or (occlusion.position-test_point).length()<1:
        fov_tiles.set_cellv(tile,-1)

Here is a visual of what I am experiencing, so you can see the craziness in the second image:

Thanks for any help!

:bust_in_silhouette: Reply From: Zergei

I’m not entirely sure what could be the issue, but I found this on the doc of set_cellv, and maybe it has something to do with your problem:

Note: Data such as navigation polygons and collision shapes are not immediately updated for performance reasons.
If you need these to be immediately updated, you can call update_dirty_quadrants().

So maybe calling update_dirty_quadrants() after map.setcellv(herotile,opendoortile) fixes your issue.

Nope. I had tried that previously. Does not seem to work, or does not fix it.

timbone316 | 2022-02-01 13:30

I’ve been following the tutorial and he mentions calling the update_visuals using the call_deferred() function in order to prevent casting rays before the collision shapes are in the system. Could it be that the openning of your door is being performed in such a way that it invalidates the collision shapes?

Since I don’t know how you implemented the rest of the logic I have to guess.

On your position, I would try debugging and drawing some stuff on screen to help out, like lines for each raycast or position values. I had to do something like that with my fluid dynamic simulation and ended up drawing every simulated tile and relation they had, and found out that way what the issue was.

Another thing I can think of is temporarily making the calc_los() func called with a input key (like spacebar), just to have more control of when it fires and make it easier to debug. I would open the door and them manually trigger the calc_los() to see if its some timing issue, if always happens, or if it happens only the first time I hit the key after opening the door. All of that could help narrow down where the issue is.

Zergei | 2022-02-01 16:02

I had been using call_deferred. I figured out what it was. I had to clear the fov_tiles in the beginning of the function. I couldn’t leave any tiles set on it. So now, i reference the field of view tilemap, clear it, and manually set every tile every turn. Its less efficient, but it works now.

timbone316 | 2022-02-01 16:27

Glad you got it working.

When you mention setting every tile every turn, do you mean on every frame?
I would try only running the fov logic whenever there is a change on the view, such as moving the player, opening doors or enemy movement, otherwise, I don’t think there is any reason to constantly keep updating the fov.

In any case, if its not a huge impact on performance, then it shouldn’t be an issue.

Zergei | 2022-02-01 16:58