How do I change values based on distance from a Light2D node?

Godot Version
Godot 4.2

I’m trying to add a game mechanic to my 2d platformer where the player turns invisible when in the dark and to show that they are invisible, I want to lower the sprite opacity. My original idea was to find the distance between the player and light source and then set the sprite’s modulate value like so:
var light_distance = global_position.distance_to(torch.global_position)
player_animation.modulate.a = 255 - light_distance

I had assumed that it would cap to 0 if it went into the negatives and cap at 255 if it went above it but when I tested it, I didn’t get the functionality I wanted. It instantly changes to and from 100% and 0% opacity and it does so at certain areas that are nowhere near my light sources. I figured maybe it wasn’t capping the values like I expected so I changed my code to this:
var light_distance = global_position.distance_to(torch.global_position)
if light_distance > 255:
player_animation.modulate.a = 0
else:
if light_distance < 0:
player_animation.modulate.a = 255
else:
player_animation.modulate.a = 255 - light_distance

I’m still having the same problem though. Any ideas?

The root of your problem is that Alpha exists on a 0 to 1 scale, not 0 to 255. So there’s only a tiny subpixel range of light_distance where subtracting it from 255 will result in anything half-transparent.

However, I want to suggest a more flexible overall solution where you won’t need to have an “if” statement at all and will also be able to manually tweak the falloff of that transparency. Here’s what you need:

@export var curve : Curve
func _process(_delta) -> void:
	var light_distance = global_position.distance_to(torch.global_position)
	player_animation.modulate.a = curve.sample(light_distance / 300)

Now, when you add that export var, you’ll see your Curve in the inspector. I suggest inverting it, so the less is your distance (x axis of the curve), the more the alpha (y axis of the curve). Here’s how I set mine up:


Note that I left the y of the second point at 0.1 instead of 0 - that’s just to be able to see the sprite even if it’s “transparent”. Feel free to tweak both points and their tangents (those make the curve steeper or flatter) - either in the editor or by assigning values directly.

You’ll also notice the “magic number” 300 in the script: that’s the distance in pixels that gets treated as 1 (fully away from the lantern). Feel free to tweak that too depending on your needs.

1 Like

Thank you! I’ll try this out when I get the time. I just started Godot about a week ago so I’m kinda just getting by with the most basic of functions and learning as I go. You’ve given me something new to look into now though with the curve variable. :+1:

1 Like