diff --git a/DungeonShooting_Godot/project.godot b/DungeonShooting_Godot/project.godot index 66967c6..3062ae5 100644 --- a/DungeonShooting_Godot/project.godot +++ b/DungeonShooting_Godot/project.godot @@ -11,7 +11,7 @@ [application] config/name="DungeonShooting" -run/main_scene="res://scene/test/TestMask.tscn" +run/main_scene="res://scene/test/TestMask2.tscn" config/features=PackedStringArray("4.2", "C#") config/icon="res://icon.png" diff --git a/DungeonShooting_Godot/resource/test/Brush1.png b/DungeonShooting_Godot/resource/test/Brush1.png new file mode 100644 index 0000000..cc29834 --- /dev/null +++ b/DungeonShooting_Godot/resource/test/Brush1.png Binary files differ diff --git a/DungeonShooting_Godot/resource/test/Brush1.png.import b/DungeonShooting_Godot/resource/test/Brush1.png.import new file mode 100644 index 0000000..36e2337 --- /dev/null +++ b/DungeonShooting_Godot/resource/test/Brush1.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://b1qqkdbgeiptt" +path="res://.godot/imported/Brush1.png-c06cfaae2d1899be439c0c781f8ded8e.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://resource/test/Brush1.png" +dest_files=["res://.godot/imported/Brush1.png-c06cfaae2d1899be439c0c781f8ded8e.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/DungeonShooting_Godot/resource/test/Brush2.png b/DungeonShooting_Godot/resource/test/Brush2.png new file mode 100644 index 0000000..a3e2d67 --- /dev/null +++ b/DungeonShooting_Godot/resource/test/Brush2.png Binary files differ diff --git a/DungeonShooting_Godot/resource/test/Brush2.png.import b/DungeonShooting_Godot/resource/test/Brush2.png.import new file mode 100644 index 0000000..e6c7edc --- /dev/null +++ b/DungeonShooting_Godot/resource/test/Brush2.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://diehy0xukqgxk" +path="res://.godot/imported/Brush2.png-dbc4fb33763caf479092647cbe3b1dd8.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://resource/test/Brush2.png" +dest_files=["res://.godot/imported/Brush2.png-dbc4fb33763caf479092647cbe3b1dd8.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/DungeonShooting_Godot/scene/test/TestMask2.tscn b/DungeonShooting_Godot/scene/test/TestMask2.tscn new file mode 100644 index 0000000..2ab1f54 --- /dev/null +++ b/DungeonShooting_Godot/scene/test/TestMask2.tscn @@ -0,0 +1,45 @@ +[gd_scene load_steps=7 format=3 uid="uid://d2b8jufx70mkl"] + +[ext_resource type="Script" path="res://src/test/TestMask2.cs" id="1_rtexh"] +[ext_resource type="Texture2D" uid="uid://b1qqkdbgeiptt" path="res://resource/test/Brush1.png" id="2_bgpg8"] +[ext_resource type="Texture2D" uid="uid://diehy0xukqgxk" path="res://resource/test/Brush2.png" id="3_207p4"] +[ext_resource type="Shader" path="res://resource/material/Blend.gdshader" id="3_cj25g"] +[ext_resource type="Texture2D" uid="uid://uhhfgdhpk7i4" path="res://icon.png" id="4_ywq1f"] + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_fisy8"] +shader = ExtResource("3_cj25g") +shader_parameter/blend = Color(1, 1, 1, 1) +shader_parameter/schedule = 0.0 +shader_parameter/modulate = Color(1, 1, 1, 0.392157) +shader_parameter/show_outline = true +shader_parameter/outline_color = Color(1, 0, 0, 1) +shader_parameter/outline_rainbow = false +shader_parameter/outline_use_blend = false +shader_parameter/grey = 0.0 + +[node name="TestMask2" type="SubViewportContainer" node_paths=PackedStringArray("Canvas")] +offset_right = 480.0 +offset_bottom = 270.0 +scale = Vector2(4, 4) +script = ExtResource("1_rtexh") +Canvas = NodePath("SubViewport/Canvas") +Brush1 = ExtResource("2_bgpg8") +Brush2 = ExtResource("3_207p4") + +[node name="SubViewport" type="SubViewport" parent="."] +disable_3d = true +handle_input_locally = false +use_hdr_2d = true +canvas_item_default_texture_filter = 0 +size = Vector2i(480, 270) +render_target_update_mode = 4 + +[node name="Sprite2D" type="Sprite2D" parent="SubViewport"] +scale = Vector2(8, 8) +texture = ExtResource("4_ywq1f") +centered = false + +[node name="Canvas" type="Sprite2D" parent="SubViewport"] +material = SubResource("ShaderMaterial_fisy8") +texture = ExtResource("4_ywq1f") +centered = false diff --git a/DungeonShooting_Godot/src/test/TestMask.cs b/DungeonShooting_Godot/src/test/TestMask.cs index 99bcaf1..2954320 100644 --- a/DungeonShooting_Godot/src/test/TestMask.cs +++ b/DungeonShooting_Godot/src/test/TestMask.cs @@ -1,5 +1,6 @@ using Godot; using System; +using System.Collections.Generic; using System.Linq; using Godot.Collections; @@ -8,7 +9,7 @@ [Export] public Polygon2D PolygonNode; - public Array Result = new Array(); + public List Result = new List(); public override void _Ready() { //Geometry2D. @@ -30,22 +31,161 @@ public override void _Process(double delta) { - if (Input.IsActionJustPressed("fire")) + //if (Input.IsActionJustPressed("fire")) + if (Input.IsActionPressed("fire") || Input.IsActionJustPressed("roll")) { - var position = GetGlobalMousePosition(); - Result.Add(new Vector2[] + var time = DateTime.Now; + RunTest(); + Debug.Log("用时: " + (DateTime.Now - time).TotalMilliseconds); + } + + if (Input.IsActionJustPressed("meleeAttack")) + { + for (var i = 0; i < Result.Count; i++) { - new Vector2(position.X, position.Y), - new Vector2(position.X + 50, position.Y), - new Vector2(position.X + 50, position.Y + 50), - new Vector2(position.X, position.Y + 50), - }); - // Geometry2D.IsPolygonClockwise() - // Geometry2D.MergePolygons() + var temp = Result[i]; + Result[i] = StreamlineVertices3(temp, 10, Mathf.DegToRad(15)); + Debug.Log($"优化前: {temp.Length}, 优化后: {Result[i].Length}"); + } + } + + if (Input.IsActionJustPressed("exchangeWeapon")) + { + Result.Clear(); } QueueRedraw(); } + private void RunTest() + { + var position = GetGlobalMousePosition(); + var circle = GetCircle(position, 50, 10); + //先检测有没有碰撞 + var flag = false; + for (var i = 0; i < Result.Count; i++) + { + var p = Result[i]; + if (CollisionPolygon(p, circle)) + { + flag = true; + var mergePolygons = Geometry2D.MergePolygons(p, circle); + Result.RemoveAt(i); + for (var j = 0; j < mergePolygons.Count; j++) + { + Result.Add(mergePolygons[j]); + //Result.Add(StreamlineVertices(mergePolygons[j], 50)); + //Result.Add(StreamlineVertices2(mergePolygons[j], Mathf.DegToRad(5))); + //Result.Add(StreamlineVertices3(mergePolygons[j], 20, Mathf.DegToRad(15))); + } + break; + } + } + + if (!flag) + { + Result.Add(circle); + //Result.Add(StreamlineVertices2(circle, Mathf.DegToRad(5))); + } + } + + private Vector2[] StreamlineVertices3(Vector2[] polygon, float d, float r) + { + if (polygon.Length <= 3) + { + return polygon; + } + + float v = d * d; + List list = new List(); + Vector2 tempPoint = polygon[0]; + Vector2 tempPoint2 = polygon[1]; + list.Add(tempPoint); + float tr = tempPoint.AngleToPoint(tempPoint2); + float delta = 0; + for (var i = 1; i < polygon.Length; i++) + { + var curr = polygon[i]; + var prev = polygon[i > 0 ? i - 1 : polygon.Length - 1]; + var next = polygon[i < polygon.Length - 1 ? i + 1 : 0]; + if (prev.DistanceSquaredTo(next) > v) + { + //list.Add(curr); + + var angle = curr.AngleToPoint(next); + delta += angle - tr; + if (Mathf.Abs(delta) >= r) + { + Debug.Log(i + ", 偏差角度: " + Mathf.RadToDeg(delta)); + tr = angle; + delta = 0; + //var result = Geometry2D.GetClosestPointToSegmentUncapped(curr, tempPoint, tempPoint2); + tempPoint = curr; + //tempPoint2 = next; + list.Add(tempPoint); + } + } + } + + return list.ToArray(); + } + + private bool CollisionPolygon(Vector2[] polygon1, Vector2[] polygon2) + { + for (int shape = 0; shape < 2; shape++) + { + if (shape == 1) + { + Vector2[] tmp = polygon1; + polygon1 = polygon2; + polygon2 = tmp; + } + + for (int a = 0; a < polygon1.Length; a++) + { + int b = (a + 1) % polygon1.Length; + float axisX = -(polygon1[b].Y - polygon1[a].Y); + float axisY = polygon1[b].X - polygon1[a].X; + + float mina = float.MaxValue; + float maxa = float.MinValue; + for (int p = 0; p < polygon1.Length; p++) + { + float t = polygon1[p].X * axisX + polygon1[p].Y * axisY; + mina = Math.Min(mina, t); + maxa = Math.Max(maxa, t); + } + + float minb = float.MaxValue; + float maxb = float.MinValue; + for (int p = 0; p < polygon2.Length; p++) + { + float t = polygon2[p].X * axisX + polygon2[p].Y * axisY; + minb = Math.Min(minb, t); + maxb = Math.Max(maxb, t); + } + + if (maxa < minb || mina > maxb) + return false; + } + } + + return true; + } + + private Vector2[] GetCircle(Vector2 position, float radius, int vertexCount) + { + Vector2[] vertices = new Vector2[vertexCount]; + + for (int i = 0; i < vertexCount; i++) + { + float angle = i * 2.0f * (float)Math.PI / vertexCount; + Vector2 vertex = position + new Vector2((float)Math.Cos(angle) * radius, (float)Math.Sin(angle) * radius); + vertices[i] = vertex; + } + + return vertices; + } + public override void _Draw() { if (Result != null) @@ -55,6 +195,10 @@ var list = vector2s.ToList(); list.Add(vector2s[0]); DrawPolyline(list.ToArray(), Colors.Red); + foreach (var vector2 in list) + { + DrawCircle(vector2, 2, Colors.Green); + } } //DrawColoredPolygon(Result[1], Colors.Red); } diff --git a/DungeonShooting_Godot/src/test/TestMask2.cs b/DungeonShooting_Godot/src/test/TestMask2.cs new file mode 100644 index 0000000..f91cb7c --- /dev/null +++ b/DungeonShooting_Godot/src/test/TestMask2.cs @@ -0,0 +1,74 @@ +using Godot; +using System; + +public partial class TestMask2 : SubViewportContainer +{ + [Export] + public Sprite2D Canvas; + + [Export] + public Texture2D Brush1; + [Export] + public Texture2D Brush2; + + private Grid _grid = new Grid(); + + private Image _brushImage1; + private Image _brushImage2; + private Image _image; + private ImageTexture _texture; + + public override void _Ready() + { + _brushImage1 = Brush1.GetImage(); + _brushImage2 = Brush2.GetImage(); + _image = Image.Create(480, 270, false, Image.Format.Rgba8); + _texture = ImageTexture.CreateFromImage(_image); + Canvas.Texture = _texture; + } + + public override void _Process(double delta) + { + if (Input.IsActionPressed("fire")) + { + var time = DateTime.Now; + RunTest(_brushImage1); + Debug.Log("用时: " + (DateTime.Now - time).TotalMilliseconds); + } + else if (Input.IsActionPressed("roll")) + { + var time = DateTime.Now; + RunTest(_brushImage2); + Debug.Log("用时: " + (DateTime.Now - time).TotalMilliseconds); + } + + if (Input.IsActionJustPressed("meleeAttack")) + { + var time = DateTime.Now; + var mousePosition = GetGlobalMousePosition(); + for (int i = 0; i < 10; i++) + { + var pixel = _image.GetPixel((int)mousePosition.X / 4 + i, (int)mousePosition.Y / 4); + } + Debug.Log("用时: " + (DateTime.Now - time).TotalMilliseconds); + } + + if (Input.IsActionJustPressed("exchangeWeapon")) + { + _image.Fill(new Color(1, 1, 1, 0)); + _texture.Update(_image); + } + + + } + + private void RunTest(Image brushImage) + { + //_image.BlitRect(); + _image.BlendRect(brushImage, + new Rect2I(Vector2I.Zero, brushImage.GetWidth(), brushImage.GetHeight()), + (GetGlobalMousePosition() / 4 - brushImage.GetSize() / 2).AsVector2I() + ); + _texture.Update(_image); + } +}