diff --git a/DungeonShooting_Godot/prefab/ui/RoomUI.tscn b/DungeonShooting_Godot/prefab/ui/RoomUI.tscn index 928fcf4..e0a86af 100644 --- a/DungeonShooting_Godot/prefab/ui/RoomUI.tscn +++ b/DungeonShooting_Godot/prefab/ui/RoomUI.tscn @@ -367,8 +367,6 @@ [node name="WeaponRoulette" parent="." instance=ExtResource("17_ydc4r")] layout_mode = 1 -grow_horizontal = 2 -grow_vertical = 2 metadata/_edit_lock_ = true [node name="RoomMap" parent="." instance=ExtResource("16_rp3sg")] diff --git a/DungeonShooting_Godot/prefab/ui/WeaponRoulette.tscn b/DungeonShooting_Godot/prefab/ui/WeaponRoulette.tscn index 37b98be..8850c5a 100644 --- a/DungeonShooting_Godot/prefab/ui/WeaponRoulette.tscn +++ b/DungeonShooting_Godot/prefab/ui/WeaponRoulette.tscn @@ -1,8 +1,17 @@ -[gd_scene load_steps=4 format=3 uid="uid://dbjpknb3d5gfw"] +[gd_scene load_steps=7 format=3 uid="uid://dbjpknb3d5gfw"] [ext_resource type="Script" path="res://src/game/ui/weaponRoulette/WeaponRoulettePanel.cs" id="1_1uvbk"] [ext_resource type="Texture2D" uid="uid://e6krxgte01j3" path="res://resource/sprite/ui/roulette/RouletteBg.png" id="2_k6gjh"] -[ext_resource type="Texture2D" uid="uid://civvcowt2wklr" path="res://resource/sprite/weapon/weapon0001/Weapon0001.png" id="3_f6rvp"] +[ext_resource type="Script" path="res://src/game/ui/weaponRoulette/WeaponSlot.cs" id="3_8v011"] +[ext_resource type="Shader" path="res://resource/material/Outline.gdshader" id="4_p348k"] + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_i1wmw"] +resource_local_to_scene = true +shader = ExtResource("4_p348k") +shader_parameter/outline_color = Color(0, 0, 0, 1) + +[sub_resource type="CircleShape2D" id="CircleShape2D_snfa8"] +radius = 2.0 [node name="WeaponRoulette" type="Control"] layout_mode = 3 @@ -37,15 +46,52 @@ grow_vertical = 2 [node name="RouletteBg" type="Sprite2D" parent="Control"] +position = Vector2(32.5, -27) scale = Vector2(4, 4) texture = ExtResource("2_k6gjh") -[node name="WeaponSlot" type="Node2D" parent="Control/RouletteBg"] +[node name="WeaponSlotNode" type="Node2D" parent="Control/RouletteBg"] +script = ExtResource("3_8v011") -[node name="Sprite" type="Sprite2D" parent="Control/RouletteBg/WeaponSlot"] -position = Vector2(65, 2.08165e-12) -texture = ExtResource("3_f6rvp") +[node name="Control" type="Control" parent="Control/RouletteBg/WeaponSlotNode"] +layout_mode = 3 +anchors_preset = 0 +offset_left = 65.25 +offset_right = 66.25 +offset_bottom = 1.0 -[node name="Area2D" type="Area2D" parent="Control/RouletteBg/WeaponSlot"] +[node name="WeaponIcon" type="Sprite2D" parent="Control/RouletteBg/WeaponSlotNode/Control"] +material = SubResource("ShaderMaterial_i1wmw") -[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="Control/RouletteBg/WeaponSlot/Area2D"] +[node name="AmmoLabel" type="Label" parent="Control/RouletteBg/WeaponSlotNode/Control"] +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -15.25 +offset_top = 4.5 +offset_right = 104.75 +offset_bottom = 44.5 +grow_horizontal = 2 +grow_vertical = 2 +scale = Vector2(0.25, 0.25) +text = "0/0" +horizontal_alignment = 1 +vertical_alignment = 1 + +[node name="SlotAreaNode" type="Area2D" parent="Control/RouletteBg/WeaponSlotNode"] +collision_layer = 0 +collision_mask = 8192 +monitorable = false + +[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="Control/RouletteBg/WeaponSlotNode/SlotAreaNode"] + +[node name="MouseArea" type="Area2D" parent="."] +collision_layer = 8192 +collision_mask = 0 +monitoring = false + +[node name="CollisionShape2D" type="CollisionShape2D" parent="MouseArea"] +shape = SubResource("CircleShape2D_snfa8") diff --git a/DungeonShooting_Godot/project.godot b/DungeonShooting_Godot/project.godot index fcc9734..7c6559c 100644 --- a/DungeonShooting_Godot/project.godot +++ b/DungeonShooting_Godot/project.godot @@ -252,6 +252,7 @@ 2d_physics/layer_8="debris" 2d_physics/layer_9="throwing" 2d_physics/layer_10="obstacle" +2d_physics/layer_14="ui_mouse" [mono] diff --git a/DungeonShooting_Godot/src/game/ui/weaponRoulette/WeaponRoulette.cs b/DungeonShooting_Godot/src/game/ui/weaponRoulette/WeaponRoulette.cs index 64dc32a..a078918 100644 --- a/DungeonShooting_Godot/src/game/ui/weaponRoulette/WeaponRoulette.cs +++ b/DungeonShooting_Godot/src/game/ui/weaponRoulette/WeaponRoulette.cs @@ -31,6 +31,19 @@ } private Control _L_Control; + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: WeaponRoulette.MouseArea + /// + public MouseArea L_MouseArea + { + get + { + if (_L_MouseArea == null) _L_MouseArea = new MouseArea((WeaponRoulettePanel)this, GetNode("MouseArea")); + return _L_MouseArea; + } + } + private MouseArea _L_MouseArea; + public WeaponRoulette() : base(nameof(WeaponRoulette)) { @@ -38,6 +51,7 @@ public sealed override void OnInitNestedUi() { + _ = L_Control.L_RouletteBg.L_WeaponSlotNode; } @@ -51,16 +65,60 @@ } /// - /// 类型: , 路径: WeaponRoulette.Control.RouletteBg.WeaponSlot.Sprite + /// 类型: , 路径: WeaponRoulette.Control.RouletteBg.WeaponSlotNode.Control.WeaponIcon /// - public class Sprite : UiNode + public class WeaponIcon : UiNode { - public Sprite(WeaponRoulettePanel uiPanel, Godot.Sprite2D node) : base(uiPanel, node) { } - public override Sprite Clone() => new (UiPanel, (Godot.Sprite2D)Instance.Duplicate()); + public WeaponIcon(WeaponRoulettePanel uiPanel, Godot.Sprite2D node) : base(uiPanel, node) { } + public override WeaponIcon Clone() => new (UiPanel, (Godot.Sprite2D)Instance.Duplicate()); } /// - /// 类型: , 路径: WeaponRoulette.Control.RouletteBg.WeaponSlot.Area2D.CollisionPolygon2D + /// 类型: , 路径: WeaponRoulette.Control.RouletteBg.WeaponSlotNode.Control.AmmoLabel + /// + public class AmmoLabel : UiNode + { + public AmmoLabel(WeaponRoulettePanel uiPanel, Godot.Label node) : base(uiPanel, node) { } + public override AmmoLabel Clone() => new (UiPanel, (Godot.Label)Instance.Duplicate()); + } + + /// + /// 类型: , 路径: WeaponRoulette.Control.RouletteBg.WeaponSlotNode.Control + /// + public class Control_1 : UiNode + { + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: WeaponRoulette.Control.RouletteBg.WeaponSlotNode.WeaponIcon + /// + public WeaponIcon L_WeaponIcon + { + get + { + if (_L_WeaponIcon == null) _L_WeaponIcon = new WeaponIcon(UiPanel, Instance.GetNode("WeaponIcon")); + return _L_WeaponIcon; + } + } + private WeaponIcon _L_WeaponIcon; + + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: WeaponRoulette.Control.RouletteBg.WeaponSlotNode.AmmoLabel + /// + public AmmoLabel L_AmmoLabel + { + get + { + if (_L_AmmoLabel == null) _L_AmmoLabel = new AmmoLabel(UiPanel, Instance.GetNode("AmmoLabel")); + return _L_AmmoLabel; + } + } + private AmmoLabel _L_AmmoLabel; + + public Control_1(WeaponRoulettePanel uiPanel, Godot.Control node) : base(uiPanel, node) { } + public override Control_1 Clone() => new (UiPanel, (Godot.Control)Instance.Duplicate()); + } + + /// + /// 类型: , 路径: WeaponRoulette.Control.RouletteBg.WeaponSlotNode.SlotAreaNode.CollisionPolygon2D /// public class CollisionPolygon2D : UiNode { @@ -69,12 +127,12 @@ } /// - /// 类型: , 路径: WeaponRoulette.Control.RouletteBg.WeaponSlot.Area2D + /// 类型: , 路径: WeaponRoulette.Control.RouletteBg.WeaponSlotNode.SlotAreaNode /// - public class Area2D : UiNode + public class SlotAreaNode : UiNode { /// - /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: WeaponRoulette.Control.RouletteBg.WeaponSlot.CollisionPolygon2D + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: WeaponRoulette.Control.RouletteBg.WeaponSlotNode.CollisionPolygon2D /// public CollisionPolygon2D L_CollisionPolygon2D { @@ -86,43 +144,43 @@ } private CollisionPolygon2D _L_CollisionPolygon2D; - public Area2D(WeaponRoulettePanel uiPanel, Godot.Area2D node) : base(uiPanel, node) { } - public override Area2D Clone() => new (UiPanel, (Godot.Area2D)Instance.Duplicate()); + public SlotAreaNode(WeaponRoulettePanel uiPanel, Godot.Area2D node) : base(uiPanel, node) { } + public override SlotAreaNode Clone() => new (UiPanel, (Godot.Area2D)Instance.Duplicate()); } /// - /// 类型: , 路径: WeaponRoulette.Control.RouletteBg.WeaponSlot + /// 类型: , 路径: WeaponRoulette.Control.RouletteBg.WeaponSlotNode /// - public class WeaponSlot : UiNode + public class WeaponSlotNode : UiNode { /// - /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: WeaponRoulette.Control.RouletteBg.Sprite + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: WeaponRoulette.Control.RouletteBg.Control /// - public Sprite L_Sprite + public Control_1 L_Control { get { - if (_L_Sprite == null) _L_Sprite = new Sprite(UiPanel, Instance.GetNode("Sprite")); - return _L_Sprite; + if (_L_Control == null) _L_Control = new Control_1(UiPanel, Instance.GetNode("Control")); + return _L_Control; } } - private Sprite _L_Sprite; + private Control_1 _L_Control; /// - /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: WeaponRoulette.Control.RouletteBg.Area2D + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: WeaponRoulette.Control.RouletteBg.SlotAreaNode /// - public Area2D L_Area2D + public SlotAreaNode L_SlotAreaNode { get { - if (_L_Area2D == null) _L_Area2D = new Area2D(UiPanel, Instance.GetNode("Area2D")); - return _L_Area2D; + if (_L_SlotAreaNode == null) _L_SlotAreaNode = new SlotAreaNode(UiPanel, Instance.GetNode("SlotAreaNode")); + return _L_SlotAreaNode; } } - private Area2D _L_Area2D; + private SlotAreaNode _L_SlotAreaNode; - public WeaponSlot(WeaponRoulettePanel uiPanel, Godot.Node2D node) : base(uiPanel, node) { } - public override WeaponSlot Clone() => new (UiPanel, (Godot.Node2D)Instance.Duplicate()); + public WeaponSlotNode(WeaponRoulettePanel uiPanel, UI.WeaponRoulette.WeaponSlot node) : base(uiPanel, node) { } + public override WeaponSlotNode Clone() => new (UiPanel, (UI.WeaponRoulette.WeaponSlot)Instance.Duplicate()); } /// @@ -131,17 +189,17 @@ public class RouletteBg : UiNode { /// - /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: WeaponRoulette.Control.WeaponSlot + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: WeaponRoulette.Control.WeaponSlotNode /// - public WeaponSlot L_WeaponSlot + public WeaponSlotNode L_WeaponSlotNode { get { - if (_L_WeaponSlot == null) _L_WeaponSlot = new WeaponSlot(UiPanel, Instance.GetNode("WeaponSlot")); - return _L_WeaponSlot; + if (_L_WeaponSlotNode == null) _L_WeaponSlotNode = new WeaponSlotNode(UiPanel, Instance.GetNode("WeaponSlotNode")); + return _L_WeaponSlotNode; } } - private WeaponSlot _L_WeaponSlot; + private WeaponSlotNode _L_WeaponSlotNode; public RouletteBg(WeaponRoulettePanel uiPanel, Godot.Sprite2D node) : base(uiPanel, node) { } public override RouletteBg Clone() => new (UiPanel, (Godot.Sprite2D)Instance.Duplicate()); @@ -169,6 +227,37 @@ public override Control Clone() => new (UiPanel, (Godot.Control)Instance.Duplicate()); } + /// + /// 类型: , 路径: WeaponRoulette.MouseArea.CollisionShape2D + /// + public class CollisionShape2D : UiNode + { + public CollisionShape2D(WeaponRoulettePanel uiPanel, Godot.CollisionShape2D node) : base(uiPanel, node) { } + public override CollisionShape2D Clone() => new (UiPanel, (Godot.CollisionShape2D)Instance.Duplicate()); + } + + /// + /// 类型: , 路径: WeaponRoulette.MouseArea + /// + public class MouseArea : UiNode + { + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: WeaponRoulette.CollisionShape2D + /// + public CollisionShape2D L_CollisionShape2D + { + get + { + if (_L_CollisionShape2D == null) _L_CollisionShape2D = new CollisionShape2D(UiPanel, Instance.GetNode("CollisionShape2D")); + return _L_CollisionShape2D; + } + } + private CollisionShape2D _L_CollisionShape2D; + + public MouseArea(WeaponRoulettePanel uiPanel, Godot.Area2D node) : base(uiPanel, node) { } + public override MouseArea Clone() => new (UiPanel, (Godot.Area2D)Instance.Duplicate()); + } + /// /// 场景中唯一名称的节点, 节点类型: , 节点路径: WeaponRoulette.Bg @@ -176,24 +265,29 @@ public Bg S_Bg => L_Bg; /// - /// 场景中唯一名称的节点, 节点类型: , 节点路径: WeaponRoulette.Control.RouletteBg.WeaponSlot.Sprite + /// 场景中唯一名称的节点, 节点类型: , 节点路径: WeaponRoulette.Control.RouletteBg.WeaponSlotNode.Control.WeaponIcon /// - public Sprite S_Sprite => L_Control.L_RouletteBg.L_WeaponSlot.L_Sprite; + public WeaponIcon S_WeaponIcon => L_Control.L_RouletteBg.L_WeaponSlotNode.L_Control.L_WeaponIcon; /// - /// 场景中唯一名称的节点, 节点类型: , 节点路径: WeaponRoulette.Control.RouletteBg.WeaponSlot.Area2D.CollisionPolygon2D + /// 场景中唯一名称的节点, 节点类型: , 节点路径: WeaponRoulette.Control.RouletteBg.WeaponSlotNode.Control.AmmoLabel /// - public CollisionPolygon2D S_CollisionPolygon2D => L_Control.L_RouletteBg.L_WeaponSlot.L_Area2D.L_CollisionPolygon2D; + public AmmoLabel S_AmmoLabel => L_Control.L_RouletteBg.L_WeaponSlotNode.L_Control.L_AmmoLabel; /// - /// 场景中唯一名称的节点, 节点类型: , 节点路径: WeaponRoulette.Control.RouletteBg.WeaponSlot.Area2D + /// 场景中唯一名称的节点, 节点类型: , 节点路径: WeaponRoulette.Control.RouletteBg.WeaponSlotNode.SlotAreaNode.CollisionPolygon2D /// - public Area2D S_Area2D => L_Control.L_RouletteBg.L_WeaponSlot.L_Area2D; + public CollisionPolygon2D S_CollisionPolygon2D => L_Control.L_RouletteBg.L_WeaponSlotNode.L_SlotAreaNode.L_CollisionPolygon2D; /// - /// 场景中唯一名称的节点, 节点类型: , 节点路径: WeaponRoulette.Control.RouletteBg.WeaponSlot + /// 场景中唯一名称的节点, 节点类型: , 节点路径: WeaponRoulette.Control.RouletteBg.WeaponSlotNode.SlotAreaNode /// - public WeaponSlot S_WeaponSlot => L_Control.L_RouletteBg.L_WeaponSlot; + public SlotAreaNode S_SlotAreaNode => L_Control.L_RouletteBg.L_WeaponSlotNode.L_SlotAreaNode; + + /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: WeaponRoulette.Control.RouletteBg.WeaponSlotNode + /// + public WeaponSlotNode S_WeaponSlotNode => L_Control.L_RouletteBg.L_WeaponSlotNode; /// /// 场景中唯一名称的节点, 节点类型: , 节点路径: WeaponRoulette.Control.RouletteBg @@ -201,8 +295,13 @@ public RouletteBg S_RouletteBg => L_Control.L_RouletteBg; /// - /// 场景中唯一名称的节点, 节点类型: , 节点路径: WeaponRoulette.Control + /// 场景中唯一名称的节点, 节点类型: , 节点路径: WeaponRoulette.MouseArea.CollisionShape2D /// - public Control S_Control => L_Control; + public CollisionShape2D S_CollisionShape2D => L_MouseArea.L_CollisionShape2D; + + /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: WeaponRoulette.MouseArea + /// + public MouseArea S_MouseArea => L_MouseArea; } diff --git a/DungeonShooting_Godot/src/game/ui/weaponRoulette/WeaponRoulettePanel.cs b/DungeonShooting_Godot/src/game/ui/weaponRoulette/WeaponRoulettePanel.cs index 1e17149..165e43b 100644 --- a/DungeonShooting_Godot/src/game/ui/weaponRoulette/WeaponRoulettePanel.cs +++ b/DungeonShooting_Godot/src/game/ui/weaponRoulette/WeaponRoulettePanel.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using Godot; namespace UI.WeaponRoulette; @@ -15,20 +16,31 @@ //是否展开轮盘 private bool _pressRouletteFlag = false; private bool _isMagnifyRoulette = false; + //所有武器插槽 + private List _slotNodes = new List(); public override void OnCreateUi() { S_RouletteBg.Instance.Visible = false; S_Bg.Instance.Visible = false; + //创建武器插槽 for (var i = 0; i < SlotCount; i++) { - var angle = i * (360 / SlotCount); - var clone = S_WeaponSlot.CloneAndPut(); + var angle = i * (360f / SlotCount); + var clone = S_WeaponSlotNode.CloneAndPut(); + var collisionPolygon2D = clone.L_SlotAreaNode.L_CollisionPolygon2D.Instance; + var sectorPolygon = Utils.CreateSectorPolygon(0, 100, 360f / SlotCount, 4); + collisionPolygon2D.Polygon = sectorPolygon; clone.Instance.RotationDegrees = angle; + clone.L_Control.Instance.RotationDegrees = -angle; + clone.L_Control.L_WeaponIcon.Instance.Material = (Material)S_WeaponSlotNode.L_Control.L_WeaponIcon.Instance.Material.Duplicate(); + _slotNodes.Add(clone); } - S_WeaponSlot.Instance.Visible = false; + S_WeaponSlotNode.QueueFree(); + + SetEnableSectorCollision(false); } public override void OnDestroyUi() @@ -55,6 +67,12 @@ { ShrinkRoulette(); } + + + if (InputManager.Roulette) + { + S_MouseArea.Instance.GlobalPosition = GetGlobalMousePosition(); + } } private void ExpandRoulette() @@ -65,6 +83,8 @@ S_RouletteBg.Instance.Visible = true; S_Bg.Instance.Visible = true; + SetEnableSectorCollision(true); + RefreshWeapon(); } private void ShrinkRoulette() @@ -74,5 +94,57 @@ _isMagnifyRoulette = false; World.Current.Pause = false; + SetEnableSectorCollision(false); + } + + //设置是否启用扇形碰撞检测 + private void SetEnableSectorCollision(bool enable) + { + S_MouseArea.Instance.Monitorable = enable; + foreach (var weaponSlotNode in _slotNodes) + { + weaponSlotNode.L_SlotAreaNode.Instance.Monitorable = enable; + } + } + + //更新显示的武器 + private void RefreshWeapon() + { + var current = Player.Current; + if (current == null) + { + foreach (var slotNode in _slotNodes) + { + slotNode.L_Control.Instance.Visible = false; + } + + return; + } + + var weapons = current.WeaponPack.ItemSlot; + for (var i = 0; i < _slotNodes.Count; i++) + { + var slotNode = _slotNodes[i]; + slotNode.L_Control.Instance.Visible = true; + if (weapons.Length > i) + { + var weapon = weapons[i]; + if (weapon != null) + { + slotNode.L_Control.Instance.Visible = true; + slotNode.L_Control.L_WeaponIcon.Instance.Texture = weapon.GetDefaultTexture(); + slotNode.L_Control.L_AmmoLabel.Instance.Text = + (weapon.CurrAmmo + weapon.ResidueAmmo).ToString() + "/" + weapon.Attribute.MaxAmmoCapacity; + } + else + { + slotNode.L_Control.Instance.Visible = false; + } + } + else + { + slotNode.L_Control.Instance.Visible = false; + } + } } } diff --git a/DungeonShooting_Godot/src/game/ui/weaponRoulette/WeaponSlot.cs b/DungeonShooting_Godot/src/game/ui/weaponRoulette/WeaponSlot.cs new file mode 100644 index 0000000..37922c1 --- /dev/null +++ b/DungeonShooting_Godot/src/game/ui/weaponRoulette/WeaponSlot.cs @@ -0,0 +1,30 @@ +using Godot; + +namespace UI.WeaponRoulette; + +public partial class WeaponSlot : Node2D, IUiNodeScript +{ + private WeaponRoulette.WeaponSlotNode _node; + public void SetUiNode(IUiNode uiNode) + { + _node = (WeaponRoulette.WeaponSlotNode)uiNode; + _node.L_SlotAreaNode.Instance.AreaEntered += OnAreaEntered; + _node.L_SlotAreaNode.Instance.AreaExited += OnAreaExited; + } + + public void OnDestroy() + { + } + + private void OnAreaEntered(Area2D other) + { + _node.Instance.Scale = new Vector2(1.1f, 1.1f); + _node.L_Control.L_WeaponIcon.Instance.Material.SetShaderMaterialParameter(ShaderParamNames.OutlineColor, Colors.White); + } + + private void OnAreaExited(Area2D other) + { + _node.Instance.Scale = Vector2.One; + _node.L_Control.L_WeaponIcon.Instance.Material.SetShaderMaterialParameter(ShaderParamNames.OutlineColor, Colors.Black); + } +} \ No newline at end of file