Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / role / Role.cs
@lijincheng lijincheng on 11 Nov 2022 12 KB 添加Role状态控制器
  1. using System;
  2. using System.Collections.Generic;
  3. using Godot;
  4.  
  5. /// <summary>
  6. /// 角色基类
  7. /// </summary>
  8. public abstract class Role : ActivityObject
  9. {
  10. /// <summary>
  11. /// 默认攻击对象层级
  12. /// </summary>
  13. public const uint DefaultAttackLayer = PhysicsLayer.Player | PhysicsLayer.Enemy | PhysicsLayer.Wall | PhysicsLayer.Props;
  14. /// <summary>
  15. /// 动画播放器
  16. /// </summary>
  17. public AnimationPlayer AnimationPlayer { get; private set; }
  18. /// <summary>
  19. /// 重写的纹理, 即将删除, 请直接更改 AnimatedSprite.Frames
  20. /// </summary>
  21. [Obsolete]
  22. public Texture OverrideTexture { get; protected set; }
  23.  
  24. /// <summary>
  25. /// 移动速度
  26. /// </summary>
  27. public float MoveSpeed = 120f;
  28.  
  29. /// <summary>
  30. /// 所属阵营
  31. /// </summary>
  32. public CampEnum Camp;
  33.  
  34. /// <summary>
  35. /// 攻击目标的碰撞器所属层级, 数据源自于: PhysicsLayer
  36. /// </summary>
  37. public uint AttackLayer { get; set; } = PhysicsLayer.Wall;
  38.  
  39. /// <summary>
  40. /// 携带的道具包裹
  41. /// </summary>
  42. public List<object> PropsPack { get; } = new List<object>();
  43.  
  44. /// <summary>
  45. /// 角色携带的枪套
  46. /// </summary>
  47. public Holster Holster { get; }
  48.  
  49. /// <summary>
  50. /// 武器挂载点
  51. /// </summary>
  52. public MountRotation MountPoint { get; private set; }
  53. /// <summary>
  54. /// 背后武器的挂载点
  55. /// </summary>
  56. public Position2D BackMountPoint { get; private set; }
  57.  
  58. /// <summary>
  59. /// 互动碰撞区域
  60. /// </summary>
  61. public Area2D InteractiveArea { get; private set; }
  62. /// <summary>
  63. /// 脸的朝向
  64. /// </summary>
  65. public FaceDirection Face { get => _face; set => SetFace(value); }
  66. private FaceDirection _face;
  67.  
  68. /// <summary>
  69. /// 是否启用角色移动
  70. /// </summary>
  71. public bool EnableMove { get; set; } = true;
  72. /// <summary>
  73. /// 移动速度
  74. /// </summary>
  75. public Vector2 Velocity { get; set; } = Vector2.Zero;
  76. /// <summary>
  77. /// 血量
  78. /// </summary>
  79. public int Hp
  80. {
  81. get => _hp;
  82. protected set
  83. {
  84. int temp = _hp;
  85. _hp = value;
  86. if (temp != _hp) OnChangeHp(_hp);
  87. }
  88. }
  89. private int _hp = 0;
  90.  
  91. /// <summary>
  92. /// 最大血量
  93. /// </summary>
  94. public int MaxHp
  95. {
  96. get => _maxHp;
  97. protected set
  98. {
  99. int temp = _maxHp;
  100. _maxHp = value;
  101. if (temp != _maxHp) OnChangeMaxHp(_maxHp);
  102. }
  103. }
  104. private int _maxHp = 0;
  105. /// <summary>
  106. /// 当前护盾值
  107. /// </summary>
  108. public int Shield
  109. {
  110. get => _shield;
  111. protected set
  112. {
  113. int temp = _shield;
  114. _shield = value;
  115. if (temp != _shield) OnChangeShield(_shield);
  116. }
  117. }
  118. private int _shield = 0;
  119.  
  120. /// <summary>
  121. /// 最大护盾值
  122. /// </summary>
  123. public int MaxShield
  124. {
  125. get => _maxShield;
  126. protected set
  127. {
  128. int temp = _maxShield;
  129. _maxShield = value;
  130. if (temp != _maxShield) OnChangeMaxShield(_maxShield);
  131. }
  132. }
  133. private int _maxShield = 0;
  134.  
  135. /// <summary>
  136. /// 当前角色所看向的对象, 也就是枪口指向的对象
  137. /// </summary>
  138. public ActivityObject LookTarget { get; set; }
  139. /// <summary>
  140. ///
  141. /// </summary>
  142. public StateCtr StateCtr { get; }
  143. //初始缩放
  144. private Vector2 _startScale;
  145. //所有角色碰撞的道具
  146. private readonly List<ActivityObject> _interactiveItemList = new List<ActivityObject>();
  147.  
  148. private CheckInteractiveResult _tempResultData;
  149.  
  150. /// <summary>
  151. /// 可以互动的道具
  152. /// </summary>
  153. protected ActivityObject InteractiveItem { get; private set; }
  154.  
  155. /// <summary>
  156. /// 当血量改变时调用
  157. /// </summary>
  158. protected virtual void OnChangeHp(int hp)
  159. {
  160. }
  161.  
  162. /// <summary>
  163. /// 当最大血量改变时调用
  164. /// </summary>
  165. protected virtual void OnChangeMaxHp(int maxHp)
  166. {
  167. }
  168. /// <summary>
  169. /// 护盾值改变时调用
  170. /// </summary>
  171. protected virtual void OnChangeShield(int shield)
  172. {
  173. }
  174.  
  175. /// <summary>
  176. /// 最大护盾值改变时调用
  177. /// </summary>
  178. protected virtual void OnChangeMaxShield(int maxShield)
  179. {
  180. }
  181.  
  182. /// <summary>
  183. /// 当受伤时调用
  184. /// </summary>
  185. /// <param name="damage">受到的伤害</param>
  186. protected virtual void OnHit(int damage)
  187. {
  188. }
  189.  
  190. /// <summary>
  191. /// 当可互动的物体改变时调用, result 参数为 null 表示变为不可互动
  192. /// </summary>
  193. /// <param name="result">检测是否可互动时的返回值</param>
  194. protected virtual void ChangeInteractiveItem(CheckInteractiveResult result)
  195. {
  196. }
  197.  
  198. /// <summary>
  199. /// 死亡时调用
  200. /// </summary>
  201. protected virtual void OnDie()
  202. {
  203. }
  204. public Role() : this(ResourcePath.prefab_role_Role_tscn)
  205. {
  206. }
  207. public Role(string scenePath) : base(scenePath)
  208. {
  209. Holster = new Holster(this);
  210. }
  211. public override void _Ready()
  212. {
  213. base._Ready();
  214. AnimationPlayer = GetNode<AnimationPlayer>("AnimationPlayer");
  215. _startScale = Scale;
  216. MountPoint = GetNode<MountRotation>("MountPoint");
  217. MountPoint.Master = this;
  218. BackMountPoint = GetNode<Position2D>("BackMountPoint");
  219. //即将删除
  220. if (OverrideTexture != null)
  221. {
  222. // 更改纹理
  223. ChangeFrameTexture(AnimatorNames.Idle, AnimatedSprite);
  224. ChangeFrameTexture(AnimatorNames.Run, AnimatedSprite);
  225. ChangeFrameTexture(AnimatorNames.ReverseRun, AnimatedSprite);
  226. }
  227. Face = FaceDirection.Right;
  228.  
  229. //连接互动物体信号
  230. InteractiveArea = GetNode<Area2D>("InteractiveArea");
  231. InteractiveArea.Connect("area_entered", this, nameof(_OnPropsEnter));
  232. InteractiveArea.Connect("area_exited", this, nameof(_OnPropsExit));
  233. }
  234.  
  235. public override void _Process(float delta)
  236. {
  237. base._Process(delta);
  238. //看向目标
  239. if (LookTarget != null)
  240. {
  241. Vector2 pos = LookTarget.GlobalPosition;
  242. //脸的朝向
  243. var gPos = GlobalPosition;
  244. if (pos.x > gPos.x && Face == FaceDirection.Left)
  245. {
  246. Face = FaceDirection.Right;
  247. }
  248. else if (pos.x < gPos.x && Face == FaceDirection.Right)
  249. {
  250. Face = FaceDirection.Left;
  251. }
  252. //枪口跟随目标
  253. MountPoint.SetLookAt(pos);
  254. }
  255. //检查可互动的道具
  256. bool findFlag = false;
  257. for (int i = 0; i < _interactiveItemList.Count; i++)
  258. {
  259. var item = _interactiveItemList[i];
  260. if (item == null)
  261. {
  262. _interactiveItemList.RemoveAt(i--);
  263. }
  264. else
  265. {
  266. //找到可互动的道具了
  267. if (!findFlag)
  268. {
  269. var result = item.CheckInteractive(this);
  270. if (result.CanInteractive) //可以互动
  271. {
  272. findFlag = true;
  273. if (InteractiveItem != item) //更改互动物体
  274. {
  275. InteractiveItem = item;
  276. ChangeInteractiveItem(result);
  277. }
  278. else if (result.ShowIcon != _tempResultData.ShowIcon) //切换状态
  279. {
  280. ChangeInteractiveItem(result);
  281. }
  282. }
  283. _tempResultData = result;
  284. }
  285. }
  286. }
  287. //没有可互动的道具
  288. if (!findFlag && InteractiveItem != null)
  289. {
  290. InteractiveItem = null;
  291. ChangeInteractiveItem(null);
  292. }
  293. }
  294.  
  295. /// <summary>
  296. /// 计算角色移动
  297. /// </summary>
  298. public virtual void CalcMove(float delta)
  299. {
  300. if (EnableMove && Velocity != Vector2.Zero)
  301. {
  302. Velocity = MoveAndSlide(Velocity);
  303. }
  304. }
  305.  
  306. /// <summary>
  307. /// 拾起一个武器, 并且切换到这个武器
  308. /// </summary>
  309. /// <param name="weapon">武器对象</param>
  310. public virtual void PickUpWeapon(Weapon weapon)
  311. {
  312. if (Holster.PickupWeapon(weapon) != -1)
  313. {
  314. //从可互动队列中移除
  315. _interactiveItemList.Remove(weapon);
  316. }
  317. }
  318.  
  319. /// <summary>
  320. /// 切换到下一个武器
  321. /// </summary>
  322. public virtual void ExchangeNext()
  323. {
  324. Holster.ExchangeNext();
  325. }
  326.  
  327. /// <summary>
  328. /// 切换到上一个武器
  329. /// </summary>
  330. public virtual void ExchangePrev()
  331. {
  332. Holster.ExchangePrev();
  333. }
  334.  
  335. /// <summary>
  336. /// 扔掉当前使用的武器, 切换到上一个武器
  337. /// </summary>
  338. public virtual void ThrowWeapon()
  339. {
  340. var weapon = Holster.RemoveWeapon(Holster.ActiveIndex);
  341. //播放抛出效果
  342. if (weapon != null)
  343. {
  344. weapon.ThrowWeapon(this);
  345. }
  346. }
  347.  
  348. /// <summary>
  349. /// 返回是否存在可互动的物体
  350. /// </summary>
  351. public bool HasInteractive()
  352. {
  353. return InteractiveItem != null;
  354. }
  355.  
  356. /// <summary>
  357. /// 触发与碰撞的物体互动, 并返回与其互动的物体
  358. /// </summary>
  359. public ActivityObject TriggerInteractive()
  360. {
  361. if (HasInteractive())
  362. {
  363. var item = InteractiveItem;
  364. item.Interactive(this);
  365. return item;
  366. }
  367. return null;
  368. }
  369.  
  370. /// <summary>
  371. /// 触发换弹
  372. /// </summary>
  373. public virtual void Reload()
  374. {
  375. if (Holster.ActiveWeapon != null)
  376. {
  377. Holster.ActiveWeapon.Reload();
  378. }
  379. }
  380.  
  381. /// <summary>
  382. /// 触发攻击
  383. /// </summary>
  384. public virtual void Attack()
  385. {
  386. if (Holster.ActiveWeapon != null)
  387. {
  388. Holster.ActiveWeapon.Trigger();
  389. }
  390. }
  391.  
  392. /// <summary>
  393. /// 受到伤害
  394. /// </summary>
  395. /// <param name="damage">伤害的量</param>
  396. public virtual void Hit(int damage)
  397. {
  398. Hp -= damage;
  399. AnimationPlayer.Stop();
  400. AnimationPlayer.Play("hit");
  401. OnHit(damage);
  402. }
  403.  
  404. /// <summary>
  405. /// 设置脸的朝向
  406. /// </summary>
  407. private void SetFace(FaceDirection face)
  408. {
  409. if (_face != face)
  410. {
  411. _face = face;
  412. if (face == FaceDirection.Right)
  413. {
  414. RotationDegrees = 0;
  415. Scale = _startScale;
  416. }
  417. else
  418. {
  419. RotationDegrees = 180;
  420. Scale = new Vector2(_startScale.x, -_startScale.y);
  421. }
  422. }
  423. }
  424.  
  425. /// <summary>
  426. /// 更改指定动画的纹理, 即将删除
  427. /// </summary>
  428. [Obsolete]
  429. private void ChangeFrameTexture(string anim, AnimatedSprite animatedSprite)
  430. {
  431. SpriteFrames spriteFrames = animatedSprite.Frames;
  432. if (spriteFrames != null)
  433. {
  434. int count = spriteFrames.GetFrameCount(anim);
  435. for (int i = 0; i < count; i++)
  436. {
  437. AtlasTexture temp = spriteFrames.GetFrame(anim, i) as AtlasTexture;
  438. temp.Atlas = OverrideTexture;
  439. }
  440. }
  441. }
  442.  
  443. /// <summary>
  444. /// 连接信号: InteractiveArea.area_entered
  445. /// 与物体碰撞
  446. /// </summary>
  447. private void _OnPropsEnter(Area2D other)
  448. {
  449. ActivityObject propObject = other.AsActivityObject();
  450. if (propObject != null)
  451. {
  452. if (!_interactiveItemList.Contains(propObject))
  453. {
  454. _interactiveItemList.Add(propObject);
  455. }
  456. }
  457. }
  458.  
  459. /// <summary>
  460. /// 连接信号: InteractiveArea.area_exited
  461. /// 物体离开碰撞区域
  462. /// </summary>
  463. private void _OnPropsExit(Area2D other)
  464. {
  465. ActivityObject propObject = other.AsActivityObject();
  466. if (propObject != null)
  467. {
  468. if (_interactiveItemList.Contains(propObject))
  469. {
  470. _interactiveItemList.Remove(propObject);
  471. }
  472. if (InteractiveItem == propObject)
  473. {
  474. InteractiveItem = null;
  475. ChangeInteractiveItem(null);
  476. }
  477. }
  478. }
  479. }