diff --git a/DungeonShooting_Godot/prefab/role/Enemy0001.tscn b/DungeonShooting_Godot/prefab/role/Enemy0001.tscn
index 6f76541..f00e445 100644
--- a/DungeonShooting_Godot/prefab/role/Enemy0001.tscn
+++ b/DungeonShooting_Godot/prefab/role/Enemy0001.tscn
@@ -272,11 +272,12 @@
"query": SubResource("Animation_usfrh")
}
-[node name="Enemy0001" node_paths=PackedStringArray("ViewRay", "NavigationAgent2D", "NavigationPoint", "HurtArea", "HurtCollision", "InteractiveArea", "InteractiveCollision", "TipRoot", "TipSprite", "AnimationPlayer", "MountPoint", "BackMountPoint", "MeleeAttackArea", "MeleeAttackCollision", "ShadowSprite", "AnimatedSprite", "Collision") instance=ExtResource("1_2vqwe")]
+[node name="Enemy0001" node_paths=PackedStringArray("ViewRay", "NavigationAgent2D", "NavigationPoint", "FirePoint", "HurtArea", "HurtCollision", "InteractiveArea", "InteractiveCollision", "TipRoot", "TipSprite", "AnimationPlayer", "MountPoint", "BackMountPoint", "MeleeAttackArea", "MeleeAttackCollision", "ShadowSprite", "AnimatedSprite", "Collision") instance=ExtResource("1_2vqwe")]
script = ExtResource("2_0pcq3")
ViewRay = NodePath("ViewRay")
NavigationAgent2D = NodePath("NavigationPoint/NavigationAgent2D")
NavigationPoint = NodePath("NavigationPoint")
+FirePoint = NodePath("FirePoint")
HurtArea = NodePath("HurtArea")
HurtCollision = NodePath("HurtArea/HurtCollision")
InteractiveArea = NodePath("InteractiveArea")
@@ -302,7 +303,10 @@
[node name="HurtCollision" parent="HurtArea" index="0"]
shape = SubResource("RectangleShape2D_rkrey")
-[node name="AnimationPlayer" parent="." index="10"]
+[node name="FirePoint" parent="." index="8"]
+position = Vector2(2, -9)
+
+[node name="AnimationPlayer" parent="." index="11"]
libraries = {
"": SubResource("AnimationLibrary_ur1ug")
}
diff --git a/DungeonShooting_Godot/prefab/role/Enemy0002.tscn b/DungeonShooting_Godot/prefab/role/Enemy0002.tscn
index 1e08932..e869f0e 100644
--- a/DungeonShooting_Godot/prefab/role/Enemy0002.tscn
+++ b/DungeonShooting_Godot/prefab/role/Enemy0002.tscn
@@ -1,11 +1,11 @@
-[gd_scene load_steps=7 format=3 uid="uid://qqktspyolb34"]
+[gd_scene load_steps=10 format=3 uid="uid://daqsdld5gnwwr"]
-[ext_resource type="PackedScene" uid="uid://cyrcv2jdgr8cf" path="res://prefab/role/template/RoleTemplate.tscn" id="1_coayb"]
+[ext_resource type="PackedScene" uid="uid://dbrig6dq441wo" path="res://prefab/role/template/EnemyTemplate.tscn" id="1_fanet"]
[ext_resource type="Script" path="res://src/game/activity/role/enemy/NoWeaponEnemy.cs" id="2_3an4s"]
[ext_resource type="Shader" path="res://resource/material/Blend.gdshader" id="2_yunbp"]
[ext_resource type="SpriteFrames" uid="uid://ctpkpxgcwb583" path="res://resource/spriteFrames/role/Enemy0002.tres" id="3_hbsqi"]
-[sub_resource type="ShaderMaterial" id="ShaderMaterial_8vxx6"]
+[sub_resource type="ShaderMaterial" id="ShaderMaterial_5rnql"]
resource_local_to_scene = true
shader = ExtResource("2_yunbp")
shader_parameter/blend = Color(0, 0, 0, 0.470588)
@@ -16,7 +16,7 @@
shader_parameter/outline_rainbow = false
shader_parameter/outline_use_blend = true
-[sub_resource type="ShaderMaterial" id="ShaderMaterial_k8mt5"]
+[sub_resource type="ShaderMaterial" id="ShaderMaterial_4qvs8"]
resource_local_to_scene = true
shader = ExtResource("2_yunbp")
shader_parameter/blend = Color(1, 1, 1, 1)
@@ -27,14 +27,76 @@
shader_parameter/outline_rainbow = false
shader_parameter/outline_use_blend = true
-[node name="Enemy0002" node_paths=PackedStringArray("ViewRay", "NavigationAgent2D", "NavigationPoint", "HurtArea", "HurtCollision", "InteractiveArea", "InteractiveCollision", "TipRoot", "TipSprite", "AnimationPlayer", "MountPoint", "BackMountPoint", "MeleeAttackArea", "MeleeAttackCollision", "ShadowSprite", "AnimatedSprite", "Collision") instance=ExtResource("1_coayb")]
-collision_layer = 16
-collision_mask = 25
+[sub_resource type="Animation" id="Animation_343jg"]
+length = 0.001
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath("AnimatedSprite:frame")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 1,
+"values": [0]
+}
+
+[sub_resource type="Animation" id="Animation_bn678"]
+resource_name = "attack"
+length = 0.6
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath("AnimatedSprite:animation")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 1,
+"values": [&"attack"]
+}
+tracks/1/type = "value"
+tracks/1/imported = false
+tracks/1/enabled = true
+tracks/1/path = NodePath("AnimatedSprite:frame")
+tracks/1/interp = 1
+tracks/1/loop_wrap = true
+tracks/1/keys = {
+"times": PackedFloat32Array(0, 0.5),
+"transitions": PackedFloat32Array(1, 1),
+"update": 0,
+"values": [0, 7]
+}
+tracks/2/type = "method"
+tracks/2/imported = false
+tracks/2/enabled = true
+tracks/2/path = NodePath(".")
+tracks/2/interp = 1
+tracks/2/loop_wrap = true
+tracks/2/keys = {
+"times": PackedFloat32Array(0.3),
+"transitions": PackedFloat32Array(1),
+"values": [{
+"args": [],
+"method": &"ShootBullet"
+}]
+}
+
+[sub_resource type="AnimationLibrary" id="AnimationLibrary_3ge8m"]
+_data = {
+"RESET": SubResource("Animation_343jg"),
+"attack": SubResource("Animation_bn678")
+}
+
+[node name="Enemy0002" node_paths=PackedStringArray("ViewRay", "NavigationAgent2D", "NavigationPoint", "FirePoint", "HurtArea", "HurtCollision", "InteractiveArea", "InteractiveCollision", "TipRoot", "TipSprite", "AnimationPlayer", "MountPoint", "BackMountPoint", "MeleeAttackArea", "MeleeAttackCollision", "ShadowSprite", "AnimatedSprite", "Collision") instance=ExtResource("1_fanet")]
script = ExtResource("2_3an4s")
CanPickUpWeapon = false
ViewRay = NodePath("ViewRay")
NavigationAgent2D = NodePath("NavigationPoint/NavigationAgent2D")
NavigationPoint = NodePath("NavigationPoint")
+FirePoint = NodePath("FirePoint")
HurtArea = NodePath("HurtArea")
HurtCollision = NodePath("HurtArea/HurtCollision")
InteractiveArea = NodePath("InteractiveArea")
@@ -51,30 +113,24 @@
Collision = NodePath("Collision")
[node name="ShadowSprite" parent="." index="0"]
-material = SubResource("ShaderMaterial_8vxx6")
-
-[node name="BackMountPoint" parent="." index="1"]
-position = Vector2(-2, -7)
+material = SubResource("ShaderMaterial_5rnql")
[node name="AnimatedSprite" parent="." index="2"]
-material = SubResource("ShaderMaterial_k8mt5")
+material = SubResource("ShaderMaterial_4qvs8")
sprite_frames = ExtResource("3_hbsqi")
+animation = &"attack"
offset = Vector2(0, -10)
[node name="HurtCollision" parent="HurtArea" index="0"]
-position = Vector2(-0.5, -7)
-
-[node name="ViewRay" type="RayCast2D" parent="." index="6"]
-position = Vector2(0, -8)
-enabled = false
+position = Vector2(0, -7)
[node name="MountPoint" parent="." index="7"]
-position = Vector2(6, -8)
+position = Vector2(4, -9)
-[node name="NavigationPoint" type="Marker2D" parent="." index="8"]
-position = Vector2(0, -5)
+[node name="FirePoint" parent="." index="8"]
+position = Vector2(7, -6)
-[node name="NavigationAgent2D" type="NavigationAgent2D" parent="NavigationPoint" index="0"]
-path_desired_distance = 3.0
-target_desired_distance = 3.0
-radius = 20.0
+[node name="AnimationPlayer" parent="." index="11"]
+libraries = {
+"": SubResource("AnimationLibrary_3ge8m")
+}
diff --git a/DungeonShooting_Godot/prefab/role/template/EnemyTemplate.tscn b/DungeonShooting_Godot/prefab/role/template/EnemyTemplate.tscn
index 272b97a..28fcf5f 100644
--- a/DungeonShooting_Godot/prefab/role/template/EnemyTemplate.tscn
+++ b/DungeonShooting_Godot/prefab/role/template/EnemyTemplate.tscn
@@ -25,7 +25,7 @@
shader_parameter/outline_rainbow = false
shader_parameter/outline_use_blend = true
-[node name="AdvancedEnemyTemplate" instance=ExtResource("1_5po38")]
+[node name="EnemyTemplate" instance=ExtResource("1_5po38")]
collision_layer = 16
collision_mask = 25
@@ -39,7 +39,9 @@
position = Vector2(0, -8)
enabled = false
-[node name="NavigationPoint" type="Marker2D" parent="." index="8"]
+[node name="FirePoint" type="Marker2D" parent="." index="8"]
+
+[node name="NavigationPoint" type="Marker2D" parent="." index="9"]
position = Vector2(0, -5)
[node name="NavigationAgent2D" type="NavigationAgent2D" parent="NavigationPoint" index="0"]
diff --git a/DungeonShooting_Godot/prefab/role/template/RoleTemplate.tscn b/DungeonShooting_Godot/prefab/role/template/RoleTemplate.tscn
index 7b79ea0..edd302e 100644
--- a/DungeonShooting_Godot/prefab/role/template/RoleTemplate.tscn
+++ b/DungeonShooting_Godot/prefab/role/template/RoleTemplate.tscn
@@ -35,7 +35,7 @@
[sub_resource type="RectangleShape2D" id="RectangleShape2D_n68nu"]
size = Vector2(10, 16.5)
-[node name="AdvancedRoleTemplate" type="CharacterBody2D"]
+[node name="RoleTemplate" type="CharacterBody2D"]
collision_layer = 0
[node name="ShadowSprite" type="Sprite2D" parent="."]
diff --git a/DungeonShooting_Godot/src/game/AnimatorNames.cs b/DungeonShooting_Godot/src/game/AnimatorNames.cs
index 56e3289..bf3d97d 100644
--- a/DungeonShooting_Godot/src/game/AnimatorNames.cs
+++ b/DungeonShooting_Godot/src/game/AnimatorNames.cs
@@ -9,85 +9,85 @@
///
/// 默认动画
///
- public const string Default = "default";
+ public static readonly StringName Default = "default";
///
/// 静止不动
///
- public const string Idle = "idle";
+ public static readonly StringName Idle = "idle";
///
/// 奔跑
///
- public const string Run = "run";
+ public static readonly StringName Run = "run";
///
/// 倒退奔跑
///
- public const string ReverseRun = "reverseRun";
+ public static readonly StringName ReverseRun = "reverseRun";
///
/// 翻滚
///
- public const string Roll = "roll";
+ public static readonly StringName Roll = "roll";
///
/// 武器泛光动画
///
- public const string Floodlight = "floodlight";
+ public static readonly StringName Floodlight = "floodlight";
///
/// 开门动画
///
- public const string OpenDoor = "openDoor";
+ public static readonly StringName OpenDoor = "openDoor";
///
/// 关门动画
///
- public const string CloseDoor = "closeDoor";
+ public static readonly StringName CloseDoor = "closeDoor";
///
/// 开火
///
- public const string Fire = "fire";
+ public static readonly StringName Fire = "fire";
///
/// 换弹
///
- public const string Reloading = "reloading";
+ public static readonly StringName Reloading = "reloading";
///
/// 子弹上膛
///
- public const string BeLoaded = "beLoaded";
+ public static readonly StringName BeLoaded = "beLoaded";
///
/// ui入场
///
- public const string In = "in";
+ public static readonly StringName In = "in";
///
/// ui出场
///
- public const string Out = "out";
+ public static readonly StringName Out = "out";
///
/// 显示动画
///
- public const string Show = "show";
+ public static readonly StringName Show = "show";
///
/// 播放特效
///
- public const string Play = "play";
+ public static readonly StringName Play = "play";
///
/// 物体移动
///
- public const string Move = "move";
+ public static readonly StringName Move = "move";
///
/// 攻击
///
- public const string Attack = "attack";
+ public static readonly StringName Attack = "attack";
///
/// 惊讶动作
///
- public const string Astonished = "astonished";
+ public static readonly StringName Astonished = "astonished";
///
/// 通知动作
///
- public const string Notify = "notify";
+ public static readonly StringName Notify = "notify";
///
/// 疑惑动作
///
- public const string Query = "query";
+ public static readonly StringName Query = "query";
///
/// 重置动画
///
- public const string Reset = "RESET";
+ public static readonly StringName Reset = "RESET";
}
\ No newline at end of file
diff --git a/DungeonShooting_Godot/src/game/activity/role/Role.cs b/DungeonShooting_Godot/src/game/activity/role/Role.cs
index 3a4e483..15541ef 100644
--- a/DungeonShooting_Godot/src/game/activity/role/Role.cs
+++ b/DungeonShooting_Godot/src/game/activity/role/Role.cs
@@ -139,12 +139,32 @@
///
/// 是否处于攻击中, 近战攻击远程攻击都算
///
- public bool IsAttack => AttackTimer > 0;
+ public bool IsAttack
+ {
+ get
+ {
+ if (AttackTimer > 0 || MeleeAttackTimer > 0)
+ {
+ return true;
+ }
+ var weapon = WeaponPack.ActiveItem;
+ if (weapon != null)
+ {
+ return weapon.GetAttackTimer() > 0 || weapon.GetContinuousCount() > 0;
+ }
+ return false;
+ }
+ }
///
/// 攻击计时器
///
public float AttackTimer { get; set; }
+
+ ///
+ /// 近战计时器
+ ///
+ public float MeleeAttackTimer { get; set; }
///
/// 是否死亡
@@ -464,6 +484,11 @@
{
AttackTimer -= delta;
}
+
+ if (MeleeAttackTimer > 0)
+ {
+ MeleeAttackTimer -= delta;
+ }
//检查可互动的物体
bool findFlag = false;
@@ -1157,7 +1182,7 @@
///
public virtual void Attack()
{
- if (!IsAttack && WeaponPack.ActiveItem != null)
+ if (MeleeAttackTimer <= 0 && WeaponPack.ActiveItem != null)
{
WeaponPack.ActiveItem.Trigger(this);
}
@@ -1168,14 +1193,14 @@
///
public virtual void MeleeAttack()
{
- if (IsAttack || AttackTimer > 0)
+ if (IsAttack)
{
return;
}
if (WeaponPack.ActiveItem != null && WeaponPack.ActiveItem.Attribute.CanMeleeAttack)
{
- AttackTimer = RoleState.MeleeAttackTime;
+ MeleeAttackTimer = RoleState.MeleeAttackTime;
MountLookTarget = false;
//播放近战动画
diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/Enemy.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/Enemy.cs
index 4876e62..90c89dd 100644
--- a/DungeonShooting_Godot/src/game/activity/role/enemy/Enemy.cs
+++ b/DungeonShooting_Godot/src/game/activity/role/enemy/Enemy.cs
@@ -68,6 +68,12 @@
///
[Export, ExportFillNode]
public Marker2D NavigationPoint { get; set; }
+
+ ///
+ /// 不通过武发射子弹的开火点
+ ///
+ [Export, ExportFillNode]
+ public Marker2D FirePoint { get; set; }
///
/// 当前敌人所看向的对象, 也就是枪口指向的对象
diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/NoWeaponEnemy.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/NoWeaponEnemy.cs
index b66c3ab..406dc9f 100644
--- a/DungeonShooting_Godot/src/game/activity/role/enemy/NoWeaponEnemy.cs
+++ b/DungeonShooting_Godot/src/game/activity/role/enemy/NoWeaponEnemy.cs
@@ -1,4 +1,5 @@
+using Config;
using Godot;
///
@@ -7,8 +8,32 @@
[Tool]
public partial class NoWeaponEnemy : Enemy
{
+ public override void OnInit()
+ {
+ base.OnInit();
+ AnimationPlayer.AnimationFinished += OnAnimationFinished;
+ }
+
public override void Attack()
{
- Debug.Log("attack...");
+ if (AnimatedSprite.Animation != AnimatorNames.Attack)
+ {
+ Debug.Log("attack...");
+ AnimatedSprite.Play(AnimatorNames.Attack);
+ }
+ }
+
+ public void ShootBullet()
+ {
+ var bulletData = FireManager.GetBulletData(this, FirePoint.GlobalPosition.AngleTo(LookTarget.Position), ExcelConfig.BulletBase_Map["0006"]);
+ FireManager.ShootBullet(bulletData, AttackLayer);
+ }
+
+ private void OnAnimationFinished(StringName name)
+ {
+ if (name == AnimatorNames.Attack)
+ {
+ AttackTimer = 2f;
+ }
}
}
\ No newline at end of file
diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/state/AiAttackState.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/state/AiAttackState.cs
index 128ec1a..6b70f5e 100644
--- a/DungeonShooting_Godot/src/game/activity/role/enemy/state/AiAttackState.cs
+++ b/DungeonShooting_Godot/src/game/activity/role/enemy/state/AiAttackState.cs
@@ -14,7 +14,7 @@
public AIStateEnum PrevState;
///
- /// 攻击状态
+ /// 武器攻击状态
///
public AiAttackEnum AttackState;
@@ -219,9 +219,9 @@
//找到武器了, 攻击结束
ChangeState(PrevState);
}
- else if (AttackState == AiAttackEnum.AttackInterval) //攻击结束
+ else if (Master.AttackTimer > 0 || Master.MeleeAttackTimer > 0) //攻击结束
{
-
+ ChangeState(PrevState);
}
else //攻击状态
{
diff --git a/DungeonShooting_Godot/src/game/manager/FireManager.cs b/DungeonShooting_Godot/src/game/manager/FireManager.cs
index 3f02409..b7c50db 100644
--- a/DungeonShooting_Godot/src/game/manager/FireManager.cs
+++ b/DungeonShooting_Godot/src/game/manager/FireManager.cs
@@ -218,8 +218,15 @@
Penetration = Utils.Random.RandomConfigRange(bullet.Penetration),
};
- data.Position = role.MountPoint.GlobalPosition;
-
+ if (role is Enemy enemy)
+ {
+ data.Position = enemy.FirePoint.GlobalPosition;
+ }
+ else
+ {
+ data.Position = role.MountPoint.GlobalPosition;
+ }
+
var deviationAngle = Utils.Random.RandomConfigRange(bullet.DeviationAngleRange);
data.Altitude = role.GetFirePointAltitude();
var roleState = role.RoleState;