using Godot;
namespace Predation.Scripts.Lights;
[GlobalClass]
public partial class FlickeringLightBase : Light2D
{
[Export] public string Pattern { get; set; }
[Export] public double Speed { get; set; }
private int _currentIndex;
private double _timeAccumulator;
public override void _PhysicsProcess(double delta)
{
base._PhysicsProcess(delta);
if (string.IsNullOrEmpty(Pattern))
{
return;
}
_timeAccumulator += Speed * delta;
if (_timeAccumulator >= 1.0)
{
_timeAccumulator = 0.0;
_currentIndex = (_currentIndex + 1) % Pattern.Length;
}
Energy = ConvertCharToIntensity(Pattern[_currentIndex]);
}
private float ConvertCharToIntensity(char c)
{
c = char.ToLower(c);
// Map 'a' to 0.0, 'm' to 1.0, 'z' to 2.0
if (c is < 'a' or > 'z')
{
return 0.0f;
}
int index = c - 'a';
return (float)(index / 12.5); // Scale the index to the range [0.0, 2.0]
}
}
The whole idea here is that I can use a pattern of letters to represent a pattern of light intensity, to have flickering lights, very similar to how Valve does it.
However, what I noticed is that I’m unable to Inherit from Light2D, which is an issue because that would mean I need to copy and paste the same code for both DirectionalLight2D and PointLight2D and I’d like to avoid that. Is there a reason why I can’t do this? For context, here’s my issue:
Light2D is abstract which means it cannot be extended by scripting, due to required functionality being unavailable, it’s not meant to be extended with custom code
It’s classes that lack fundamental features to work correctly, and can’t really be solved by scripting, for example 2D lights are just representations of the internal rendering functionality, handling the data and making the rendering side work
Essentially: The base type Light2D doesn’t do the details of lights, and there’s no way in scripting to make use of the shared functionality in Light2D, the specific differences between the different types of lights are handled in those lights themselves, Light2D mainly handles shared properties and some updates, so extending it wouldn’t make it useful without adding a bunch of extra code like virtual functions, but there’s not really any meaning to that, what would you do differently than the existing light types?
Well my issue with that is that I need logic inside said base, and interfaces have no logic. If I create an interface, I still essentially would just copy paste code for all light types. My logic only modifies the Energy value, which is inside the Light2D. That’s why I didn’t think about creating an interface.
As of right now though, I solved this by creating a Component that attaches to any light and modify it’s Energy value that way. Not the solution I wanted but it’s good enough.