Updating the layer color in real time

Godot Version

4.2

Question

Hello,

I am trying to make a simple road building system in 2D top-down game. It requires a user input - first click sets a start point, and second click sets the end point.

When user clicks for the first time and start point is set, code starts to update the end point each frame in _physics_proccess(delta), until user clicks for the second time.

Here are the code blocks:

This part inside the _unhandled_input. It handles the first click:

		if isBuildingRoad == true:
			if isStartPoint == false: 
				road_start_pos = get_global_mouse_position()
				tile_road_start_pos = tile_map.local_to_map(road_start_pos)
				isStartPoint = true

Then I have this. Basically I’m updating end position each frame.

func _physics_process(_delta):

	if isBuildingRoad == true and isStartPoint == true and isEndPoint == false: 
		var tile_mouse_pos = tile_map.local_to_map(mouse_pos)
		temporaryEndPosition(tile_mouse_pos)

And utilizing it this content block. Here I am counting distance, direction and amount of tiles between two points, then looping them through.

func temporaryEndPosition(temp_end_pos : Vector2):
	if temp_coords.size():
		for i in temp_coords.size():
			tile_map.set_cell(road_layer, temp_coords[i], -1)
	temp_coords.clear()
    isObstacleOnRoad = false
	tile_map.set_layer_modulate(road_layer, '#058de9')
	var tiles_amount = (tile_road_start_pos.distance_to(temp_end_pos))
	var tiles_direction = (tile_road_start_pos.direction_to(temp_end_pos))
	var direction_x = round(tiles_direction.x)
	var direction_y = round(tiles_direction.y)
	
	if direction_x != 0 and direction_y == 0 or direction_x == 0 and direction_y != 0 :
		for i in tiles_amount: 
			obstacleGhost.position = tile_map.map_to_local(Vector2(tile_road_start_pos.x+(direction_x*i), tile_road_start_pos.y+(direction_y*i)))
			temp_coords.append(Vector2(tile_road_start_pos.x+(direction_x*i), tile_road_start_pos.y+(direction_y*i)))
			#tile_map.set_cell(road_layer, Vector2(tile_road_start_pos.x+(direction_x*i), tile_road_start_pos.y+(direction_y*i)), 1, Vector2(8, 9))
	buildTempRoad()

I have an Area2D called ‘obstacleGhost’ I want to check if there is any object (node) placed in between two points - start point and end point. I am checking that by placing ‘obstacleGhost’ on each tile. So I have a signal:

func _on_obstacle_ghost_body_entered(body):
	isObstacleOnRoad = true

And finally I’m drawing the line of road (temporary line):

func buildTempRoad():
	var building_color = '#058de9'
	
	if isObstacleOnRoad == true:
		building_color = '#ff001d'
	else:
		building_color = '#058de9'

	for i in temp_coords.size():
		tile_map.set_cell(road_layer, temp_coords[i], 1, Vector2(8, 9))

My expectation was that in each frame this whole loop will happen and if there is an object in between point A and B I will set color to red, otherwise it should be green.

But in current state the road is always green, even if there is an object (object detection works correctly). I assume that it happens due to the fact that temporary road is being updated each frame.

Thanks a lot in advance!

You never use the building_color variable in buildTempRoad()

Yes, indeed, thanks for notice.

I updated the function:

func buildTempRoad():
	var building_color = '#058de9'
	
	if isObstacleOnRoad == true:
		building_color = '#ff001d'
	else:
		building_color = '#058de9'

	for i in temp_coords.size():
		tile_map.set_layer_modulate(road_layer, building_color)
		tile_map.set_cell(road_layer, temp_coords[i], 1, Vector2(8, 9))

But once road turns red, it never turns green back even if the new road is not blocked by any other object.

I tried to reset the value on each frame in ‘func temporaryEndPosition()’ (which is triggered every frame), but in that case road is always green, even if the object is blocking it.

The problem is that I can’t understand when and where I have to set isObstacleOnRoad value to false again.

The body_entered signal is only emitted once when a body enters an area. You set isObstacleOnRoad to true there. Then You set isObstacleOnRoad to false the next time you can temporaryEndPosition() Try to rethink your logic and see if you can untangle it.