diff --git a/DungeonShooting_Godot/prefab/role/Role0001.tscn b/DungeonShooting_Godot/prefab/role/Role0001.tscn index 71e4939..11cf968 100644 --- a/DungeonShooting_Godot/prefab/role/Role0001.tscn +++ b/DungeonShooting_Godot/prefab/role/Role0001.tscn @@ -24,7 +24,7 @@ [sub_resource type="AnimationLibrary" id="AnimationLibrary_ka171"] [node name="Role0001" node_paths=PackedStringArray("HurtArea", "HurtCollision", "InteractiveArea", "InteractiveCollision", "TipRoot", "TipSprite", "AnimationPlayer", "MountPoint", "BackMountPoint", "MeleeAttackArea", "MeleeAttackCollision", "ShadowSprite", "AnimatedSprite", "Collision") instance=ExtResource("1_10c2n")] -collision_layer = 8 +collision_layer = 24 script = ExtResource("2_6xwnt") HurtArea = NodePath("HurtArea") HurtCollision = NodePath("HurtArea/HurtCollision") diff --git a/DungeonShooting_Godot/prefab/role/template/RoleTemplate.tscn b/DungeonShooting_Godot/prefab/role/template/RoleTemplate.tscn index 102bf01..ad4f584 100644 --- a/DungeonShooting_Godot/prefab/role/template/RoleTemplate.tscn +++ b/DungeonShooting_Godot/prefab/role/template/RoleTemplate.tscn @@ -46,7 +46,7 @@ shape = SubResource("CircleShape2D_5pj80") [node name="HurtArea" type="Area2D" parent="."] -collision_layer = 0 +collision_layer = 1024 collision_mask = 0 monitoring = false script = ExtResource("2_2eey0") diff --git a/DungeonShooting_Godot/project.godot b/DungeonShooting_Godot/project.godot index 9c42853..1822292 100644 --- a/DungeonShooting_Godot/project.godot +++ b/DungeonShooting_Godot/project.godot @@ -246,13 +246,13 @@ 2d_physics/layer_2="bullet" 2d_physics/layer_3="prop" 2d_physics/layer_4="player" -2d_physics/layer_5="enemy" +2d_physics/layer_5="role" 2d_physics/layer_6="affiliation" 2d_physics/layer_7="onHand" 2d_physics/layer_8="debris" 2d_physics/layer_9="throwing" 2d_physics/layer_10="obstacle" -2d_physics/layer_11="npc" +2d_physics/layer_11="hurtArea" 2d_physics/layer_14="ui_mouse" [mono] diff --git a/DungeonShooting_Godot/src/framework/activity/hurt/HurtArea.cs b/DungeonShooting_Godot/src/framework/activity/hurt/HurtArea.cs index 8631faa..7b8b7a0 100644 --- a/DungeonShooting_Godot/src/framework/activity/hurt/HurtArea.cs +++ b/DungeonShooting_Godot/src/framework/activity/hurt/HurtArea.cs @@ -1,17 +1,19 @@ using Godot; +/// +/// 可被子弹击中的区域 +/// [Tool] public partial class HurtArea : Area2D, IHurt { - public delegate void HurtDelegate(ActivityObject target, int damage, float angle); + /// + /// 所属角色 + /// + public Role Master { get; private set; } - public event HurtDelegate OnHurtEvent; - - public ActivityObject ActivityObject { get; private set; } - - public void InitActivityObject(ActivityObject activityObject) + public void InitRole(Role role) { - ActivityObject = activityObject; + Master = role; } public override void _Ready() @@ -19,11 +21,23 @@ Monitoring = false; } + public bool CanHurt(ActivityObject target) + { + //无敌状态 + if (Master.Invincible) + { + return true; + } + + if (target is Role role) + { + return Master.IsEnemy(role); + } + return true; + } + public void Hurt(ActivityObject target, int damage, float angle) { - if (OnHurtEvent != null) - { - OnHurtEvent(target, damage, angle); - } + Master.CallDeferred(nameof(Master.HurtHandler), target, damage, angle); } } \ No newline at end of file diff --git a/DungeonShooting_Godot/src/framework/activity/hurt/IHurt.cs b/DungeonShooting_Godot/src/framework/activity/hurt/IHurt.cs index fd27abc..3c3686d 100644 --- a/DungeonShooting_Godot/src/framework/activity/hurt/IHurt.cs +++ b/DungeonShooting_Godot/src/framework/activity/hurt/IHurt.cs @@ -4,6 +4,12 @@ public interface IHurt { /// + /// 返回是否可以造成伤害 + /// + /// 触发伤害的对象, 为 null 表示不存在对象或者对象已经被销毁 + bool CanHurt(ActivityObject target); + + /// /// 受到伤害 /// /// 触发伤害的对象, 为 null 表示不存在对象或者对象已经被销毁 diff --git a/DungeonShooting_Godot/src/framework/common/NodeExtend.cs b/DungeonShooting_Godot/src/framework/common/NodeExtend.cs index e04437d..50d1ad9 100644 --- a/DungeonShooting_Godot/src/framework/common/NodeExtend.cs +++ b/DungeonShooting_Godot/src/framework/common/NodeExtend.cs @@ -21,7 +21,7 @@ if (hurt is HurtArea hurtArea) { - return hurtArea.ActivityObject; + return hurtArea.Master; } return null; diff --git a/DungeonShooting_Godot/src/framework/map/AffiliationArea.cs b/DungeonShooting_Godot/src/framework/map/AffiliationArea.cs index 10f775d..3c9123d 100644 --- a/DungeonShooting_Godot/src/framework/map/AffiliationArea.cs +++ b/DungeonShooting_Godot/src/framework/map/AffiliationArea.cs @@ -64,7 +64,7 @@ Monitoring = true; Monitorable = false; CollisionLayer = PhysicsLayer.None; - CollisionMask = PhysicsLayer.Prop | PhysicsLayer.Player | PhysicsLayer.Enemy | PhysicsLayer.Debris | PhysicsLayer.Throwing; + CollisionMask = PhysicsLayer.Prop | PhysicsLayer.Role | PhysicsLayer.Debris | PhysicsLayer.Throwing | PhysicsLayer.Obstacle; BodyEntered += OnBodyEntered; BodyExited += OnBodyExited; diff --git a/DungeonShooting_Godot/src/framework/map/preinstall/RoomPreinstall.cs b/DungeonShooting_Godot/src/framework/map/preinstall/RoomPreinstall.cs index 2a63757..4e398ae 100644 --- a/DungeonShooting_Godot/src/framework/map/preinstall/RoomPreinstall.cs +++ b/DungeonShooting_Godot/src/framework/map/preinstall/RoomPreinstall.cs @@ -317,7 +317,7 @@ foreach (var preloadData in _readyList) { //有敌人 - if (!hasEnemy && preloadData.ActivityObject.CollisionWithMask(PhysicsLayer.Enemy)) + if (!hasEnemy && preloadData.ActivityObject is Role role && role.IsEnemyWithPlayer()) { hasEnemy = true; } @@ -332,7 +332,7 @@ if (!hasEnemy) { hasEnemy = RoomInfo.AffiliationArea.ExistIncludeItem( - activityObject => activityObject.CollisionWithMask(PhysicsLayer.Enemy) + activityObject => activityObject is Role role && role.IsEnemyWithPlayer() ); } diff --git a/DungeonShooting_Godot/src/framework/map/room/RoomInfo.cs b/DungeonShooting_Godot/src/framework/map/room/RoomInfo.cs index 740846d..3459432 100644 --- a/DungeonShooting_Godot/src/framework/map/room/RoomInfo.cs +++ b/DungeonShooting_Godot/src/framework/map/room/RoomInfo.cs @@ -474,7 +474,7 @@ //房间内有敌人, 或者会刷新敌人才会关门 var hasEnemy = false; - if (AffiliationArea.ExistEnterItem(activityObject => activityObject.CollisionWithMask(PhysicsLayer.Enemy))) //先判断房间里面是否有敌人 + if (AffiliationArea.ExistEnterItem(activityObject => activityObject is Role role && role.IsEnemyWithPlayer())) //先判断房间里面是否有敌人 { hasEnemy = true; } diff --git a/DungeonShooting_Godot/src/game/World.cs b/DungeonShooting_Godot/src/game/World.cs deleted file mode 100644 index 34add95..0000000 --- a/DungeonShooting_Godot/src/game/World.cs +++ /dev/null @@ -1,202 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using Godot; - -/// -/// 游戏世界 -/// -public partial class World : CanvasModulate, ICoroutine -{ - /// - /// 当前的游戏世界对象 - /// - public static World Current => GameApplication.Instance.DungeonManager.CurrWorld; - - /// - /// 当前操作的玩家 - /// - public Player Player { get; private set; } - - /// - /// //对象根节点 - /// - public Node2D NormalLayer; - - /// - /// 对象根节点, 带y轴排序功能 - /// - public Node2D YSortLayer; - - /// - /// 地图根节点 - /// - public TileMap TileRoot; - - public Node2D StaticSpriteRoot; - public Node2D AffiliationAreaRoot; - public Node2D FogMaskRoot; - public Node2D NavigationRoot; - - /// - /// 是否暂停 - /// - public bool Pause - { - get => _pause; - set - { - if (_pause != value) - { - _pause = value; - if (value) - { - ProcessMode = ProcessModeEnum.WhenPaused; - } - else - { - ProcessMode = ProcessModeEnum.Inherit; - } - } - } - } - - /// - /// 所有被扔在地上的武器 - /// - public HashSet Weapon_UnclaimedWeapons { get; } = new HashSet(); - - /// - /// 记录所有存活的敌人 - /// - public List Enemy_InstanceList { get; } = new List(); - - /// - /// 随机数对象 - /// - public SeedRandom Random { get; private set; } - - /// - /// 随机对象池 - /// - public RandomPool RandomPool { get; private set; } - - /// - /// 角色死亡事件 - /// - public event Action OnRoleDieEvent; - - private bool _pause = false; - private List _coroutineList; - - public override void _Ready() - { - //TileRoot.YSortEnabled = false; - NormalLayer = GetNode("TileRoot/NormalLayer"); - YSortLayer = GetNode("TileRoot/YSortLayer"); - TileRoot = GetNode("TileRoot"); - StaticSpriteRoot = GetNode("TileRoot/StaticSpriteRoot"); - FogMaskRoot = GetNode("TileRoot/FogMaskRoot"); - NavigationRoot = GetNode("TileRoot/NavigationRoot"); - AffiliationAreaRoot = GetNode("TileRoot/AffiliationAreaRoot"); - } - - public override void _Process(double delta) - { - //协程更新 - ProxyCoroutineHandler.ProxyUpdateCoroutine(ref _coroutineList, (float)delta); - } - - /// - /// 获取指定层级根节点 - /// - public Node2D GetRoomLayer(RoomLayerEnum layerEnum) - { - switch (layerEnum) - { - case RoomLayerEnum.NormalLayer: - return NormalLayer; - case RoomLayerEnum.YSortLayer: - return YSortLayer; - } - - return null; - } - - /// - /// 设置当前操作的玩家对象 - /// - public void SetCurrentPlayer(Player player) - { - Player = player; - //设置相机和鼠标跟随玩家 - GameCamera.Main.SetFollowTarget(player); - GameApplication.Instance.Cursor.SetMountRole(player); - } - - /// - /// 通知其他敌人发现目标了 - /// - /// 发送通知的角色 - /// 目标 - public void NotifyEnemyTarget(Role self, ActivityObject target) - { - foreach (var role in Enemy_InstanceList) - { - if (role != self && !role.IsDestroyed && role.AffiliationArea == self.AffiliationArea) - { - //将未发现目标的敌人状态置为惊讶状态 - var controller = role.StateController; - //延时通知效果 - role.CallDelay(Utils.Random.RandomRangeFloat(0.2f, 1f), () => - { - if (controller.CurrState == AIStateEnum.AiNormal) - { - controller.ChangeState(AIStateEnum.AiLeaveFor, target); - } - }); - } - } - } - - public long StartCoroutine(IEnumerator able) - { - return ProxyCoroutineHandler.ProxyStartCoroutine(ref _coroutineList, able); - } - - public void StopCoroutine(long coroutineId) - { - ProxyCoroutineHandler.ProxyStopCoroutine(ref _coroutineList, coroutineId); - } - - public bool IsCoroutineOver(long coroutineId) - { - return ProxyCoroutineHandler.ProxyIsCoroutineOver(ref _coroutineList, coroutineId); - } - - public void StopAllCoroutine() - { - ProxyCoroutineHandler.ProxyStopAllCoroutine(ref _coroutineList); - } - - /// - /// 初始化随机池 - /// - public void InitRandomPool(SeedRandom random) - { - Random = random; - RandomPool = new RandomPool(this); - } - - /// - /// 角色死亡 - /// - public void OnRoleDie(Role role) - { - if (OnRoleDieEvent != null) - { - OnRoleDieEvent(role); - } - } -} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/activity/bullet/explode/Explode.cs b/DungeonShooting_Godot/src/game/activity/bullet/explode/Explode.cs index 17edff3..34cfd7f 100644 --- a/DungeonShooting_Godot/src/game/activity/bullet/explode/Explode.cs +++ b/DungeonShooting_Godot/src/game/activity/bullet/explode/Explode.cs @@ -164,7 +164,11 @@ if (len <= _hitRadius) //在伤害半径内 { - hurt.Hurt(BulletData.TriggerRole.IsDestroyed ? null : BulletData.TriggerRole, _harm, angle); + var target = BulletData.TriggerRole.IsDestroyed ? null : BulletData.TriggerRole; + if (hurt.CanHurt(target)) + { + hurt.Hurt(target, _harm, angle); + } } if (len <= _repelledRadius) //击退半径内 diff --git a/DungeonShooting_Godot/src/game/activity/bullet/laser/Laser.cs b/DungeonShooting_Godot/src/game/activity/bullet/laser/Laser.cs index ebfb3f2..70e2787 100644 --- a/DungeonShooting_Godot/src/game/activity/bullet/laser/Laser.cs +++ b/DungeonShooting_Godot/src/game/activity/bullet/laser/Laser.cs @@ -224,7 +224,11 @@ } //造成伤害 - hurt.Hurt(BulletData.TriggerRole.IsDestroyed ? null : BulletData.TriggerRole, BulletData.Harm, Rotation); + var target = BulletData.TriggerRole.IsDestroyed ? null : BulletData.TriggerRole; + if (hurt.CanHurt(target)) + { + hurt.Hurt(target, BulletData.Harm, Rotation); + } } public long StartCoroutine(IEnumerator able) diff --git a/DungeonShooting_Godot/src/game/activity/bullet/normal/Bullet.cs b/DungeonShooting_Godot/src/game/activity/bullet/normal/Bullet.cs index 5ce3d20..9b95710 100644 --- a/DungeonShooting_Godot/src/game/activity/bullet/normal/Bullet.cs +++ b/DungeonShooting_Godot/src/game/activity/bullet/normal/Bullet.cs @@ -204,7 +204,11 @@ } //造成伤害 - hurt.Hurt(BulletData.TriggerRole.IsDestroyed ? null : BulletData.TriggerRole, BulletData.Harm, Rotation); + var target = BulletData.TriggerRole.IsDestroyed ? null : BulletData.TriggerRole; + if (hurt.CanHurt(target)) + { + hurt.Hurt(target, BulletData.Harm, Rotation); + } //穿透次数 CurrentPenetration++; diff --git a/DungeonShooting_Godot/src/game/activity/item/ObstacleObject.cs b/DungeonShooting_Godot/src/game/activity/item/ObstacleObject.cs index 46ed568..f9d0d16 100644 --- a/DungeonShooting_Godot/src/game/activity/item/ObstacleObject.cs +++ b/DungeonShooting_Godot/src/game/activity/item/ObstacleObject.cs @@ -7,6 +7,11 @@ [Tool] public partial class ObstacleObject : ActivityObject, IHurt { + public virtual bool CanHurt(ActivityObject target) + { + return true; + } + public virtual void Hurt(ActivityObject target, int damage, float angle) { } diff --git a/DungeonShooting_Godot/src/game/activity/role/CampEnum.cs b/DungeonShooting_Godot/src/game/activity/role/CampEnum.cs index 6954070..6ba2bb7 100644 --- a/DungeonShooting_Godot/src/game/activity/role/CampEnum.cs +++ b/DungeonShooting_Godot/src/game/activity/role/CampEnum.cs @@ -1,10 +1,28 @@ public enum CampEnum { - // 阵营1, 玩家 + /// + /// 无阵营, 所有角色都视为敌人 + /// + None, + /// + /// 和平阵营, 不会被攻击 + /// + Peace, + /// + /// 阵营1, 玩家 + /// Camp1, - // 阵营2, 敌人 + /// + /// 阵营2, 敌人 + /// Camp2, - // 阵营3, 中立单位 - Camp3 + /// + /// 阵营3, 敌人2 + /// + Camp3, + /// + /// 阵营4, 敌人3 + /// + Camp4, } \ 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 850cba3..01ff94c 100644 --- a/DungeonShooting_Godot/src/game/activity/role/Role.cs +++ b/DungeonShooting_Godot/src/game/activity/role/Role.cs @@ -11,6 +11,11 @@ public abstract partial class Role : ActivityObject { /// + /// 攻击目标的碰撞器所属层级, 数据源自于: + /// + public const uint AttackLayer = PhysicsLayer.Wall | PhysicsLayer.Obstacle | PhysicsLayer.HurtArea; + + /// /// 当前角色对其他角色造成伤害时对回调 /// 参数1为目标角色 /// 参数2为造成对伤害值 @@ -28,11 +33,6 @@ public RoleState RoleState { get; private set; } /// - /// 默认攻击对象层级 - /// - public const uint DefaultAttackLayer = PhysicsLayer.Player | PhysicsLayer.Enemy | PhysicsLayer.Obstacle; - - /// /// 伤害区域 /// [Export, ExportFillNode] @@ -47,17 +47,7 @@ /// /// 所属阵营 /// - public CampEnum Camp; - - /// - /// 攻击目标的碰撞器所属层级, 数据源自于: - /// - public uint AttackLayer { get; set; } = PhysicsLayer.Wall | PhysicsLayer.Obstacle; - - /// - /// 该角色敌对目标的碰撞器所属层级, 数据源自于: - /// - public uint EnemyLayer { get; set; } = PhysicsLayer.Enemy; + public CampEnum Camp { get; set; } /// /// 携带的被动道具列表 @@ -282,20 +272,11 @@ { if (value) //无敌状态 { - if (HurtArea != null) - { - HurtArea.CollisionLayer = _currentLayer; - } - _flashingInvincibleTimer = -1; _flashingInvincibleFlag = false; } else //正常状态 { - if (HurtArea != null) - { - HurtArea.CollisionLayer = _currentLayer; - } SetBlendModulate(new Color(1, 1, 1, 1)); } } @@ -335,7 +316,6 @@ private Vector2 _startScale; //当前可互动的物体 private CheckInteractiveResult _currentResultData; - private uint _currentLayer; //闪烁计时器 private float _flashingInvincibleTimer = -1; //闪烁状态 @@ -479,15 +459,7 @@ _startScale = Scale; - HurtArea.InitActivityObject(this); - HurtArea.CollisionLayer = CollisionLayer; - HurtArea.CollisionMask = PhysicsLayer.None; - _currentLayer = HurtArea.CollisionLayer; - //CollisionLayer = PhysicsLayer.None; - HurtArea.OnHurtEvent += (target, damage, angle) => - { - CallDeferred(nameof(HurtHandler), target, damage, angle); - }; + HurtArea.InitRole(this); Face = FaceDirection.Right; @@ -857,7 +829,7 @@ /// 触发伤害的对象, 为 null 表示不存在对象或者对象已经被销毁 /// 伤害的量 /// 伤害角度(弧度制) - protected virtual void HurtHandler(ActivityObject target, int damage, float angle) + public virtual void HurtHandler(ActivityObject target, int damage, float angle) { //受伤闪烁, 无敌状态 if (Invincible) @@ -1016,6 +988,20 @@ return this == World.Player; } + + /// + /// 返回指定角色是否是敌人 + /// + public bool IsEnemy(Role other) + { + if (other.Camp == Camp || other.Camp == CampEnum.Peace || Camp == CampEnum.Peace) + { + return false; + } + + return true; + } + /// /// 是否是玩家的敌人 /// @@ -1025,7 +1011,7 @@ { return false; } - return CollisionWithMask(World.Player.EnemyLayer); + return IsEnemy(World.Player); } /// @@ -1437,8 +1423,11 @@ var v2 = position.Normalized() * repel; o.AddRepelForce(v2); } - - hurt.Hurt(this, damage, (pos - GlobalPosition).Angle()); + + if (hurt.CanHurt(this)) + { + hurt.Hurt(this, damage, (pos - GlobalPosition).Angle()); + } } protected override void OnDestroy() diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/Enemy.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/Enemy.cs index 14c0bc5..998ecfd 100644 --- a/DungeonShooting_Godot/src/game/activity/role/enemy/Enemy.cs +++ b/DungeonShooting_Godot/src/game/activity/role/enemy/Enemy.cs @@ -63,9 +63,6 @@ public override void OnInit() { base.OnInit(); - - AttackLayer = PhysicsLayer.Obstacle | PhysicsLayer.Player; - EnemyLayer = PhysicsLayer.Player; Camp = CampEnum.Camp2; RoleState.MoveSpeed = 20; diff --git a/DungeonShooting_Godot/src/game/activity/role/player/Player.cs b/DungeonShooting_Godot/src/game/activity/role/player/Player.cs index 342d205..33e39ca 100644 --- a/DungeonShooting_Godot/src/game/activity/role/player/Player.cs +++ b/DungeonShooting_Godot/src/game/activity/role/player/Player.cs @@ -37,8 +37,6 @@ IsAi = false; StateController = AddComponent>(); - AttackLayer = PhysicsLayer.Obstacle | PhysicsLayer.Enemy; - EnemyLayer = EnemyLayer = PhysicsLayer.Enemy; Camp = CampEnum.Camp1; MaxHp = 6; @@ -223,10 +221,14 @@ } else if (Input.IsKeyPressed(Key.O)) //测试用, 消灭房间内所有敌人 { - var enemyList = AffiliationArea.FindIncludeItems(o => o.CollisionWithMask(PhysicsLayer.Enemy)); + var enemyList = AffiliationArea.FindIncludeItems(o => o is Role role && role.IsEnemyWithPlayer()); foreach (var enemy in enemyList) { - ((Enemy)enemy).HurtArea.Hurt(this, 1000, 0); + var hurt = ((Enemy)enemy).HurtArea; + if (hurt.CanHurt(this)) + { + hurt.Hurt(this, 1000, 0); + } } } // //测试用 diff --git a/DungeonShooting_Godot/src/game/activity/weapon/Weapon.cs b/DungeonShooting_Godot/src/game/activity/weapon/Weapon.cs index edb144a..065bced 100644 --- a/DungeonShooting_Godot/src/game/activity/weapon/Weapon.cs +++ b/DungeonShooting_Godot/src/game/activity/weapon/Weapon.cs @@ -28,9 +28,9 @@ private ExcelConfig.WeaponBase _aiWeaponAttribute; /// - /// 武器攻击的目标阵营 + /// 攻击目标层级 /// - public CampEnum TargetCamp { get; set; } + public uint AttackLayer => Role.AttackLayer; public Role Master { get; set; } @@ -150,11 +150,6 @@ public Role TriggerRole { get; private set; } /// - /// 上一次触发改武器开火的触发开火攻击的层级, 数据源自于: - /// - public long TriggerRoleAttackLayer { get; private set; } - - /// /// 武器当前射速 /// public float CurrentFiringSpeed { get; private set; } @@ -850,13 +845,11 @@ if (triggerRole != null) { TriggerRole = triggerRole; - TriggerRoleAttackLayer = triggerRole.AttackLayer; SetCurrentWeaponAttribute(triggerRole.IsAi ? _aiWeaponAttribute : _playerWeaponAttribute); } else if (Master != null) { TriggerRole = Master; - TriggerRoleAttackLayer = Master.AttackLayer; SetCurrentWeaponAttribute(Master.IsAi ? _aiWeaponAttribute : _playerWeaponAttribute); } @@ -1276,19 +1269,6 @@ } /// - /// 获取武器攻击的目标层级 - /// - /// - public uint GetAttackLayer() - { - if (TriggerRoleAttackLayer > 0) - { - return (uint)TriggerRoleAttackLayer; - } - return Master != null ? Master.AttackLayer : Role.DefaultAttackLayer; - } - - /// /// 返回弹药是否到达上限 /// public bool IsAmmoFull() diff --git a/DungeonShooting_Godot/src/game/activity/weapon/knife/Knife.cs b/DungeonShooting_Godot/src/game/activity/weapon/knife/Knife.cs index 11c2d30..11f51c7 100644 --- a/DungeonShooting_Godot/src/game/activity/weapon/knife/Knife.cs +++ b/DungeonShooting_Godot/src/game/activity/weapon/knife/Knife.cs @@ -75,7 +75,7 @@ { Debug.Log("近战武器攻击! 蓄力时长: " + GetTriggerChargeTime() + ", 扳机按下时长: " + GetTriggerDownTime()); //更新碰撞层级 - _hitArea.CollisionMask = GetAttackLayer() | PhysicsLayer.Bullet; + _hitArea.CollisionMask = AttackLayer | PhysicsLayer.Bullet; //启用碰撞 _hitArea.Monitoring = true; _attackIndex = 0; @@ -143,7 +143,6 @@ } bullet.MoveController.ScaleAllVelocity(scale); bullet.Rotation += Mathf.Pi; - bullet.AttackLayer = TriggerRole.AttackLayer; bullet.RefreshBulletColor(false); } } @@ -195,6 +194,9 @@ } //造成伤害 - hurt.Hurt(TriggerRole, damage, (hurt.GetPosition() - globalPosition).Angle()); + if (hurt.CanHurt(TriggerRole)) + { + hurt.Hurt(TriggerRole, damage, (hurt.GetPosition() - globalPosition).Angle()); + } } } diff --git a/DungeonShooting_Godot/src/game/data/property/PhysicsLayer.cs b/DungeonShooting_Godot/src/game/data/property/PhysicsLayer.cs index 0194269..cf6f7f8 100644 --- a/DungeonShooting_Godot/src/game/data/property/PhysicsLayer.cs +++ b/DungeonShooting_Godot/src/game/data/property/PhysicsLayer.cs @@ -24,9 +24,9 @@ /// public const uint Player = 0b1000; /// - /// 敌人 + /// 角色基类 /// - public const uint Enemy = 0b10000; + public const uint Role = 0b10000; /// /// 归属区域判断层级 /// @@ -48,7 +48,7 @@ /// public const uint Obstacle = 0b1000000000; /// - /// npc + /// 可被子弹击中的区域 /// - public const uint Npc = 0b10000000000; + public const uint HurtArea = 0b10000000000; } \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/manager/FireManager.cs b/DungeonShooting_Godot/src/game/manager/FireManager.cs index c7b436b..a941ca2 100644 --- a/DungeonShooting_Godot/src/game/manager/FireManager.cs +++ b/DungeonShooting_Godot/src/game/manager/FireManager.cs @@ -97,11 +97,11 @@ { if (bullet.Type == 1) //实体子弹 { - return ShootSolidBullet(CreateSolidBulletData(weapon, fireRotation, bullet), weapon.GetAttackLayer()); + return ShootSolidBullet(CreateSolidBulletData(weapon, fireRotation, bullet), weapon.AttackLayer); } else if (bullet.Type == 2) //激光子弹 { - return ShootLaser(CreateLaserData(weapon, fireRotation, bullet), weapon.GetAttackLayer()); + return ShootLaser(CreateLaserData(weapon, fireRotation, bullet), weapon.AttackLayer); } else { @@ -118,7 +118,7 @@ { if (bullet.Type == 1) //实体子弹 { - return ShootSolidBullet(CreateSolidBulletData(trigger, fireRotation, bullet), trigger.AttackLayer); + return ShootSolidBullet(CreateSolidBulletData(trigger, fireRotation, bullet), Role.AttackLayer); } return null; diff --git a/DungeonShooting_Godot/src/game/room/DungeonManager.cs b/DungeonShooting_Godot/src/game/room/DungeonManager.cs index ab52b27..7878e52 100644 --- a/DungeonShooting_Godot/src/game/room/DungeonManager.cs +++ b/DungeonShooting_Godot/src/game/room/DungeonManager.cs @@ -904,7 +904,7 @@ { //房间内是否有存活的敌人 var flag = ActiveAffiliationArea.ExistEnterItem( - activityObject => activityObject.CollisionWithMask(PhysicsLayer.Enemy) + activityObject => activityObject is Role role && role.IsEnemyWithPlayer() ); //Debug.Log("当前房间存活数量: " + count); if (!flag) diff --git a/DungeonShooting_Godot/src/game/world/World.cs b/DungeonShooting_Godot/src/game/world/World.cs new file mode 100644 index 0000000..34add95 --- /dev/null +++ b/DungeonShooting_Godot/src/game/world/World.cs @@ -0,0 +1,202 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using Godot; + +/// +/// 游戏世界 +/// +public partial class World : CanvasModulate, ICoroutine +{ + /// + /// 当前的游戏世界对象 + /// + public static World Current => GameApplication.Instance.DungeonManager.CurrWorld; + + /// + /// 当前操作的玩家 + /// + public Player Player { get; private set; } + + /// + /// //对象根节点 + /// + public Node2D NormalLayer; + + /// + /// 对象根节点, 带y轴排序功能 + /// + public Node2D YSortLayer; + + /// + /// 地图根节点 + /// + public TileMap TileRoot; + + public Node2D StaticSpriteRoot; + public Node2D AffiliationAreaRoot; + public Node2D FogMaskRoot; + public Node2D NavigationRoot; + + /// + /// 是否暂停 + /// + public bool Pause + { + get => _pause; + set + { + if (_pause != value) + { + _pause = value; + if (value) + { + ProcessMode = ProcessModeEnum.WhenPaused; + } + else + { + ProcessMode = ProcessModeEnum.Inherit; + } + } + } + } + + /// + /// 所有被扔在地上的武器 + /// + public HashSet Weapon_UnclaimedWeapons { get; } = new HashSet(); + + /// + /// 记录所有存活的敌人 + /// + public List Enemy_InstanceList { get; } = new List(); + + /// + /// 随机数对象 + /// + public SeedRandom Random { get; private set; } + + /// + /// 随机对象池 + /// + public RandomPool RandomPool { get; private set; } + + /// + /// 角色死亡事件 + /// + public event Action OnRoleDieEvent; + + private bool _pause = false; + private List _coroutineList; + + public override void _Ready() + { + //TileRoot.YSortEnabled = false; + NormalLayer = GetNode("TileRoot/NormalLayer"); + YSortLayer = GetNode("TileRoot/YSortLayer"); + TileRoot = GetNode("TileRoot"); + StaticSpriteRoot = GetNode("TileRoot/StaticSpriteRoot"); + FogMaskRoot = GetNode("TileRoot/FogMaskRoot"); + NavigationRoot = GetNode("TileRoot/NavigationRoot"); + AffiliationAreaRoot = GetNode("TileRoot/AffiliationAreaRoot"); + } + + public override void _Process(double delta) + { + //协程更新 + ProxyCoroutineHandler.ProxyUpdateCoroutine(ref _coroutineList, (float)delta); + } + + /// + /// 获取指定层级根节点 + /// + public Node2D GetRoomLayer(RoomLayerEnum layerEnum) + { + switch (layerEnum) + { + case RoomLayerEnum.NormalLayer: + return NormalLayer; + case RoomLayerEnum.YSortLayer: + return YSortLayer; + } + + return null; + } + + /// + /// 设置当前操作的玩家对象 + /// + public void SetCurrentPlayer(Player player) + { + Player = player; + //设置相机和鼠标跟随玩家 + GameCamera.Main.SetFollowTarget(player); + GameApplication.Instance.Cursor.SetMountRole(player); + } + + /// + /// 通知其他敌人发现目标了 + /// + /// 发送通知的角色 + /// 目标 + public void NotifyEnemyTarget(Role self, ActivityObject target) + { + foreach (var role in Enemy_InstanceList) + { + if (role != self && !role.IsDestroyed && role.AffiliationArea == self.AffiliationArea) + { + //将未发现目标的敌人状态置为惊讶状态 + var controller = role.StateController; + //延时通知效果 + role.CallDelay(Utils.Random.RandomRangeFloat(0.2f, 1f), () => + { + if (controller.CurrState == AIStateEnum.AiNormal) + { + controller.ChangeState(AIStateEnum.AiLeaveFor, target); + } + }); + } + } + } + + public long StartCoroutine(IEnumerator able) + { + return ProxyCoroutineHandler.ProxyStartCoroutine(ref _coroutineList, able); + } + + public void StopCoroutine(long coroutineId) + { + ProxyCoroutineHandler.ProxyStopCoroutine(ref _coroutineList, coroutineId); + } + + public bool IsCoroutineOver(long coroutineId) + { + return ProxyCoroutineHandler.ProxyIsCoroutineOver(ref _coroutineList, coroutineId); + } + + public void StopAllCoroutine() + { + ProxyCoroutineHandler.ProxyStopAllCoroutine(ref _coroutineList); + } + + /// + /// 初始化随机池 + /// + public void InitRandomPool(SeedRandom random) + { + Random = random; + RandomPool = new RandomPool(this); + } + + /// + /// 角色死亡 + /// + public void OnRoleDie(Role role) + { + if (OnRoleDieEvent != null) + { + OnRoleDieEvent(role); + } + } +} \ No newline at end of file