110 lines
4 KiB
C#
110 lines
4 KiB
C#
using System;
|
|
using System.Diagnostics;
|
|
using Godot;
|
|
|
|
public partial class Flashlight : Node
|
|
{
|
|
[Signal]
|
|
public delegate void EnergyOutEventHandler();
|
|
[Signal]
|
|
public delegate void ChargedEventHandler();
|
|
|
|
[Export] public Player Player;
|
|
[Export] public GameCamera Camera;
|
|
|
|
[Export] public Node2D Circle;
|
|
[Export] public Node2D PlayerCircle;
|
|
[Export] public Polygon2D Polygon;
|
|
|
|
[Export] public CollisionShape2D CollisionCircle;
|
|
[Export] public CollisionShape2D CollisionPlayerCircle;
|
|
[Export] public CollisionPolygon2D CollisionPolygon;
|
|
[Export] public CanvasGroup FlashlightGroup;
|
|
|
|
[Export] public Curve BrightnessCurve;
|
|
|
|
[Export] public AudioStreamPlayer CrankSoundPlayer;
|
|
|
|
private float FlashlightRadius = Constants.MaxFlashlightRadius;
|
|
private float FlashlightEnergy = 0;
|
|
private float FlashlightChargeTimeout = 1;
|
|
private bool _isDischarged = true;
|
|
|
|
public override void _Ready()
|
|
{
|
|
base._Ready();
|
|
|
|
if (CollisionCircle.Shape is not CircleShape2D)
|
|
throw new Exception("Invalid collision shape on the circle");
|
|
if (CollisionPlayerCircle.Shape is not CircleShape2D)
|
|
throw new Exception("Invalid collision shape on the player circle");
|
|
}
|
|
|
|
public override void _PhysicsProcess(double delta)
|
|
{
|
|
var playerScreenCenterPosition = Player.Position - Camera.Position;
|
|
var flashlightScreenCenterPosition = Camera.FlashlightPosition - Camera.Position;
|
|
|
|
var playerScreenPosition = playerScreenCenterPosition + Constants.HalfScreenSize;
|
|
PlayerCircle.Position = playerScreenPosition;
|
|
CollisionPlayerCircle.Position = playerScreenPosition;
|
|
|
|
var d = Camera.FlashlightPosition.DistanceTo(Player.Position);
|
|
FlashlightRadius = Mathf.Lerp(Constants.MinFlashlightRadius, Constants.MaxFlashlightRadius,
|
|
Mathf.Clamp(d - Constants.MinFlashlightDistance, 0,
|
|
Constants.MaxFlashlightDistance - Constants.MinFlashlightDistance) / Constants.MaxFlashlightDistance);
|
|
|
|
var flashlightScreenPosition = flashlightScreenCenterPosition + Constants.HalfScreenSize;
|
|
var flashlightScale = FlashlightRadius / Constants.MaxFlashlightRadius;
|
|
Circle.Position = flashlightScreenPosition;
|
|
Circle.Scale = new Vector2(flashlightScale, flashlightScale);
|
|
CollisionCircle.Position = flashlightScreenPosition;
|
|
((CircleShape2D)CollisionCircle.Shape).Radius = FlashlightRadius;
|
|
|
|
if (d <= FlashlightRadius)
|
|
Polygon.Visible = false;
|
|
else
|
|
{
|
|
Polygon.Visible = true;
|
|
|
|
var a = Mathf.Sqrt(d * d - FlashlightRadius * FlashlightRadius);
|
|
var xy2 = Camera.FlashlightPosition - Player.Position;
|
|
var angle = xy2.Angle();
|
|
|
|
var arcsinRd = Mathf.Asin(FlashlightRadius / d);
|
|
var dslkhjdsflkhjsdfhlkjdfsjlk = angle + arcsinRd;
|
|
var xy3 = a * new Vector2(Mathf.Cos(dslkhjdsflkhjsdfhlkjdfsjlk), Mathf.Sin(dslkhjdsflkhjsdfhlkjdfsjlk));
|
|
var dslkhjdsflkhjsdfhlkjdfsjlk2 = angle - arcsinRd;
|
|
var xy4 = a * new Vector2(Mathf.Cos(dslkhjdsflkhjsdfhlkjdfsjlk2), Mathf.Sin(dslkhjdsflkhjsdfhlkjdfsjlk2));
|
|
|
|
var polygon = new[]
|
|
{ playerScreenPosition, playerScreenPosition + xy3, playerScreenPosition + xy4 };
|
|
Polygon.Polygon = polygon;
|
|
CollisionPolygon.Polygon = polygon;
|
|
}
|
|
|
|
FlashlightChargeTimeout = Mathf.Clamp(FlashlightChargeTimeout - (float)delta, 0, 1);
|
|
if (Input.IsActionJustPressed("flashlight_charge") && FlashlightChargeTimeout <= 0)
|
|
{
|
|
EmitSignal(SignalName.Charged);
|
|
_isDischarged = false;
|
|
FlashlightChargeTimeout = 1;
|
|
FlashlightEnergy += Constants.FlashlightEnergyPerCharge;
|
|
var rng = new RandomNumberGenerator();
|
|
CrankSoundPlayer.PitchScale = rng.RandfRange(1f, 1.15f);
|
|
CrankSoundPlayer.Play();
|
|
}
|
|
|
|
FlashlightEnergy = Mathf.Clamp(FlashlightEnergy - (float)delta * Constants.FlashlightDischargeModifier,
|
|
0, Constants.MaxFlashlightEnergy);
|
|
FlashlightGroup.Modulate =
|
|
new Color(BrightnessCurve.Sample(FlashlightEnergy / Constants.MaxFlashlightEnergy), 1, 1, 1);
|
|
CollisionCircle.Disabled = CollisionPlayerCircle.Disabled = CollisionPolygon.Disabled = FlashlightEnergy < 10;
|
|
|
|
if (!_isDischarged && FlashlightEnergy < 5)
|
|
{
|
|
EmitSignal(SignalName.EnergyOut);
|
|
_isDischarged = true;
|
|
}
|
|
}
|
|
}
|