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