flash-effect for separate tile

Godot Version

`4.5 stable

Question

hello there! im working on my small top-down 2d game about tanks
so here is my problem:
i want to implement wall breaking feature. my walls are placed as tilemaplayer. to make visible, that u can actually break this wall, I decided to do this with the flash effect when hitting a wall, but I came across the fact that all the tiles of the wall are highlighted, and I need to implement it so that only the tile that is hit is highlighted.

here are my scripts:
##projectile.gd

extends Area2D

@export var speed: float = 600
@export var damage: float = 1
@export var lifeTime: float = 2.00

func explode():
	queue_free()
	#speed = 0
	#$Sprite.hide()
	#$Explosion.show()
	#$Explosion.play()

func _on_body_entered(body: Node2D) -> void:
	$SFXHit.play()
	explode()
	if body.has_method("take_damage"):
		if body is TileMapLayer:
			body.take_damage(damage, body.local_to_map(global_position))#emit_signal("get_cell_vector", body.local_to_map(global_position))
		else:
			body.take_damage(damage)
			
func _on_life_timer_timeout() -> void:
	explode()

func _ready() -> void:
	$LifeTimer.wait_time = lifeTime
	$LifeTimer.start()
	
func _process(delta: float) -> void:
	position += transform.x * speed * delta



func _on_explosion_animation_finished() -> void:
	pass
	#queue_free() # Replace with function body.

##tilemaplayer.gd

extends TileMapLayer

@onready var flash_shader = load("res://shaders/hitFlashEffect.gdshader")
var cell : TileData

func take_damage(amount, cell_vector : Vector2):
	cell = get_cell_tile_data(cell_vector)
	cell.set_custom_data("health", get_cell_tile_data(cell_vector).get_custom_data("health") - amount)
	flash(cell)

func flash(cell : TileData):
	$FlashTimer.start()
	var flash_material = ShaderMaterial.new()
	flash_material.shader = flash_shader.duplicate()
	cell.material = flash_material
	cell.material.set_shader_parameter("flash_modifier", 0.5)



func _on_flash_timer_timeout() -> void:
	cell.material.set_shader_parameter("flash_modifier", 0.0)

##hitFlashEffect.gdshader

shader_type canvas_item;

uniform vec4 flash_color: source_color = vec4(1.0);
uniform float flash_modifier: hint_range(0.0, 1.0, 0.1) = 0;

void fragment() {
	 vec4 color = texture(TEXTURE, UV);
	color.rgb = mix(color.rgb, flash_color.rgb, flash_modifier);
	COLOR = color;
}

link to demonstration 2025-09-16 23-30-17

many thanks!!!

Changing the TileData like that should affect all tiles that use these data. I’m not entirely sure, but from looking into the docs, _tile_data_runtime_update() could be what you’re looking for?

extends TileMapLayer

@onready var flash_shader = preload("res://shaders/hitFlashEffect.gdshader") 
var tile_health: Dictionary = {}

func take_damage(amount: float, cell_vector: Vector2) -> void:
	if get_cell_tile_data(cell_vector) != null and get_cell_tile_data(cell_vector).get_custom_data("health") > 0.0:
		print("Наносимый урон: ", amount, "; Vector2: ", cell_vector)
		var current_health: float
		if tile_health.has(cell_vector):
			current_health = tile_health[cell_vector]
			print("Текущее здоровье тайла: ", current_health)
		else:
			current_health = get_cell_tile_data(cell_vector).get_custom_data("health")
			tile_health[cell_vector] = current_health
			print("Тайл новый, устанавливаем начальное здоровье: ", current_health)
		
		current_health -= amount
		tile_health[cell_vector] = current_health
		print("Новое здоровье тайла: ", current_health)

		if current_health <= 0:
			set_cell(cell_vector, 2, Vector2(2, 0), 0)
			tile_health.erase(cell_vector)
		else:
			flash(cell_vector)

func flash(cell_vector: Vector2):
	var shader_sprite = Sprite2D.new()
	shader_sprite.position = map_to_local(cell_vector)
	shader_sprite.texture = get_cell_texture(cell_vector)
	var flash_material = ShaderMaterial.new()
	flash_material.shader = flash_shader.duplicate()
	shader_sprite.material = flash_material
	shader_sprite.material.set_shader_parameter("flash_modifier", 0.5)
	add_child(shader_sprite)
	var timer = Timer.new()
	timer.wait_time = 0.1
	timer.one_shot = true
	add_child(timer)
	timer.start()
	timer.timeout.connect(func(): on_flash_timeout(shader_sprite))
	

func get_cell_texture(coord:Vector2i) -> Texture:
	var source_id := get_cell_source_id(coord)
	var source:TileSetAtlasSource = tile_set.get_source(source_id) as TileSetAtlasSource
	var altas_coord := get_cell_atlas_coords(coord)
	var rect := source.get_tile_texture_region(altas_coord)
	var image:Image = source.texture.get_image()
	var tile_image := image.get_region(rect)
	return ImageTexture.create_from_image(tile_image)

func on_flash_timeout(sprite : Sprite2D):
	sprite.queue_free()

okay, so i got it to work by this way

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.