diff --git a/DungeonShooting_Godot/prefab/role/Enemy0001.tscn b/DungeonShooting_Godot/prefab/role/Enemy0001.tscn
index deb7e34..7eac0c4 100644
--- a/DungeonShooting_Godot/prefab/role/Enemy0001.tscn
+++ b/DungeonShooting_Godot/prefab/role/Enemy0001.tscn
@@ -32,6 +32,7 @@
[sub_resource type="Animation" id="Animation_nb4pe"]
resource_name = "astonished"
length = 0.6
+step = 0.05
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
@@ -56,6 +57,42 @@
"update": 1,
"values": [ExtResource("5_0p4q8")]
}
+tracks/2/type = "value"
+tracks/2/imported = false
+tracks/2/enabled = true
+tracks/2/path = NodePath("AnimatedSprite:scale")
+tracks/2/interp = 1
+tracks/2/loop_wrap = true
+tracks/2/keys = {
+"times": PackedFloat32Array(0, 0.05, 0.15, 0.25, 0.35, 0.45),
+"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1),
+"update": 0,
+"values": [Vector2(1, 1), Vector2(0.8, 0.8), Vector2(1.2, 1.2), Vector2(0.9, 0.9), Vector2(1.1, 1.1), Vector2(1, 1)]
+}
+tracks/3/type = "value"
+tracks/3/imported = false
+tracks/3/enabled = true
+tracks/3/path = NodePath("TipSprite:modulate")
+tracks/3/interp = 1
+tracks/3/loop_wrap = true
+tracks/3/keys = {
+"times": PackedFloat32Array(0, 0.1, 0.5, 0.6),
+"transitions": PackedFloat32Array(1, 1, 1, 1),
+"update": 0,
+"values": [Color(1, 1, 1, 0), Color(1, 1, 1, 1), Color(1, 1, 1, 1), Color(1, 1, 1, 0)]
+}
+tracks/4/type = "value"
+tracks/4/imported = false
+tracks/4/enabled = true
+tracks/4/path = NodePath("TipSprite:position")
+tracks/4/interp = 1
+tracks/4/loop_wrap = true
+tracks/4/keys = {
+"times": PackedFloat32Array(0, 0.2, 0.45, 0.6),
+"transitions": PackedFloat32Array(1, 1, 1, 1),
+"update": 0,
+"values": [Vector2(0, -22), Vector2(0, -28), Vector2(0, -28), Vector2(0, -35)]
+}
[sub_resource type="Animation" id="Animation_0l5k0"]
length = 0.001
@@ -83,6 +120,42 @@
"update": 1,
"values": [ExtResource("5_0p4q8")]
}
+tracks/2/type = "value"
+tracks/2/imported = false
+tracks/2/enabled = true
+tracks/2/path = NodePath("AnimatedSprite:scale")
+tracks/2/interp = 1
+tracks/2/loop_wrap = true
+tracks/2/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [Vector2(1, 1)]
+}
+tracks/3/type = "value"
+tracks/3/imported = false
+tracks/3/enabled = true
+tracks/3/path = NodePath("TipSprite:modulate")
+tracks/3/interp = 1
+tracks/3/loop_wrap = true
+tracks/3/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [Color(1, 1, 1, 0)]
+}
+tracks/4/type = "value"
+tracks/4/imported = false
+tracks/4/enabled = true
+tracks/4/path = NodePath("TipSprite:position")
+tracks/4/interp = 1
+tracks/4/loop_wrap = true
+tracks/4/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [Vector2(0, -22)]
+}
[sub_resource type="Animation" id="Animation_5mflw"]
resource_name = "notify"
@@ -146,7 +219,8 @@
sprite_frames = ExtResource("4_qv8w5")
[node name="TipSprite" parent="." index="9"]
-position = Vector2(0, -28)
+modulate = Color(1, 1, 1, 0)
+position = Vector2(0, -22)
[node name="AnimationPlayer" parent="." index="10"]
libraries = {
diff --git a/DungeonShooting_Godot/prefab/role/template/AdvancedEnemyTemplate.tscn b/DungeonShooting_Godot/prefab/role/template/AdvancedEnemyTemplate.tscn
index e622500..58209e0 100644
--- a/DungeonShooting_Godot/prefab/role/template/AdvancedEnemyTemplate.tscn
+++ b/DungeonShooting_Godot/prefab/role/template/AdvancedEnemyTemplate.tscn
@@ -35,6 +35,8 @@
[node name="AnimatedSprite" parent="." index="2"]
material = SubResource("ShaderMaterial_k8mt5")
+position = Vector2(0, 0)
+offset = Vector2(0, -12)
[node name="ViewRay" type="RayCast2D" parent="." index="6"]
position = Vector2(0, -8)
diff --git a/DungeonShooting_Godot/prefab/role/template/AdvancedRoleTemplate.tscn b/DungeonShooting_Godot/prefab/role/template/AdvancedRoleTemplate.tscn
index 9e6bb5f..3874d8b 100644
--- a/DungeonShooting_Godot/prefab/role/template/AdvancedRoleTemplate.tscn
+++ b/DungeonShooting_Godot/prefab/role/template/AdvancedRoleTemplate.tscn
@@ -46,7 +46,7 @@
[node name="AnimatedSprite" type="AnimatedSprite2D" parent="."]
material = SubResource("ShaderMaterial_yif6x")
-position = Vector2(0, -12)
+offset = Vector2(0, -12)
[node name="Collision" type="CollisionShape2D" parent="."]
position = Vector2(0, -4)
diff --git a/DungeonShooting_Godot/prefab/role/template/RoleTemplate.tscn b/DungeonShooting_Godot/prefab/role/template/RoleTemplate.tscn
index 454bcbd..b001cfc 100644
--- a/DungeonShooting_Godot/prefab/role/template/RoleTemplate.tscn
+++ b/DungeonShooting_Godot/prefab/role/template/RoleTemplate.tscn
@@ -42,7 +42,7 @@
[node name="AnimatedSprite" type="AnimatedSprite2D" parent="."]
material = SubResource("ShaderMaterial_yif6x")
-position = Vector2(0, -12)
+offset = Vector2(0, -12)
[node name="Collision" type="CollisionShape2D" parent="."]
position = Vector2(0, -4)
diff --git a/DungeonShooting_Godot/resource/sprite/role/common/Role_astonished.png b/DungeonShooting_Godot/resource/sprite/role/common/Role_astonished.png
new file mode 100644
index 0000000..6ba090b
--- /dev/null
+++ b/DungeonShooting_Godot/resource/sprite/role/common/Role_astonished.png
Binary files differ
diff --git a/DungeonShooting_Godot/resource/sprite/role/common/Role_astonished.png.import b/DungeonShooting_Godot/resource/sprite/role/common/Role_astonished.png.import
new file mode 100644
index 0000000..6eb2d0d
--- /dev/null
+++ b/DungeonShooting_Godot/resource/sprite/role/common/Role_astonished.png.import
@@ -0,0 +1,34 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://b75k7hefqy3tm"
+path="res://.godot/imported/Role_astonished.png-8166b8786411283003a535d1677d0104.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://resource/sprite/role/common/Role_astonished.png"
+dest_files=["res://.godot/imported/Role_astonished.png-8166b8786411283003a535d1677d0104.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/sprite/role/common/Role_notify.png b/DungeonShooting_Godot/resource/sprite/role/common/Role_notify.png
new file mode 100644
index 0000000..b93ffca
--- /dev/null
+++ b/DungeonShooting_Godot/resource/sprite/role/common/Role_notify.png
Binary files differ
diff --git a/DungeonShooting_Godot/resource/sprite/role/common/Role_notify.png.import b/DungeonShooting_Godot/resource/sprite/role/common/Role_notify.png.import
new file mode 100644
index 0000000..0bd8a72
--- /dev/null
+++ b/DungeonShooting_Godot/resource/sprite/role/common/Role_notify.png.import
@@ -0,0 +1,34 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://6jka6itu76x7"
+path="res://.godot/imported/Role_notify.png-be3f9ba9bf6d85ab3633bbe6cbe960e3.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://resource/sprite/role/common/Role_notify.png"
+dest_files=["res://.godot/imported/Role_notify.png-be3f9ba9bf6d85ab3633bbe6cbe960e3.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/src/framework/activity/ActivityObject.cs b/DungeonShooting_Godot/src/framework/activity/ActivityObject.cs
index 162153c..b4bfe60 100644
--- a/DungeonShooting_Godot/src/framework/activity/ActivityObject.cs
+++ b/DungeonShooting_Godot/src/framework/activity/ActivityObject.cs
@@ -18,6 +18,11 @@
public static bool IsDebug { get; set; }
///
+ /// 实例唯一 Id
+ ///
+ public long Id { get; set; }
+
+ ///
/// 当前物体对应的配置数据, 如果不是通过 ActivityObject.Create() 函数创建出来的对象那么 ItemConfig 为 null
///
public ExcelConfig.ActivityBase ActivityBase { get; private set; }
@@ -361,6 +366,7 @@
World = world;
ActivityBase = config;
Name = GetType().Name + (_instanceIndex++);
+ Id = _instanceIndex;
_blendShaderMaterial = AnimatedSprite.Material as ShaderMaterial;
_shadowBlendShaderMaterial = ShadowSprite.Material as ShaderMaterial;
if (_blendShaderMaterial != null)
@@ -1333,6 +1339,8 @@
///
public void CalcShadowTransform()
{
+ //偏移
+ ShadowSprite.Offset = AnimatedSprite.Offset;
//缩放
ShadowSprite.Scale = AnimatedSprite.Scale;
//阴影角度
diff --git a/DungeonShooting_Godot/src/framework/map/room/RoomInfo.cs b/DungeonShooting_Godot/src/framework/map/room/RoomInfo.cs
index a249dda..39bb1f9 100644
--- a/DungeonShooting_Godot/src/framework/map/room/RoomInfo.cs
+++ b/DungeonShooting_Godot/src/framework/map/room/RoomInfo.cs
@@ -104,6 +104,11 @@
/// 是否处于闭关状态, 也就是房间门没有主动打开
///
public bool IsSeclusion { get; private set; } = false;
+
+ ///
+ /// 用于标记攻击目标位置
+ ///
+ public Dictionary MarkTargetPosition { get; private set; } = new Dictionary();
public bool IsDestroyed { get; private set; }
private bool _openDoorFlag = true;
@@ -340,6 +345,8 @@
{
AffiliationArea.Destroy();
}
+
+ MarkTargetPosition.Clear();
}
///
diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/AdvancedEnemy.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/AdvancedEnemy.cs
index f93a65f..97dc009 100644
--- a/DungeonShooting_Godot/src/game/activity/role/enemy/AdvancedEnemy.cs
+++ b/DungeonShooting_Godot/src/game/activity/role/enemy/AdvancedEnemy.cs
@@ -459,4 +459,15 @@
AnimatedSprite.Play(AnimatorNames.Idle);
BasisVelocity = Vector2.Zero;
}
+
+ ///
+ /// 更新房间中标记的目标位置
+ ///
+ public void UpdateMarkTargetPosition()
+ {
+ if (LookTarget != null)
+ {
+ AffiliationArea.RoomInfo.MarkTargetPosition[LookTarget.Id] = LookTarget.Position;
+ }
+ }
}
diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiAttackState.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiAttackState.cs
index 7d8b30d..f49c137 100644
--- a/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiAttackState.cs
+++ b/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiAttackState.cs
@@ -74,6 +74,9 @@
public override void Process(float delta)
{
+ //更新标记位置
+ Master.UpdateMarkTargetPosition();
+
var weapon = Master.WeaponPack.ActiveItem;
if (weapon == null)
{
@@ -116,7 +119,7 @@
if (AttackState == AiAttackEnum.LockingTime) //锁定玩家状态
{
Master.LockTargetTime += delta;
-
+
var aiLockRemainderTime = Master.GetLockRemainderTime();
Master.MountLookTarget = aiLockRemainderTime >= weapon.Attribute.AiAttackAttr.LockAngleTime;
//更新瞄准辅助线
diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiFollowUpState.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiFollowUpState.cs
index 6d7f141..4a602a8 100644
--- a/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiFollowUpState.cs
+++ b/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiFollowUpState.cs
@@ -97,6 +97,8 @@
//在视野中
if (Master.TargetInView)
{
+ //更新标记位置
+ Master.UpdateMarkTargetPosition();
if (inAttackRange) //在攻击范围内
{
//距离够近, 可以切换到环绕模式
diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiLeaveForState.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiLeaveForState.cs
index 16fc162..058b053 100644
--- a/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiLeaveForState.cs
+++ b/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiLeaveForState.cs
@@ -46,16 +46,6 @@
}
}
- ///
- /// 设置移动目标位置
- ///
- public void SetTargetPosition(Vector2 target)
- {
- _targetPosition = target;
- _navigationUpdateTimer = _navigationInterval;
- Master.NavigationAgent2D.TargetPosition = target;
- }
-
public override void Process(float delta)
{
//这个状态下不会有攻击事件, 所以没必要每一帧检查是否弹药耗尽
@@ -65,6 +55,10 @@
{
//每隔一段时间秒更改目标位置
_navigationUpdateTimer = _navigationInterval;
+ if (Master.AffiliationArea.RoomInfo.MarkTargetPosition.TryGetValue(_target.Id, out var pos))
+ {
+ _targetPosition = pos;
+ }
Master.NavigationAgent2D.TargetPosition = _targetPosition;
}
else
diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiSurroundState.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiSurroundState.cs
index 6faee7a..875d365 100644
--- a/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiSurroundState.cs
+++ b/DungeonShooting_Godot/src/game/activity/role/enemy/advancedState/AiSurroundState.cs
@@ -73,6 +73,9 @@
//在视野中
if (Master.TargetInView)
{
+ //更新标记位置
+ Master.UpdateMarkTargetPosition();
+
if (_pauseTimer >= 0)
{
Master.AnimatedSprite.Play(AnimatorNames.Idle);