diff --git a/DungeonShooting_Godot/prefab/role/Enemy0001.tscn b/DungeonShooting_Godot/prefab/role/Enemy0001.tscn index 5f153c2..6d6eeaf 100644 --- a/DungeonShooting_Godot/prefab/role/Enemy0001.tscn +++ b/DungeonShooting_Godot/prefab/role/Enemy0001.tscn @@ -25,14 +25,16 @@ shader_parameter/outline_color = Color(0, 0, 0, 1) shader_parameter/outline_rainbow = false -[node name="Enemy0001" node_paths=PackedStringArray("HurtArea", "MountPoint", "BackMountPoint", "InteractiveArea", "ShadowSprite", "AnimatedSprite", "Collision") instance=ExtResource("1_5po38")] +[node name="Enemy0001" node_paths=PackedStringArray("HurtArea", "HurtCollision", "MountPoint", "BackMountPoint", "InteractiveArea", "InteractiveCollision", "ShadowSprite", "AnimatedSprite", "Collision") instance=ExtResource("1_5po38")] collision_layer = 16 collision_mask = 25 script = ExtResource("2_1plrq") HurtArea = NodePath("HurtArea") +HurtCollision = NodePath("HurtArea/HurtCollision") MountPoint = NodePath("MountPoint") BackMountPoint = NodePath("BackMountPoint") InteractiveArea = NodePath("InteractiveArea") +InteractiveCollision = NodePath("InteractiveArea/InteractiveCollision") ShadowSprite = NodePath("ShadowSprite") AnimatedSprite = NodePath("AnimatedSprite") Collision = NodePath("Collision") diff --git a/DungeonShooting_Godot/prefab/role/Role0001.tscn b/DungeonShooting_Godot/prefab/role/Role0001.tscn index 4560a76..196f400 100644 --- a/DungeonShooting_Godot/prefab/role/Role0001.tscn +++ b/DungeonShooting_Godot/prefab/role/Role0001.tscn @@ -1,7 +1,7 @@ [gd_scene load_steps=7 format=3 uid="uid://cxhrcytrx0kcf"] [ext_resource type="PackedScene" uid="uid://cyrcv2jdgr8cf" path="res://prefab/role/RoleTemplate.tscn" id="1_10c2n"] -[ext_resource type="Script" path="res://src/game/activity/role/Player.cs" id="2_i08u4"] +[ext_resource type="Script" path="res://src/game/activity/role/player/Player.cs" id="2_6xwnt"] [ext_resource type="Shader" path="res://resource/material/Blend.gdshader" id="3_rk4gg"] [ext_resource type="SpriteFrames" uid="uid://n11thtali6es" path="res://resource/spriteFrames/role/Role0001.tres" id="4_galcc"] @@ -25,13 +25,15 @@ shader_parameter/outline_color = Color(0, 0, 0, 1) shader_parameter/outline_rainbow = false -[node name="Role0001" node_paths=PackedStringArray("HurtArea", "MountPoint", "BackMountPoint", "InteractiveArea", "ShadowSprite", "AnimatedSprite", "Collision") instance=ExtResource("1_10c2n")] +[node name="Role0001" node_paths=PackedStringArray("HurtArea", "HurtCollision", "MountPoint", "BackMountPoint", "InteractiveArea", "InteractiveCollision", "ShadowSprite", "AnimatedSprite", "Collision") instance=ExtResource("1_10c2n")] collision_layer = 8 -script = ExtResource("2_i08u4") +script = ExtResource("2_6xwnt") HurtArea = NodePath("HurtArea") +HurtCollision = NodePath("HurtArea/HurtCollision") MountPoint = NodePath("MountPoint") BackMountPoint = NodePath("BackMountPoint") InteractiveArea = NodePath("InteractiveArea") +InteractiveCollision = NodePath("InteractiveArea/InteractiveCollision") ShadowSprite = NodePath("ShadowSprite") AnimatedSprite = NodePath("AnimatedSprite") Collision = NodePath("Collision") @@ -42,10 +44,6 @@ [node name="AnimatedSprite" parent="." index="2"] material = SubResource("ShaderMaterial_8hgu2") sprite_frames = ExtResource("4_galcc") -frame_progress = 0.0995217 - -[node name="CollisionShape2D" parent="HurtArea" index="0"] -position = Vector2(0, -12) [node name="MountPoint" parent="." index="6"] position = Vector2(2, -8) diff --git a/DungeonShooting_Godot/prefab/role/RoleTemplate.tscn b/DungeonShooting_Godot/prefab/role/RoleTemplate.tscn index fde7ce1..d55de02 100644 --- a/DungeonShooting_Godot/prefab/role/RoleTemplate.tscn +++ b/DungeonShooting_Godot/prefab/role/RoleTemplate.tscn @@ -8,7 +8,7 @@ shader = ExtResource("1_xk5yk") shader_parameter/blend = Color(0, 0, 0, 0.470588) shader_parameter/schedule = 0.0 -shader_parameter/alpha = 1.0 +shader_parameter/modulate = Color(1, 1, 1, 1) shader_parameter/show_outline = true shader_parameter/outline_color = Color(0, 0, 0, 1) shader_parameter/outline_rainbow = false @@ -18,7 +18,7 @@ shader = ExtResource("1_xk5yk") shader_parameter/blend = Color(1, 1, 1, 1) shader_parameter/schedule = 0.0 -shader_parameter/alpha = 1.0 +shader_parameter/modulate = Color(1, 1, 1, 1) shader_parameter/show_outline = true shader_parameter/outline_color = Color(0, 0, 0, 1) shader_parameter/outline_rainbow = false @@ -54,7 +54,7 @@ collision_mask = 0 monitoring = false -[node name="CollisionShape2D" type="CollisionShape2D" parent="HurtArea"] +[node name="HurtCollision" type="CollisionShape2D" parent="HurtArea"] position = Vector2(0, -9) shape = SubResource("RectangleShape2D_1eja2") @@ -64,7 +64,7 @@ collision_mask = 4 monitorable = false -[node name="Collision" type="CollisionShape2D" parent="InteractiveArea"] +[node name="InteractiveCollision" type="CollisionShape2D" parent="InteractiveArea"] position = Vector2(0, -5) shape = SubResource("RectangleShape2D_n68nu") diff --git a/DungeonShooting_Godot/resource/spriteFrames/role/Role0001.tres b/DungeonShooting_Godot/resource/spriteFrames/role/Role0001.tres index e262de5..8205354 100644 --- a/DungeonShooting_Godot/resource/spriteFrames/role/Role0001.tres +++ b/DungeonShooting_Godot/resource/spriteFrames/role/Role0001.tres @@ -1,4 +1,4 @@ -[gd_resource type="SpriteFrames" load_steps=15 format=3 uid="uid://n11thtali6es"] +[gd_resource type="SpriteFrames" load_steps=21 format=3 uid="uid://n11thtali6es"] [ext_resource type="Texture2D" uid="uid://ekas4lqprrml" path="res://resource/sprite/role/role0001/idle/Sprite-0002.png" id="1_le6bk"] [ext_resource type="Texture2D" uid="uid://b81k08ofpf2oo" path="res://resource/sprite/role/role0001/idle/Sprite-0003.png" id="2_whsc2"] @@ -14,6 +14,12 @@ [ext_resource type="Texture2D" uid="uid://d32g0f5vk68sj" path="res://resource/sprite/role/role0001/run/Sprite-0004.png" id="12_cbabh"] [ext_resource type="Texture2D" uid="uid://cw83liyy6gnln" path="res://resource/sprite/role/role0001/run/Sprite-0003.png" id="13_u0cmp"] [ext_resource type="Texture2D" uid="uid://b1gh481w2xvsl" path="res://resource/sprite/role/role0001/run/Sprite-0002.png" id="14_nlfq5"] +[ext_resource type="Texture2D" uid="uid://sknj4eflhbvc" path="res://resource/sprite/role/role0001/roll/Sprite-0004.png" id="17_xnddk"] +[ext_resource type="Texture2D" uid="uid://c8ijooj30lvpw" path="res://resource/sprite/role/role0001/roll/Sprite-0005.png" id="18_1doii"] +[ext_resource type="Texture2D" uid="uid://blqx76rvx6c34" path="res://resource/sprite/role/role0001/roll/Sprite-0006.png" id="19_ilt25"] +[ext_resource type="Texture2D" uid="uid://48qebkjqggub" path="res://resource/sprite/role/role0001/roll/Sprite-0007.png" id="20_tp03g"] +[ext_resource type="Texture2D" uid="uid://dvrxriqd6dk1d" path="res://resource/sprite/role/role0001/roll/Sprite-0008.png" id="21_oocqa"] +[ext_resource type="Texture2D" uid="uid://ceqi6d4vhbpt" path="res://resource/sprite/role/role0001/roll/Sprite-0009.png" id="22_yc5ek"] [resource] animations = [{ @@ -53,9 +59,6 @@ }, { "frames": [{ "duration": 1.0, -"texture": ExtResource("8_scwvl") -}, { -"duration": 1.0, "texture": ExtResource("9_yjs5f") }, { "duration": 1.0, @@ -72,6 +75,9 @@ }, { "duration": 1.0, "texture": ExtResource("14_nlfq5") +}, { +"duration": 1.0, +"texture": ExtResource("8_scwvl") }], "loop": true, "name": &"reverseRun", @@ -79,6 +85,29 @@ }, { "frames": [{ "duration": 1.0, +"texture": ExtResource("17_xnddk") +}, { +"duration": 1.0, +"texture": ExtResource("18_1doii") +}, { +"duration": 1.0, +"texture": ExtResource("19_ilt25") +}, { +"duration": 1.0, +"texture": ExtResource("20_tp03g") +}, { +"duration": 1.0, +"texture": ExtResource("21_oocqa") +}, { +"duration": 1.0, +"texture": ExtResource("22_yc5ek") +}], +"loop": false, +"name": &"roll", +"speed": 15.0 +}, { +"frames": [{ +"duration": 1.0, "texture": ExtResource("14_nlfq5") }, { "duration": 1.0, diff --git a/DungeonShooting_Godot/resource/spriteFrames/role/Role1001.tres b/DungeonShooting_Godot/resource/spriteFrames/role/Role1001.tres index dd4a35a..600ba06 100644 --- a/DungeonShooting_Godot/resource/spriteFrames/role/Role1001.tres +++ b/DungeonShooting_Godot/resource/spriteFrames/role/Role1001.tres @@ -1,6 +1,6 @@ [gd_resource type="SpriteFrames" load_steps=15 format=3 uid="uid://cnctpyrn02rhd"] -[ext_resource type="Texture2D" path="res://resource/sprite/role/enemy0001/enemy0001.png" id="1_xi6qw"] +[ext_resource type="Texture2D" uid="uid://ddhkhfaos2w1g" path="res://resource/sprite/role/enemy0001/enemy0001.png" id="1_xi6qw"] [sub_resource type="AtlasTexture" id="AtlasTexture_jttte"] atlas = ExtResource("1_xi6qw") diff --git a/DungeonShooting_Godot/src/framework/activity/Component.cs b/DungeonShooting_Godot/src/framework/activity/Component.cs index f96b8dd..ec1897d 100644 --- a/DungeonShooting_Godot/src/framework/activity/Component.cs +++ b/DungeonShooting_Godot/src/framework/activity/Component.cs @@ -1,10 +1,11 @@ +using System.Collections; using Godot; /// /// 组件基类, 用于挂载到游戏物体上, 相比于原生 Node 更加轻量化, 实例化 Component 不会创建额外的 Node, 可以大量添加组件 /// -public abstract class Component : IProcess, IDestroy +public abstract class Component : IProcess, IDestroy, ICoroutine { /// /// 当前组件所挂载的游戏对象 @@ -212,4 +213,24 @@ ActivityInstance.RemoveComponent(this); OnDestroy(); } + + public long StartCoroutine(IEnumerator able) + { + return ActivityInstance.StartCoroutine(able); + } + + public void StopCoroutine(long coroutineId) + { + ActivityInstance.StopCoroutine(coroutineId); + } + + public bool IsCoroutineOver(long coroutineId) + { + return ActivityInstance.IsCoroutineOver(coroutineId); + } + + public void StopAllCoroutine() + { + ActivityInstance.StopAllCoroutine(); + } } \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/activity/bullet/Bullet.cs b/DungeonShooting_Godot/src/game/activity/bullet/Bullet.cs index 743708a..124220e 100644 --- a/DungeonShooting_Godot/src/game/activity/bullet/Bullet.cs +++ b/DungeonShooting_Godot/src/game/activity/bullet/Bullet.cs @@ -74,11 +74,11 @@ BasisVelocity = new Vector2(FlySpeed, 0).Rotated(Rotation); //如果子弹会对玩家造成伤害, 则显示红色描边 - if (Player.Current.CollisionWithMask(targetLayer)) - { - ShowOutline = true; - OutlineColor = new Color(1, 0, 0, 0.9f); - } + // if (Player.Current.CollisionWithMask(targetLayer)) + // { + // ShowOutline = true; + // OutlineColor = new Color(1, 0, 0, 0.9f); + // } } protected override void PhysicsProcessOver(float delta) diff --git a/DungeonShooting_Godot/src/game/activity/role/Player.cs b/DungeonShooting_Godot/src/game/activity/role/Player.cs deleted file mode 100644 index a4f3640..0000000 --- a/DungeonShooting_Godot/src/game/activity/role/Player.cs +++ /dev/null @@ -1,287 +0,0 @@ -using Godot; - - -/// -/// 玩家角色基类, 所有角色都必须继承该类 -/// -[Tool] -public partial class Player : Role -{ - /// - /// 获取当前操作的角色 - /// - public static Player Current { get; private set; } - - /// - /// 设置当前操作的玩家对象 - /// - public static void SetCurrentPlayer(Player player) - { - Current = player; - //设置相机和鼠标跟随玩家 - GameCamera.Main.SetFollowTarget(player); - GameApplication.Instance.Cursor.SetMountRole(player); - } - - public override void OnInit() - { - base.OnInit(); - - AttackLayer = PhysicsLayer.Wall | PhysicsLayer.Prop | PhysicsLayer.Enemy; - Camp = CampEnum.Camp1; - - MaxHp = 6; - Hp = 6; - MaxShield = 0; - Shield = 0; - - // debug用 - // RoleState.Acceleration = 3000; - // RoleState.Friction = 3000; - // RoleState.MoveSpeed = 500; - // CollisionLayer = 0; - // CollisionMask = 0; - // GameCamera.Main.Zoom = new Vector2(0.2f, 0.2f); - // //GameCamera.Main.Zoom = new Vector2(0.5f, 0.5f); - } - - protected override void Process(float delta) - { - if (IsDie) - { - return; - } - base.Process(delta); - //脸的朝向 - if (LookTarget == null) - { - var gPos = GlobalPosition; - Vector2 mousePos = InputManager.CursorPosition; - if (mousePos.X > gPos.X && Face == FaceDirection.Left) - { - Face = FaceDirection.Right; - } - else if (mousePos.X < gPos.X && Face == FaceDirection.Right) - { - Face = FaceDirection.Left; - } - //枪口跟随鼠标 - MountPoint.SetLookAt(mousePos); - } - - if (InputManager.ExchangeWeapon) //切换武器 - { - ExchangeNextWeapon(); - } - else if (InputManager.ThrowWeapon) //扔掉武器 - { - ThrowWeapon(); - - // //测试用的, 所有敌人也扔掉武器 - // if (Affiliation != null) - // { - // var enemies = Affiliation.FindIncludeItems(o => - // { - // return o.CollisionWithMask(PhysicsLayer.Enemy); - // }); - // foreach (var activityObject in enemies) - // { - // if (activityObject is Enemy enemy) - // { - // enemy.ThrowWeapon(); - // } - // } - // } - } - else if (InputManager.Interactive) //互动物体 - { - TriggerInteractive(); - } - else if (InputManager.Reload) //换弹 - { - Reload(); - } - - if (InputManager.Fire) //开火 - { - Attack(); - // var weaponArray = AffiliationArea.FindEnterItems(o => o is Weapon); - // foreach (Weapon activityObject in weaponArray) - // { - // activityObject.Trigger(this); - // } - } - - if (InputManager.UseActiveProp) //使用道具 - { - UseActiveProp(); - } - else if (InputManager.RemoveProp) //扔掉道具 - { - ThrowActiveProp(); - } - - if (Input.IsKeyPressed(Key.P)) - { - //Hurt(1000, 0); - Hp = 0; - Hurt(1000, 0); - } - } - - protected override void PhysicsProcess(float delta) - { - if (IsDie) - { - return; - } - - base.PhysicsProcess(delta); - HandleMoveInput(delta); - //播放动画 - PlayAnim(); - } - - protected override void OnPickUpWeapon(Weapon weapon) - { - EventManager.EmitEvent(EventEnum.OnPlayerPickUpWeapon, weapon); - } - - protected override void OnThrowWeapon(Weapon weapon) - { - EventManager.EmitEvent(EventEnum.OnPlayerRemoveWeapon, weapon); - } - - protected override int OnHandlerHurt(int damage) - { - //修改受到的伤害, 每次只受到1点伤害 - return 1; - } - - protected override void OnHit(int damage, bool realHarm) - { - //进入无敌状态 - if (realHarm) //真实伤害 - { - PlayInvincibleFlashing(RoleState.WoundedInvincibleTime); - } - else //护盾抵消掉的 - { - PlayInvincibleFlashing(RoleState.ShieldInvincibleTime); - } - } - - protected override void OnChangeHp(int hp) - { - //GameApplication.Instance.Ui.SetHp(hp); - EventManager.EmitEvent(EventEnum.OnPlayerHpChange, hp); - } - - protected override void OnChangeMaxHp(int maxHp) - { - //GameApplication.Instance.Ui.SetMaxHp(maxHp); - EventManager.EmitEvent(EventEnum.OnPlayerMaxHpChange, maxHp); - } - - protected override void ChangeInteractiveItem(CheckInteractiveResult prev, CheckInteractiveResult result) - { - if (prev != null && prev.Target.ShowOutline) - { - prev.Target.OutlineColor = Colors.Black; - } - if (result != null && result.Target.ShowOutline) - { - result.Target.OutlineColor = Colors.White; - } - //派发互动对象改变事件 - EventManager.EmitEvent(EventEnum.OnPlayerChangeInteractiveItem, result); - } - - protected override void OnChangeShield(int shield) - { - //GameApplication.Instance.Ui.SetShield(shield); - EventManager.EmitEvent(EventEnum.OnPlayerShieldChange, shield); - } - - protected override void OnChangeMaxShield(int maxShield) - { - //GameApplication.Instance.Ui.SetMaxShield(maxShield); - EventManager.EmitEvent(EventEnum.OnPlayerMaxShieldChange, maxShield); - } - - protected override void OnDie() - { - GameCamera.Main.SetFollowTarget(null); - BasisVelocity = Vector2.Zero; - MoveController.ClearForce(); - UiManager.Open_Settlement(); - } - - protected override void OnPickUpActiveProp(ActiveProp activeProp) - { - EventManager.EmitEvent(EventEnum.OnPlayerPickUpProp, activeProp); - } - - protected override void OnRemoveActiveProp(ActiveProp activeProp) - { - EventManager.EmitEvent(EventEnum.OnPlayerRemoveProp, activeProp); - } - - protected override void OnPickUpBuffProp(BuffProp buffProp) - { - EventManager.EmitEvent(EventEnum.OnPlayerPickUpProp, buffProp); - } - - protected override void OnRemoveBuffProp(BuffProp buffProp) - { - EventManager.EmitEvent(EventEnum.OnPlayerRemoveProp, buffProp); - } - - //处理角色移动的输入 - private void HandleMoveInput(float delta) - { - //角色移动 - Vector2 dir = InputManager.MoveAxis; - // 移动. 如果移动的数值接近0(是用 摇杆可能出现 方向 可能会出现浮点),就friction的值 插值 到 0 - // 如果 有输入 就以当前速度,用acceleration 插值到 对应方向 * 最大速度 - if (Mathf.IsZeroApprox(dir.X)) - { - BasisVelocity = new Vector2(Mathf.MoveToward(BasisVelocity.X, 0, RoleState.Friction * delta), BasisVelocity.Y); - } - else - { - BasisVelocity = new Vector2(Mathf.MoveToward(BasisVelocity.X, dir.X * RoleState.MoveSpeed, RoleState.Acceleration * delta), - BasisVelocity.Y); - } - - if (Mathf.IsZeroApprox(dir.Y)) - { - BasisVelocity = new Vector2(BasisVelocity.X, Mathf.MoveToward(BasisVelocity.Y, 0, RoleState.Friction * delta)); - } - else - { - BasisVelocity = new Vector2(BasisVelocity.X, - Mathf.MoveToward(BasisVelocity.Y, dir.Y * RoleState.MoveSpeed, RoleState.Acceleration * delta)); - } - } - - // 播放动画 - private void PlayAnim() - { - if (BasisVelocity != Vector2.Zero) - { - if ((Face == FaceDirection.Right && BasisVelocity.X >= 0) || Face == FaceDirection.Left && BasisVelocity.X <= 0) //向前走 - { - AnimatedSprite.Play(AnimatorNames.Run); - } - else if ((Face == FaceDirection.Right && BasisVelocity.X < 0) || Face == FaceDirection.Left && BasisVelocity.X > 0) //向后走 - { - AnimatedSprite.Play(AnimatorNames.ReverseRun); - } - } - else - { - AnimatedSprite.Play(AnimatorNames.Idle); - } - } -} \ 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 1221d33..f910803 100644 --- a/DungeonShooting_Godot/src/game/activity/role/Role.cs +++ b/DungeonShooting_Godot/src/game/activity/role/Role.cs @@ -27,6 +27,12 @@ /// [Export, ExportFillNode] public Area2D HurtArea { get; set; } + + /// + /// 伤害区域碰撞器 + /// + [Export, ExportFillNode] + public CollisionShape2D HurtCollision { get; set; } /// /// 所属阵营 @@ -71,6 +77,12 @@ public Area2D InteractiveArea { get; set; } /// + /// 互动区域碰撞器 + /// + [Export, ExportFillNode] + public CollisionShape2D InteractiveCollision { get; set; } + + /// /// 脸的朝向 /// public FaceDirection Face { get => _face; set => SetFace(value); } diff --git a/DungeonShooting_Godot/src/game/activity/role/RoleState.cs b/DungeonShooting_Godot/src/game/activity/role/RoleState.cs index 0585f25..835d741 100644 --- a/DungeonShooting_Godot/src/game/activity/role/RoleState.cs +++ b/DungeonShooting_Godot/src/game/activity/role/RoleState.cs @@ -15,6 +15,11 @@ /// 移动加速度 /// public float Acceleration = 1500f; + + /// + /// 翻滚速度 + /// + public float RollSpeed = 180f; /// /// 移动摩擦力 diff --git a/DungeonShooting_Godot/src/game/activity/role/player/Player.cs b/DungeonShooting_Godot/src/game/activity/role/player/Player.cs new file mode 100644 index 0000000..89e806c --- /dev/null +++ b/DungeonShooting_Godot/src/game/activity/role/player/Player.cs @@ -0,0 +1,290 @@ +using Godot; + + +/// +/// 玩家角色基类, 所有角色都必须继承该类 +/// +[Tool] +public partial class Player : Role +{ + /// + /// 获取当前操作的角色 + /// + public static Player Current { get; private set; } + + /// + /// 玩家身上的状态机控制器 + /// + public StateController StateController { get; private set; } + + /// + /// 是否翻滚中 + /// + public bool IsRolling { get; private set; } + + /// + /// 设置当前操作的玩家对象 + /// + public static void SetCurrentPlayer(Player player) + { + Current = player; + //设置相机和鼠标跟随玩家 + GameCamera.Main.SetFollowTarget(player); + GameApplication.Instance.Cursor.SetMountRole(player); + } + + public override void OnInit() + { + base.OnInit(); + + IsAi = false; + StateController = AddComponent>(); + AttackLayer = PhysicsLayer.Wall | PhysicsLayer.Prop | PhysicsLayer.Enemy; + Camp = CampEnum.Camp1; + + MaxHp = 6; + Hp = 6; + MaxShield = 0; + Shield = 0; + + // debug用 + // RoleState.Acceleration = 3000; + // RoleState.Friction = 3000; + // RoleState.MoveSpeed = 500; + // CollisionLayer = 0; + // CollisionMask = 0; + // GameCamera.Main.Zoom = new Vector2(0.2f, 0.2f); + // //GameCamera.Main.Zoom = new Vector2(0.5f, 0.5f); + + //注册状态机 + StateController.Register(new PlayerIdleState()); + StateController.Register(new PlayerMoveState()); + StateController.Register(new PlayerRollState()); + //默认状态 + StateController.ChangeStateInstant(PlayerStateEnum.Idle); + } + + protected override void Process(float delta) + { + if (IsDie) + { + return; + } + base.Process(delta); + //脸的朝向 + if (LookTarget == null) + { + var gPos = GlobalPosition; + Vector2 mousePos = InputManager.CursorPosition; + if (mousePos.X > gPos.X && Face == FaceDirection.Left) + { + Face = FaceDirection.Right; + } + else if (mousePos.X < gPos.X && Face == FaceDirection.Right) + { + Face = FaceDirection.Left; + } + //枪口跟随鼠标 + MountPoint.SetLookAt(mousePos); + } + + if (InputManager.ExchangeWeapon) //切换武器 + { + ExchangeNextWeapon(); + } + else if (InputManager.ThrowWeapon) //扔掉武器 + { + ThrowWeapon(); + + // //测试用的, 所有敌人也扔掉武器 + // if (Affiliation != null) + // { + // var enemies = Affiliation.FindIncludeItems(o => + // { + // return o.CollisionWithMask(PhysicsLayer.Enemy); + // }); + // foreach (var activityObject in enemies) + // { + // if (activityObject is Enemy enemy) + // { + // enemy.ThrowWeapon(); + // } + // } + // } + } + else if (InputManager.Interactive) //互动物体 + { + TriggerInteractive(); + } + else if (InputManager.Reload) //换弹 + { + Reload(); + } + + if (InputManager.Fire) //开火 + { + if (StateController.CurrState != PlayerStateEnum.Roll) //不能是翻滚状态 + { + Attack(); + // var weaponArray = AffiliationArea.FindEnterItems(o => o is Weapon); + // foreach (Weapon activityObject in weaponArray) + // { + // activityObject.Trigger(this); + // } + } + } + + if (InputManager.UseActiveProp) //使用道具 + { + UseActiveProp(); + } + else if (InputManager.RemoveProp) //扔掉道具 + { + ThrowActiveProp(); + } + + if (Input.IsKeyPressed(Key.P)) //测试用, 自杀 + { + //Hurt(1000, 0); + Hp = 0; + Hurt(1000, 0); + } + } + + // protected override void PhysicsProcess(float delta) + // { + // if (IsDie) + // { + // return; + // } + // + // base.PhysicsProcess(delta); + // //处理移动 + // HandleMoveInput(delta); + // //播放动画 + // PlayAnim(); + // } + + protected override void OnPickUpWeapon(Weapon weapon) + { + EventManager.EmitEvent(EventEnum.OnPlayerPickUpWeapon, weapon); + } + + protected override void OnThrowWeapon(Weapon weapon) + { + EventManager.EmitEvent(EventEnum.OnPlayerRemoveWeapon, weapon); + } + + protected override int OnHandlerHurt(int damage) + { + //修改受到的伤害, 每次只受到1点伤害 + return 1; + } + + protected override void OnHit(int damage, bool realHarm) + { + //进入无敌状态 + if (realHarm) //真实伤害 + { + PlayInvincibleFlashing(RoleState.WoundedInvincibleTime); + } + else //护盾抵消掉的 + { + PlayInvincibleFlashing(RoleState.ShieldInvincibleTime); + } + } + + protected override void OnChangeHp(int hp) + { + //GameApplication.Instance.Ui.SetHp(hp); + EventManager.EmitEvent(EventEnum.OnPlayerHpChange, hp); + } + + protected override void OnChangeMaxHp(int maxHp) + { + //GameApplication.Instance.Ui.SetMaxHp(maxHp); + EventManager.EmitEvent(EventEnum.OnPlayerMaxHpChange, maxHp); + } + + protected override void ChangeInteractiveItem(CheckInteractiveResult prev, CheckInteractiveResult result) + { + if (prev != null && prev.Target.ShowOutline) + { + prev.Target.OutlineColor = Colors.Black; + } + if (result != null && result.Target.ShowOutline) + { + result.Target.OutlineColor = Colors.White; + } + //派发互动对象改变事件 + EventManager.EmitEvent(EventEnum.OnPlayerChangeInteractiveItem, result); + } + + protected override void OnChangeShield(int shield) + { + //GameApplication.Instance.Ui.SetShield(shield); + EventManager.EmitEvent(EventEnum.OnPlayerShieldChange, shield); + } + + protected override void OnChangeMaxShield(int maxShield) + { + //GameApplication.Instance.Ui.SetMaxShield(maxShield); + EventManager.EmitEvent(EventEnum.OnPlayerMaxShieldChange, maxShield); + } + + protected override void OnDie() + { + StateController.Enable = false; + GameCamera.Main.SetFollowTarget(null); + BasisVelocity = Vector2.Zero; + MoveController.ClearForce(); + UiManager.Open_Settlement(); + } + + protected override void OnPickUpActiveProp(ActiveProp activeProp) + { + EventManager.EmitEvent(EventEnum.OnPlayerPickUpProp, activeProp); + } + + protected override void OnRemoveActiveProp(ActiveProp activeProp) + { + EventManager.EmitEvent(EventEnum.OnPlayerRemoveProp, activeProp); + } + + protected override void OnPickUpBuffProp(BuffProp buffProp) + { + EventManager.EmitEvent(EventEnum.OnPlayerPickUpProp, buffProp); + } + + protected override void OnRemoveBuffProp(BuffProp buffProp) + { + EventManager.EmitEvent(EventEnum.OnPlayerRemoveProp, buffProp); + } + + /// + /// 处理角色移动的输入 + /// + public void HandleMoveInput(float delta) + { + var dir = InputManager.MoveAxis; + // 移动. 如果移动的数值接近0(是用 摇杆可能出现 方向 可能会出现浮点),就friction的值 插值 到 0 + // 如果 有输入 就以当前速度,用acceleration 插值到 对应方向 * 最大速度 + if (Mathf.IsZeroApprox(dir.X)) + { + BasisVelocity = new Vector2(Mathf.MoveToward(BasisVelocity.X, 0, RoleState.Friction * delta), BasisVelocity.Y); + } + else + { + BasisVelocity = new Vector2(Mathf.MoveToward(BasisVelocity.X, dir.X * RoleState.MoveSpeed, RoleState.Acceleration * delta), BasisVelocity.Y); + } + + if (Mathf.IsZeroApprox(dir.Y)) + { + BasisVelocity = new Vector2(BasisVelocity.X, Mathf.MoveToward(BasisVelocity.Y, 0, RoleState.Friction * delta)); + } + else + { + BasisVelocity = new Vector2(BasisVelocity.X, Mathf.MoveToward(BasisVelocity.Y, dir.Y * RoleState.MoveSpeed, RoleState.Acceleration * delta)); + } + } +} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/activity/role/player/state/PlayerIdleState.cs b/DungeonShooting_Godot/src/game/activity/role/player/state/PlayerIdleState.cs new file mode 100644 index 0000000..fb3c530 --- /dev/null +++ b/DungeonShooting_Godot/src/game/activity/role/player/state/PlayerIdleState.cs @@ -0,0 +1,38 @@ + +using Godot; + +/// +/// 空闲状态 +/// +public class PlayerIdleState : StateBase +{ + public PlayerIdleState() : base(PlayerStateEnum.Idle) + { + } + + public override void Enter(PlayerStateEnum prev, params object[] args) + { + Master.HandleMoveInput((float)Master.GetProcessDeltaTime()); + Master.AnimatedSprite.Play(AnimatorNames.Idle); + } + + public override void Process(float delta) + { + var dir = InputManager.MoveAxis; + if (dir != Vector2.Zero) + { + if (InputManager.Roll) //按下翻滚 + { + ChangeState(PlayerStateEnum.Roll); + } + else //移动 + { + ChangeState(PlayerStateEnum.Move); + } + } + else + { + Master.HandleMoveInput(delta); + } + } +} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/activity/role/player/state/PlayerMoveState.cs b/DungeonShooting_Godot/src/game/activity/role/player/state/PlayerMoveState.cs new file mode 100644 index 0000000..a3953f1 --- /dev/null +++ b/DungeonShooting_Godot/src/game/activity/role/player/state/PlayerMoveState.cs @@ -0,0 +1,51 @@ + +using Godot; + +/// +/// 移动状态 +/// +public class PlayerMoveState : StateBase +{ + public PlayerMoveState() : base(PlayerStateEnum.Move) + { + } + + public override void Enter(PlayerStateEnum prev, params object[] args) + { + Master.HandleMoveInput((float)Master.GetProcessDeltaTime()); + PlayAnim(); + } + + public override void Process(float delta) + { + if (InputManager.MoveAxis == Vector2.Zero) //停止移动 + { + ChangeState(PlayerStateEnum.Idle); + } + else + { + if (InputManager.Roll) //翻滚 + { + ChangeState(PlayerStateEnum.Roll); + } + else //执行移动 + { + Master.HandleMoveInput(delta); + PlayAnim(); + } + } + } + + // 播放动画 + private void PlayAnim() + { + if ((Master.Face == FaceDirection.Right && Master.BasisVelocity.X >= 0) || Master.Face == FaceDirection.Left && Master.BasisVelocity.X <= 0) //向前走 + { + Master.AnimatedSprite.Play(AnimatorNames.Run); + } + else if ((Master.Face == FaceDirection.Right && Master.BasisVelocity.X < 0) || Master.Face == FaceDirection.Left && Master.BasisVelocity.X > 0) //向后走 + { + Master.AnimatedSprite.Play(AnimatorNames.ReverseRun); + } + } +} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/activity/role/player/state/PlayerRollState.cs b/DungeonShooting_Godot/src/game/activity/role/player/state/PlayerRollState.cs new file mode 100644 index 0000000..badde0e --- /dev/null +++ b/DungeonShooting_Godot/src/game/activity/role/player/state/PlayerRollState.cs @@ -0,0 +1,66 @@ + +using System.Collections; +using Godot; + +/// +/// 翻滚状态 +/// +public class PlayerRollState : StateBase +{ + private long _coroutineId = -1; + private Vector2 _moveDir; + + public PlayerRollState() : base(PlayerStateEnum.Roll) + { + } + + public override void Enter(PlayerStateEnum prev, params object[] args) + { + if (_coroutineId >= 0) + { + Master.StopCoroutine(_coroutineId); + } + + _coroutineId = Master.StartCoroutine(RunRoll()); + Master.AnimatedSprite.Play(AnimatorNames.Roll); + + //隐藏武器 + Master.BackMountPoint.Visible = false; + Master.MountPoint.Visible = false; + //禁用伤害碰撞 + Master.HurtCollision.Disabled = true; + + //翻滚移动方向 + _moveDir = InputManager.MoveAxis; + Master.BasisVelocity = _moveDir * Master.RoleState.RollSpeed; + } + + public override void Exit(PlayerStateEnum next) + { + //显示武器 + Master.BackMountPoint.Visible = true; + Master.MountPoint.Visible = true; + //启用伤害碰撞 + Master.HurtCollision.Disabled = false; + } + + public override void Process(float delta) + { + Master.BasisVelocity = _moveDir * Master.RoleState.RollSpeed; + } + + //翻滚逻辑处理 + private IEnumerator RunRoll() + { + yield return Master.AnimatedSprite.ToSignal(Master.AnimatedSprite, AnimatedSprite2D.SignalName.AnimationFinished); + _coroutineId = -1; + if (InputManager.MoveAxis != Vector2.Zero) //切换到移动状态 + { + ChangeState(PlayerStateEnum.Move); + } + else //切换空闲状态 + { + ChangeState(PlayerStateEnum.Idle); + } + } +} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/activity/role/player/state/PlayerStateEnum.cs b/DungeonShooting_Godot/src/game/activity/role/player/state/PlayerStateEnum.cs new file mode 100644 index 0000000..5bbd421 --- /dev/null +++ b/DungeonShooting_Godot/src/game/activity/role/player/state/PlayerStateEnum.cs @@ -0,0 +1,16 @@ + +public enum PlayerStateEnum +{ + /// + /// 待机状态 + /// + Idle, + /// + /// 移动状态 + /// + Move, + /// + /// 翻滚状态 + /// + Roll +} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/manager/InputManager.cs b/DungeonShooting_Godot/src/game/manager/InputManager.cs index 9ebf832..01512d6 100644 --- a/DungeonShooting_Godot/src/game/manager/InputManager.cs +++ b/DungeonShooting_Godot/src/game/manager/InputManager.cs @@ -7,7 +7,7 @@ public static class InputManager { /// - /// 移动方向, 键鼠: 键盘WASD + /// 移动方向, 已经归一化, 键鼠: 键盘WASD /// public static Vector2 MoveAxis { get; private set; }