diff --git a/DungeonShooting_Godot/addons/dungeonShooting_plugin/Plugin.cs b/DungeonShooting_Godot/addons/dungeonShooting_plugin/Plugin.cs
index af4f4ec..6e9581b 100644
--- a/DungeonShooting_Godot/addons/dungeonShooting_plugin/Plugin.cs
+++ b/DungeonShooting_Godot/addons/dungeonShooting_plugin/Plugin.cs
@@ -42,18 +42,12 @@
//自定义节点
private CustomTypeInfo[] _customTypeInfos = new CustomTypeInfo[]
{
- // new CustomTypeInfo(
- // "ActivityMark",
- // "Node2D",
- // "res://src/framework/map/mark/ActivityMark.cs",
- // "res://addons/dungeonShooting_plugin/Mark.svg"
- // ),
- // new CustomTypeInfo(
- // "EnemyMark",
- // "Node2D",
- // "res://src/framework/map/mark/EnemyMark.cs",
- // "res://addons/dungeonShooting_plugin/Mark.svg"
- // ),
+ new CustomTypeInfo(
+ "ActivityInstance",
+ "Node2D",
+ "res://src/framework/activity/ActivityInstance.cs",
+ "res://addons/dungeonShooting_plugin/Mark.svg"
+ ),
};
public override void _Process(double delta)
diff --git a/DungeonShooting_Godot/scene/Hall.tscn b/DungeonShooting_Godot/scene/Hall.tscn
index 0669ca8..dd62a0b 100644
--- a/DungeonShooting_Godot/scene/Hall.tscn
+++ b/DungeonShooting_Godot/scene/Hall.tscn
@@ -1,6 +1,6 @@
[gd_scene load_steps=10 format=3 uid="uid://c2hynqudkykxl"]
-[ext_resource type="PackedScene" path="res://scene/Dungeon.tscn" id="1_31od0"]
+[ext_resource type="PackedScene" uid="uid://bqf2vks5ggnsp" path="res://scene/Dungeon.tscn" id="1_31od0"]
[ext_resource type="Script" path="res://src/game/hall/Hall.cs" id="2_43fdu"]
[ext_resource type="Texture2D" uid="uid://b2j5mkqm3uv6w" path="res://resource/sprite/hall/HallBg.png" id="3_p8v6p"]
[ext_resource type="Script" path="res://src/game/hall/DungeonEntrance.cs" id="3_t3my6"]
@@ -27,10 +27,14 @@
metadata/_edit_horizontal_guides_ = [666.0, -210.0]
[node name="HallBg" type="Sprite2D" parent="." index="1"]
+z_index = -5
texture = ExtResource("3_p8v6p")
centered = false
-[node name="DungeonEntrance" type="Area2D" parent="." index="2"]
+[node name="BirthMark" type="Marker2D" parent="." index="2"]
+position = Vector2(553, 320)
+
+[node name="DungeonEntrance" type="Area2D" parent="." index="3"]
position = Vector2(537, 209)
collision_layer = 0
collision_mask = 8
@@ -40,14 +44,7 @@
[node name="CollisionShape2D" type="CollisionShape2D" parent="DungeonEntrance" index="0"]
shape = SubResource("RectangleShape2D_ru8u4")
-[node name="BirthMark" type="Marker2D" parent="." index="3"]
-position = Vector2(553, 320)
-
-[node name="PointLight2D" type="PointLight2D" parent="." index="4"]
-position = Vector2(138, 306)
-texture_scale = 3.11
-
-[node name="StaticBody2D" type="StaticBody2D" parent="." index="5"]
+[node name="StaticBody2D" type="StaticBody2D" parent="." index="4"]
collision_mask = 0
[node name="CollisionShape2D" type="CollisionShape2D" parent="StaticBody2D" index="0"]
diff --git a/DungeonShooting_Godot/src/framework/activity/ActivityInstance.cs b/DungeonShooting_Godot/src/framework/activity/ActivityInstance.cs
new file mode 100644
index 0000000..6deea4b
--- /dev/null
+++ b/DungeonShooting_Godot/src/framework/activity/ActivityInstance.cs
@@ -0,0 +1,325 @@
+
+using System;
+using System.IO;
+using Godot;
+
+///
+/// 用于在预制场景中创建 ActivityObject
+///
+[Tool]
+public partial class ActivityInstance : Node2D
+{
+ ///
+ /// 物体Id
+ ///
+ [Export]
+ public string Id
+ {
+ get => _id;
+ set
+ {
+ _id = value;
+ _dirty = true;
+ }
+ }
+
+ ///
+ /// 默认所在层级
+ ///
+ [Export]
+ public RoomLayerEnum DefaultLayer { get; set; } = RoomLayerEnum.NormalLayer;
+
+ ///
+ /// 是否显示阴影
+ ///
+ [Export]
+ public bool ShowSprite
+ {
+ get => _showSprite;
+ set
+ {
+ _showSprite = value;
+ if (_activityObject != null)
+ {
+ if (value)
+ {
+ _activityObject.ShowShadowSprite();
+ }
+ else
+ {
+ _activityObject.HideShadowSprite();
+ }
+ }
+ }
+ }
+
+ ///
+ /// 阴影偏移
+ ///
+ [Export]
+ public Vector2 ShowOffset
+ {
+ get => _showOffset;
+ set
+ {
+ _showOffset = value;
+ if (_activityObject != null)
+ {
+ _activityObject.ShadowOffset = value;
+ }
+ }
+ }
+
+ ///
+ /// 初始海拔高度
+ ///
+ [Export]
+ public float Altitude
+ {
+ get => _altitude;
+ set
+ {
+ _altitude = value;
+ if (_activityObject != null)
+ {
+ _activityObject.Altitude = value;
+ _activityObject.Collision.Position = _collPos;
+ _activityObject.UpdateShadowSprite((float)GetProcessDeltaTime());
+ _activityObject.CalcThrowAnimatedPosition();
+ }
+ }
+ }
+
+ ///
+ /// 是否启用垂直运动模拟
+ ///
+ [Export]
+ public bool VerticalMotion { get; private set; } = true;
+
+ ///
+ /// 编辑器属性, 物体子碰撞器在编辑器中是否可见
+ ///
+ [Export]
+ public bool CollisionVisible
+ {
+ get => _collisionVisible;
+ set
+ {
+ _collisionVisible = value;
+ OnChangeCollisionVisible();
+ }
+ }
+
+ private bool _dirty = false;
+ private bool _collisionVisible = true;
+ private string _prevId;
+ private string _id;
+ private ActivityObject _activityObject;
+ private Sprite2D _errorSprite;
+ private bool _showSprite = true;
+ private Vector2 _showOffset = new Vector2(0, 2);
+ private float _altitude;
+
+ private Vector2 _collPos;
+ private bool _createFlag = false;
+
+ private static string _jsonText;
+
+ public override void _Ready()
+ {
+#if TOOLS
+ if (!Engine.IsEditorHint())
+ {
+#endif
+ var world = World.Current;
+ if (world != null && world.YSortLayer != null && world.NormalLayer != null)
+ {
+ DoCreateObject();
+ }
+#if TOOLS
+ }
+#endif
+ }
+
+ public override void _Process(double delta)
+ {
+#if TOOLS
+ if (Engine.IsEditorHint())
+ {
+ if (_dirty || (_activityObject != null && _activityObject.GetParent() != this))
+ {
+ _dirty = false;
+
+ if (_prevId != _id)
+ {
+ OnChangeActivityId(_id);
+ }
+ else if (string.IsNullOrEmpty(_id))
+ {
+ ShowErrorSprite();
+ }
+
+ OnChangeCollisionVisible();
+ }
+
+ if (_activityObject != null)
+ {
+ _activityObject.Collision.Position = _collPos;
+ _activityObject.UpdateShadowSprite((float)delta);
+ _activityObject.CalcThrowAnimatedPosition();
+ }
+ }
+ else
+ {
+#endif
+ var world = World.Current;
+ if (world != null && world.YSortLayer != null && world.NormalLayer != null)
+ {
+ DoCreateObject();
+ }
+#if TOOLS
+ }
+#endif
+ }
+
+ public override void _EnterTree()
+ {
+#if TOOLS
+ if (Engine.IsEditorHint())
+ {
+ var children = GetChildren();
+ foreach (var child in children)
+ {
+ child.QueueFree();
+ }
+ _dirty = true;
+ _activityObject = null;
+ _prevId = null;
+ }
+#endif
+ }
+
+ public override void _ExitTree()
+ {
+#if TOOLS
+ if (Engine.IsEditorHint() && _activityObject != null)
+ {
+ _activityObject.QueueFree();
+ _activityObject = null;
+ }
+#endif
+ }
+
+ private void DoCreateObject()
+ {
+ if (_createFlag)
+ {
+ return;
+ }
+
+ _createFlag = true;
+ var activityObject = ActivityObject.Create(Id);
+ activityObject.Position = GlobalPosition;
+ activityObject.Scale = GlobalScale;
+ activityObject.Rotation = GlobalRotation;
+ activityObject.Name = Name;
+ activityObject.Visible = Visible;
+ activityObject.ShadowOffset = _showOffset;
+ activityObject.Altitude = _altitude;
+ activityObject.EnableVerticalMotion = VerticalMotion;
+ activityObject.PutDown(DefaultLayer, _showSprite);
+ QueueFree();
+ }
+
+ private void OnChangeActivityId(string id)
+ {
+ _prevId = id;
+
+ if (_activityObject != null)
+ {
+ _activityObject.QueueFree();
+ _activityObject = null;
+ }
+
+ if (string.IsNullOrEmpty(id))
+ {
+ GD.Print("删除物体");
+ ShowErrorSprite();
+ return;
+ }
+
+ if (_jsonText == null)
+ {
+ _jsonText = File.ReadAllText("resource/config/ActivityBase.json");
+ }
+ var str = $"\"Id\": \"{id}\",";
+ var index = _jsonText.IndexOf(str, StringComparison.Ordinal);
+ if (index > -1)
+ {
+ const string s = "\"Prefab\": \"";
+ var startIndex = _jsonText.IndexOf(s, index, StringComparison.Ordinal);
+ if (startIndex > -1)
+ {
+ var endIndex = _jsonText.IndexOf('"', startIndex + s.Length + 1);
+ if (endIndex > -1)
+ {
+ var prefab = _jsonText.Substring(startIndex + s.Length, endIndex - (startIndex + s.Length));
+ GD.Print("创建物体: " + id);
+ var instance = ResourceManager.LoadAndInstantiate(prefab);
+ _activityObject = instance;
+ _collPos = instance.Collision.Position - instance.AnimatedSprite.Position - instance.AnimatedSprite.Offset;
+ Debug.Log("_collPos: " + _collPos);
+ instance.IsCustomShadowSprite = instance.ShadowSprite.Texture != null;
+ instance.Altitude = _altitude;
+ instance.ShadowOffset = _showOffset;
+ if (_showSprite)
+ {
+ instance.ShowShadowSprite();
+ }
+ AddChild(instance);
+ HideErrorSprite();
+ return;
+ }
+ }
+ }
+ GD.PrintErr($"未找到Id为'{id}'的物体!");
+ ShowErrorSprite();
+ }
+
+ private void OnChangeCollisionVisible()
+ {
+ if (_activityObject != null)
+ {
+ Utils.EachNode(_activityObject, node =>
+ {
+ if (node is CollisionShape2D collisionShape2D)
+ {
+ collisionShape2D.Visible = _collisionVisible;
+ }
+ else if (node is CollisionPolygon2D collisionPolygon2D)
+ {
+ collisionPolygon2D.Visible = _collisionVisible;
+ }
+ });
+ }
+ }
+
+ private void ShowErrorSprite()
+ {
+ if (_errorSprite == null)
+ {
+ _errorSprite = new Sprite2D();
+ _errorSprite.Texture = ResourceManager.LoadTexture2D(ResourcePath.resource_sprite_ui_commonIcon_Error_mini_png);
+ AddChild(_errorSprite);
+ }
+ }
+
+ private void HideErrorSprite()
+ {
+ if (_errorSprite != null)
+ {
+ _errorSprite.QueueFree();
+ _errorSprite = null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/DungeonShooting_Godot/src/framework/activity/ActivityObject.cs b/DungeonShooting_Godot/src/framework/activity/ActivityObject.cs
index fc03323..e5b5a58 100644
--- a/DungeonShooting_Godot/src/framework/activity/ActivityObject.cs
+++ b/DungeonShooting_Godot/src/framework/activity/ActivityObject.cs
@@ -245,7 +245,7 @@
///
/// 是否是自定义阴影纹理
///
- public bool IsCustomShadowSprite { get; private set; }
+ public bool IsCustomShadowSprite { get; set; }
///
/// 记录绘制液体的笔刷上一次绘制的位置
@@ -1361,8 +1361,10 @@
ShadowSprite.GlobalPosition = new Vector2(pos.X + ShadowOffset.X, pos.Y + ShadowOffset.Y + Altitude);
}
- //计算位置
- private void CalcThrowAnimatedPosition()
+ ///
+ /// 计算物体精灵和阴影位置
+ ///
+ public void CalcThrowAnimatedPosition()
{
if (Scale.Y < 0)
{
diff --git a/DungeonShooting_Godot/src/framework/common/Utils.cs b/DungeonShooting_Godot/src/framework/common/Utils.cs
index be6cc8e..9b3dbd7 100644
--- a/DungeonShooting_Godot/src/framework/common/Utils.cs
+++ b/DungeonShooting_Godot/src/framework/common/Utils.cs
@@ -1,3 +1,4 @@
+using System;
using System.Collections.Generic;
using Godot;
using UI.TileSetEditorCombination;
@@ -554,4 +555,17 @@
}
return list.ToArray();
}
+
+ ///
+ /// 遍历节点树
+ ///
+ public static void EachNode(Node node, Action action)
+ {
+ action(node);
+ var childCount = node.GetChildCount();
+ for (var i = 0; i < childCount; i++)
+ {
+ EachNode(node.GetChild(i), action);
+ }
+ }
}
\ No newline at end of file
diff --git a/DungeonShooting_Godot/src/game/World.cs b/DungeonShooting_Godot/src/game/World.cs
index aaa8d72..421110e 100644
--- a/DungeonShooting_Godot/src/game/World.cs
+++ b/DungeonShooting_Godot/src/game/World.cs
@@ -11,7 +11,7 @@
///
/// 当前的游戏世界对象
///
- public static World Current => GameApplication.Instance.DungeonManager.CurrWorld;
+ public static World Current => GameApplication.Instance?.DungeonManager?.CurrWorld;
///
/// //对象根节点