Advertisement
kubpica

drut

Mar 14th, 2021 (edited)
77
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 6.62 KB | None | 0 0
  1. using Godot;
  2. using System.Collections.Generic;
  3.  
  4. public class Drut2D : Node2D
  5. {
  6.     private class Wire
  7.     {
  8.         private List<Segment> segments = new List<Segment>();
  9.         public float TotalDistance { get; private set; }
  10.  
  11.         public Wire(Segment firstSegment)
  12.         {
  13.             addSegment(firstSegment);
  14.         }
  15.  
  16.         private void addSegment(Segment seg)
  17.         {
  18.             segments.Add(seg);
  19.             TotalDistance += seg.TotalDistance;
  20.         }
  21.  
  22.         public void AttachNextSegment(Vector2 offsetToMiddle, float r, float y, bool toRight)
  23.         {
  24.             var end = segments[segments.Count - 1].EndPoint;
  25.             var seg = new Segment(end, end + offsetToMiddle, r, y, toRight);
  26.             addSegment(seg);
  27.         }
  28.  
  29.         public void Draw(CanvasItem c)
  30.         {
  31.             foreach (var s in segments)
  32.             {
  33.                 s.Draw(c);
  34.             }
  35.         }
  36.  
  37.         public void DrawRing(CanvasItem c, float atDistance)
  38.         {
  39.             foreach (var s in segments)
  40.             {
  41.                 var sd = s.TotalDistance;
  42.                 if (atDistance > sd)
  43.                 {
  44.                     atDistance -= sd;
  45.                     continue;
  46.                 }
  47.                 else
  48.                 {
  49.                     s.DrawRing(c, atDistance);
  50.                     return;
  51.                 }
  52.             }
  53.         }
  54.     }
  55.  
  56.     private class Segment
  57.     {
  58.         private static Color color = new Color(1, 0, 0);
  59.  
  60.         private Vector2 xStart;
  61.         private Vector2 xEnd;
  62.         private Vector2 center;
  63.         private float r;
  64.         private Vector2 yStart;
  65.         private Vector2 yEnd;
  66.         private float startAngle;
  67.         private float endAngle;
  68.         private bool toRight;
  69.  
  70.         private float xDistance;
  71.         private float arcDistance;
  72.         private float yDistance;
  73.  
  74.         public Vector2 EndPoint => yEnd;
  75.         public float TotalDistance => xDistance + arcDistance + yDistance;
  76.  
  77.         public Segment(Vector2 startPoint, Vector2 middlePoint, float r, float y, bool toRight = false)
  78.         {
  79.             this.toRight = toRight;
  80.  
  81.             // Calc the x fragment
  82.             var direction = (middlePoint - startPoint).Normalized();
  83.             xStart = startPoint;
  84.             xEnd = middlePoint - direction * r;
  85.             xDistance = (xEnd - xStart).Length();
  86.  
  87.             // Calc the arc fragment
  88.             this.r = r;
  89.  
  90.             var perp = direction.Perpendicular();
  91.             if (toRight)
  92.                 perp *= -1;
  93.  
  94.             center = xEnd + perp * r;
  95.             yStart = middlePoint + perp * r;
  96.  
  97.             startAngle = (yStart - center).Angle();
  98.             endAngle = (xEnd - center).Angle();
  99.             if (Mathf.Abs(endAngle - startAngle) > Mathf.Pi)
  100.             {
  101.                 if (startAngle <= 0)
  102.                     startAngle += Mathf.Pi * 2;
  103.                 if (endAngle <= 0)
  104.                     endAngle += Mathf.Pi * 2;
  105.             }
  106.             arcDistance = Mathf.Abs(endAngle - startAngle) * r;
  107.  
  108.             // Calc the y fragment
  109.             yEnd = yStart + perp * y;
  110.             yDistance = y;
  111.         }
  112.  
  113.         public void Draw(CanvasItem c)
  114.         {
  115.             c.DrawLine(xStart, xEnd, color, 5);
  116.             c.DrawArc(center, r, startAngle, endAngle, 180, color, 5);
  117.             c.DrawLine(yStart, yEnd, color, 5);
  118.         }
  119.  
  120.         public void DrawRing(CanvasItem c, float atDistance)
  121.         {
  122.             Vector2 vectorPosition;
  123.             Vector2 ringDirection;
  124.             if (atDistance >= xDistance + arcDistance)
  125.             {
  126.                 // On the y fragment
  127.                 vectorPosition = VectorExtensions.Lerp(yStart, yEnd, (atDistance - xDistance - arcDistance) / yDistance);
  128.                 ringDirection = (yEnd - yStart).Normalized();
  129.             }
  130.             else if (atDistance > xDistance)
  131.             {
  132.                 // On the arc
  133.                 var v = xEnd - center;
  134.                 var rotationRadians = (atDistance - xDistance) / r;
  135.                 if (!toRight)
  136.                     rotationRadians *= -1;
  137.                 v = v.Rotated(rotationRadians);
  138.                 vectorPosition = center + v;
  139.  
  140.                 ringDirection = v.Perpendicular().Normalized();
  141.                 if (toRight)
  142.                     ringDirection *= -1;
  143.  
  144.                 //c.DrawLine(center, xEnd, new Color(0, 0, 1));
  145.                 //c.DrawLine(center, vectorPosition, new Color(0, 1, 0));
  146.  
  147.                 float centripetalForce = velocity*velocity/r;
  148.                 v = v.Normalized() * -1;
  149.                 Vector2 forceP = vectorPosition + v * (centripetalForce/velocity)*10;
  150.                 c.DrawLine(vectorPosition + v * 10, forceP, new Color(0, 0, 1), 3);
  151.                 c.DrawLine(forceP, forceP - v.Rotated(0.785f).Normalized()*10, new Color(0, 0, 1), 2);
  152.                 c.DrawLine(forceP, forceP - v.Rotated(-0.785f).Normalized()*10, new Color(0, 0, 1), 2);
  153.             }
  154.             else
  155.             {
  156.                 // On the x fragment
  157.                 vectorPosition = VectorExtensions.Lerp(xStart, xEnd, atDistance / xDistance);
  158.                 ringDirection = (xEnd - xStart).Normalized();
  159.             }
  160.  
  161.             c.DrawCircle(vectorPosition, 10, new Color(0, 1, 0));
  162.             c.DrawLine(vectorPosition, vectorPosition+ringDirection*10, new Color(0, 0, 1), 3);
  163.         }
  164.     }
  165.  
  166.     private Wire wire;
  167.     private static float velocity = 100;
  168.     private float ringDistance;
  169.  
  170.     // Called when the node enters the scene tree for the first time.
  171.     public override void _Ready()
  172.     {
  173.         wire = new Wire(new Segment(new Vector2(50, 400), new Vector2(50, 500), 50, 100));
  174.         wire.AttachNextSegment(new Vector2(100, 0), 30, 100, false);
  175.         wire.AttachNextSegment(new Vector2(0, -100), 60, 100, true);
  176.         wire.AttachNextSegment(new Vector2(300, 0), 45, 100, true);
  177.         wire.AttachNextSegment(new Vector2(0, 100), 55, 100, false);
  178.         wire.AttachNextSegment(new Vector2(50, 0), 25, 100, false);
  179.         wire.AttachNextSegment(new Vector2(0, -200), 40, 100, false);
  180.         wire.AttachNextSegment(new Vector2(-775, 0), 50, 160, false);
  181.     }
  182.  
  183.     public override void _Draw()
  184.     {
  185.         wire.Draw(this);
  186.         wire.DrawRing(this, ringDistance);
  187.     }
  188.  
  189.     // Called every frame. 'delta' is the elapsed time since the previous frame.
  190.     public override void _Process(float delta)
  191.     {
  192.         Update();
  193.         ringDistance += velocity * delta;
  194.  
  195.         if(ringDistance > wire.TotalDistance)
  196.         {
  197.             ringDistance %= wire.TotalDistance;
  198.         }
  199.     }
  200. }
  201.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement