working on aiming

This commit is contained in:
2026-06-04 03:42:07 -04:00
parent c97b0e5cc2
commit cfc13d9350
4 changed files with 115 additions and 22 deletions
+106 -20
View File
@@ -6,13 +6,19 @@ using System.Diagnostics;
public partial class Tower : Sprite2D
{
public bool _hovered, _aiming;
public Vector2 _aimOffset;
public int _launchForce = 1000, _arcIterations = 50;
public float _gravity, _drag;
public Vector2 _aimOffset, _arcEnd;
public List<Vector2> _arc = new();
public Marker2D _offset, _attackSpawn;
public Area2D _area;
public Commander _commander;
public override void _Ready()
{
base._Ready();
_gravity = (float)ProjectSettings.GetSetting("physics/2d/default_gravity");
_drag = (float)ProjectSettings.GetSetting("physics/2d/default_linear_damp");
_area = GetNode<Area2D>("Area");
_offset = GetNode<Marker2D>("Offset");
_attackSpawn = GetNode<Marker2D>("AttackSpawn");
@@ -24,6 +30,11 @@ public partial class Tower : Sprite2D
{
if (_aiming)
{
if (_arcEnd != GetGlobalMousePosition())
{
CalculateLaunchAngle(_attackSpawn.GlobalPosition, GetGlobalMousePosition(), _launchForce, _gravity, _drag);
DrawArc();
}
if (Input.IsActionJustPressed("rightClick"))
{
_commander.UnloadAttack();
@@ -32,14 +43,15 @@ public partial class Tower : Sprite2D
else if (Input.IsActionJustPressed("leftClick"))
{
_aimOffset = GetGlobalMousePosition() - GlobalPosition;
_aimOffset = CalculateLaunchAngle(_attackSpawn.GlobalPosition, GetGlobalMousePosition(), _launchForce, _gravity, _drag);
_commander.ShootCurrentAttack(_aimOffset);
_aiming = false;
}
}
if (Input.IsActionJustPressed("leftClick"))
else if (_hovered)
{
if (_hovered)
if (Input.IsActionJustPressed("leftClick"))
{
_aiming = true;
_commander.LoadAttack(_attackSpawn.Position);
@@ -48,28 +60,102 @@ public partial class Tower : Sprite2D
}
}
public List<Vector2> PredictPath()
public Vector2 CalculateLaunchAngle(Vector2 startPos, Vector2 targetPos, float launchSpeed, float gravity, float drag, int maxIterations = 20)
{
Vector2 velocity = _aimOffset;
float timeBetweenSteps = 0.05f;
Vector2 startPosition = _attackSpawn.Position;
float gravity = -(float)ProjectSettings.GetSetting("physics/2d/default_gravity", 980.0f);
float drag = (float)ProjectSettings.GetSetting("physics/2d/default_linear_damp", 0.0f);
List<Vector2> points = [startPosition];
for (int i = 0; i < 151; i++)
{
velocity.Y += gravity * timeBetweenSteps;
// GD.Print(velocity);
velocity *= (float)Math.Clamp(1.0 - drag * timeBetweenSteps, 0, 1);
Vector2 toTarget = targetPos - startPos;
float baseAngle = toTarget.Angle(); // Directly pointing at the target
points.Add(points[^1] + velocity);
// Pure vertical angle going straight up (-Y is up in Godot)
float straightUpAngle = -Mathf.Pi / 2.0f;
// We use a normalized 0.0 to 1.0 search range to avoid radian sign confusion
float lowT = 0.0f; // 0% = pointing straight at target
float highT = 1.0f; // 100% = pointing straight up
float bestAngle = baseAngle;
float delta = 1.0f / 60.0f; // Matches standard physics step
for (int i = 0; i < maxIterations; i++)
{
float testT = (lowT + highT) / 2.0f;
// Interpolate smoothly between the base angle and straight up
float testAngle = Mathf.LerpAngle(baseAngle, straightUpAngle, testT);
float error = EvaluateSimulationError(testAngle, startPos, targetPos, launchSpeed, gravity, drag, delta);
if (Mathf.Abs(error) < 0.2f)
{
bestAngle = testAngle;
break;
}
// error > 0 means the simulated projectile landed below the target (+Y is down)
if (error > 0)
{
// It fell short or low. We need to loft it higher up (move toward 1.0)
lowT = testT;
}
else
{
// It flew over the target. We need to lower the arc (move toward 0.0)
highT = testT;
}
bestAngle = testAngle;
}
return points;
return Vector2.FromAngle(bestAngle) * _launchForce;
}
// public Dictionary<> Ra
public void DrawArc()
{
Path2D path = _commander._attack.GetNode<Path2D>("PredictedPath");
path.Curve.ClearPoints();
for (int i = 0; i < _arc.Count; i++)
{
path.Curve.AddPoint(_arc[i]);
}
GD.Print(path.Curve.PointCount);
}
private float EvaluateSimulationError(float angle, Vector2 start, Vector2 target, float speed, float gravity, float drag, float delta)
{
Vector2 velocity = new Vector2(Mathf.Cos(angle), Mathf.Sin(angle)) * speed;
Vector2 position = start;
float directionSign = Mathf.Sign(target.X - start.X);
float maxFlightTime = 6.0f;
int totalSteps = (int)(maxFlightTime / delta);
_arc = [start];
for (int step = 0; step < totalSteps; step++)
{
velocity.Y += gravity * delta;
velocity -= velocity * drag * delta;
position += velocity * delta;
_arc.Add(position);
// Check if our projectile crossed the target line on the X axis
bool reachedTargetX = (directionSign >= 0) ? (position.X >= target.X) : (position.X <= target.X);
if (reachedTargetX)
{
return position.Y - target.Y;
}
}
_arcEnd = _arc[^1];
// If it ran out of time or hit a wall before crossing target.X, penalize it heavily
return (position.Y > target.Y) ? 99999f : -99999f;
}
public void StartTurn()
{
if (_commander != null)
{
_commander._actions = _commander._actionsMax;
}
}
public void OnMouseEntered(){
_hovered = true;