Newer
Older
DungeonShooting / DungeonShooting_Godot / src / test / TestMask.cs
@小李xl 小李xl on 24 Nov 2023 4 KB 调研中
  1. using Godot;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using Godot.Collections;
  6.  
  7. public partial class TestMask : Node2D
  8. {
  9. [Export]
  10. public Polygon2D PolygonNode;
  11.  
  12. public List<Vector2[]> Result = new List<Vector2[]>();
  13. public override void _Ready()
  14. {
  15. //Geometry2D.
  16. // var point = new Vector2[]
  17. // {
  18. // new Vector2(0, 0),
  19. // new Vector2(0, 500),
  20. // new Vector2(500, 500),
  21. // new Vector2(500, 0)
  22. // };
  23. // Result = Geometry2D.ClipPolygons(point, new Vector2[]
  24. // {
  25. // new Vector2(20, 20),
  26. // new Vector2(20, 100),
  27. // new Vector2(90, 50),
  28. // });
  29. //PolygonNode.Polygon = clipPolygons[0];
  30. }
  31.  
  32. public override void _Process(double delta)
  33. {
  34. //if (Input.IsActionJustPressed("fire"))
  35. if (Input.IsActionPressed("fire") || Input.IsActionJustPressed("roll"))
  36. {
  37. var time = DateTime.Now;
  38. RunTest();
  39. Debug.Log("用时: " + (DateTime.Now - time).TotalMilliseconds);
  40. }
  41.  
  42. if (Input.IsActionJustPressed("meleeAttack"))
  43. {
  44. for (var i = 0; i < Result.Count; i++)
  45. {
  46. var temp = Result[i];
  47. Result[i] = StreamlineVertices3(temp, 10, Mathf.DegToRad(15));
  48. Debug.Log($"优化前: {temp.Length}, 优化后: {Result[i].Length}");
  49. }
  50. }
  51.  
  52. if (Input.IsActionJustPressed("exchangeWeapon"))
  53. {
  54. Result.Clear();
  55. }
  56. QueueRedraw();
  57. }
  58.  
  59. private void RunTest()
  60. {
  61. var position = GetGlobalMousePosition();
  62. var circle = GetCircle(position, 50, 10);
  63. //先检测有没有碰撞
  64. var flag = false;
  65. for (var i = 0; i < Result.Count; i++)
  66. {
  67. var p = Result[i];
  68. if (CollisionPolygon(p, circle))
  69. {
  70. flag = true;
  71. var mergePolygons = Geometry2D.MergePolygons(p, circle);
  72. Result.RemoveAt(i);
  73. for (var j = 0; j < mergePolygons.Count; j++)
  74. {
  75. Result.Add(mergePolygons[j]);
  76. //Result.Add(StreamlineVertices(mergePolygons[j], 50));
  77. //Result.Add(StreamlineVertices2(mergePolygons[j], Mathf.DegToRad(5)));
  78. //Result.Add(StreamlineVertices3(mergePolygons[j], 20, Mathf.DegToRad(15)));
  79. }
  80. break;
  81. }
  82. }
  83.  
  84. if (!flag)
  85. {
  86. Result.Add(circle);
  87. //Result.Add(StreamlineVertices2(circle, Mathf.DegToRad(5)));
  88. }
  89. }
  90. private Vector2[] StreamlineVertices3(Vector2[] polygon, float d, float r)
  91. {
  92. if (polygon.Length <= 3)
  93. {
  94. return polygon;
  95. }
  96. float v = d * d;
  97. List<Vector2> list = new List<Vector2>();
  98. Vector2 tempPoint = polygon[0];
  99. Vector2 tempPoint2 = polygon[1];
  100. list.Add(tempPoint);
  101. float tr = tempPoint.AngleToPoint(tempPoint2);
  102. float delta = 0;
  103. for (var i = 1; i < polygon.Length; i++)
  104. {
  105. var curr = polygon[i];
  106. var prev = polygon[i > 0 ? i - 1 : polygon.Length - 1];
  107. var next = polygon[i < polygon.Length - 1 ? i + 1 : 0];
  108. if (prev.DistanceSquaredTo(next) > v)
  109. {
  110. //list.Add(curr);
  111. var angle = curr.AngleToPoint(next);
  112. delta += angle - tr;
  113. if (Mathf.Abs(delta) >= r)
  114. {
  115. Debug.Log(i + ", 偏差角度: " + Mathf.RadToDeg(delta));
  116. tr = angle;
  117. delta = 0;
  118. //var result = Geometry2D.GetClosestPointToSegmentUncapped(curr, tempPoint, tempPoint2);
  119. tempPoint = curr;
  120. //tempPoint2 = next;
  121. list.Add(tempPoint);
  122. }
  123. }
  124. }
  125.  
  126. return list.ToArray();
  127. }
  128.  
  129. private bool CollisionPolygon(Vector2[] polygon1, Vector2[] polygon2)
  130. {
  131. for (int shape = 0; shape < 2; shape++)
  132. {
  133. if (shape == 1)
  134. {
  135. Vector2[] tmp = polygon1;
  136. polygon1 = polygon2;
  137. polygon2 = tmp;
  138. }
  139.  
  140. for (int a = 0; a < polygon1.Length; a++)
  141. {
  142. int b = (a + 1) % polygon1.Length;
  143. float axisX = -(polygon1[b].Y - polygon1[a].Y);
  144. float axisY = polygon1[b].X - polygon1[a].X;
  145.  
  146. float mina = float.MaxValue;
  147. float maxa = float.MinValue;
  148. for (int p = 0; p < polygon1.Length; p++)
  149. {
  150. float t = polygon1[p].X * axisX + polygon1[p].Y * axisY;
  151. mina = Math.Min(mina, t);
  152. maxa = Math.Max(maxa, t);
  153. }
  154.  
  155. float minb = float.MaxValue;
  156. float maxb = float.MinValue;
  157. for (int p = 0; p < polygon2.Length; p++)
  158. {
  159. float t = polygon2[p].X * axisX + polygon2[p].Y * axisY;
  160. minb = Math.Min(minb, t);
  161. maxb = Math.Max(maxb, t);
  162. }
  163.  
  164. if (maxa < minb || mina > maxb)
  165. return false;
  166. }
  167. }
  168.  
  169. return true;
  170. }
  171.  
  172. private Vector2[] GetCircle(Vector2 position, float radius, int vertexCount)
  173. {
  174. Vector2[] vertices = new Vector2[vertexCount];
  175.  
  176. for (int i = 0; i < vertexCount; i++)
  177. {
  178. float angle = i * 2.0f * (float)Math.PI / vertexCount;
  179. Vector2 vertex = position + new Vector2((float)Math.Cos(angle) * radius, (float)Math.Sin(angle) * radius);
  180. vertices[i] = vertex;
  181. }
  182.  
  183. return vertices;
  184. }
  185.  
  186. public override void _Draw()
  187. {
  188. if (Result != null)
  189. {
  190. foreach (var vector2s in Result)
  191. {
  192. var list = vector2s.ToList();
  193. list.Add(vector2s[0]);
  194. DrawPolyline(list.ToArray(), Colors.Red);
  195. foreach (var vector2 in list)
  196. {
  197. DrawCircle(vector2, 2, Colors.Green);
  198. }
  199. }
  200. //DrawColoredPolygon(Result[1], Colors.Red);
  201. }
  202. }
  203. }