Achieving a range effect

Godot Version

v4.2.2.stable.official [15073afe3]

Question

I am making a tower defence game, and I want to add a similar range effect to the one on Bloons TD 6. I want it so that if there is a collision in the way, it highlights in red (see attached image). I’m not really sure how to go about this. So far, to detect a collision, I have a raycast2D. If you knew how to go about this, that would be great!

You have several options. I’ll mention two.

  1. Run a shader on everything that is an obstacle. Pass the circle center and the radius to those shaders via global uniforms and let them alter their color for pixels that are in range.

  2. Project a circular decal onto obstacles.

I have been running into a couple of issues when trying to implement this.

This is a 2D game, so I can not exactly project decals.

To my knowledge, shaders can only detect pixel colours (I’m not the best with shaders). If I wanted to add sprites to these obstacles, how could I detect the obstacles?

Shaders don’t need to “detect” anything. You decide which sprites represent obstacles and to such sprites you assign a shader that overlays the range circle over their normal appearance.

There you go:

shader_type canvas_item;
uniform vec2 center = vec2(400.0, 400.0);
uniform float radius = 230.0;
uniform vec4 range_color: source_color = vec4(1.0, 0.0, 0.0, 0.5);
varying vec2 vertex_world;

void vertex() {
	vertex_world = (MODEL_MATRIX * vec4(VERTEX, 0.0, 1.0)).xy;
}

void fragment() {
	float falloff = distance(center, vertex_world);
	vec4 tex = texture(TEXTURE, UV);
	vec4 tex_in_range = mix(tex, range_color, range_color.a);
	COLOR.rgb = mix(tex_in_range.rgb, tex.rgb, step(radius, falloff));
}

Thanks!
I was able to implement it pretty smoothly into my game.
I have not experimented with shaders much, hats why I was a little confused.

I just noticed a problem with this solution.
It does work as intended, but it does not colour the circle beyond the point of the collision object (see attached image). Is there another way I could achieve this effect?

I’m not sure I get what you mean. You can set the radius in the shader to be larger than collider’s radius. Those are not mutually dependent in any way.

Oh I think I get it. You want “shadows”. You’ll have to use LightOccluder2D nodes and a point light, render that into a separate viewport and composit it over the main viewport.

Thanks again!
I was able to do it without the viewport stuff and just used a LightOccluder2D and a PointLight2D.

1 Like

:+1:
You’d still might need to use a viewport later when the actual graphics come in.