Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / role / Role.cs
  1. using System.Collections.Generic;
  2. using Godot;
  3.  
  4. /// <summary>
  5. /// 角色基类
  6. /// </summary>
  7. public abstract class Role : ActivityObject
  8. {
  9. /// <summary>
  10. /// 动画播放器
  11. /// </summary>
  12. public AnimationPlayer AnimationPlayer { get; private set; }
  13. /// <summary>
  14. /// 重写的纹理
  15. /// </summary>
  16. public Texture OverrideTexture { get; protected set; }
  17.  
  18. /// <summary>
  19. /// 移动速度
  20. /// </summary>
  21. public float MoveSpeed = 120f;
  22.  
  23. /// <summary>
  24. /// 所属阵营
  25. /// </summary>
  26. public CampEnum Camp;
  27.  
  28. /// <summary>
  29. /// 携带的道具包裹
  30. /// </summary>
  31. public List<object> PropsPack { get; } = new List<object>();
  32.  
  33. /// <summary>
  34. /// 角色携带的枪套
  35. /// </summary>
  36. public Holster Holster { get; }
  37.  
  38. /// <summary>
  39. /// 武器挂载点
  40. /// </summary>
  41. public MountRotation MountPoint { get; private set; }
  42. /// <summary>
  43. /// 背后武器的挂载点
  44. /// </summary>
  45. public Position2D BackMountPoint { get; private set; }
  46.  
  47. /// <summary>
  48. /// 互动碰撞区域
  49. /// </summary>
  50. public Area2D InteractiveArea { get; private set; }
  51. /// <summary>
  52. /// 脸的朝向
  53. /// </summary>
  54. public FaceDirection Face { get => _face; set => SetFace(value); }
  55. private FaceDirection _face;
  56.  
  57. /// <summary>
  58. /// 血量
  59. /// </summary>
  60. public int Hp
  61. {
  62. get => _hp;
  63. protected set
  64. {
  65. int temp = _hp;
  66. _hp = value;
  67. if (temp != _hp) OnChangeHp(_hp);
  68. }
  69. }
  70. private int _hp = 0;
  71.  
  72. /// <summary>
  73. /// 最大血量
  74. /// </summary>
  75. public int MaxHp
  76. {
  77. get => _maxHp;
  78. protected set
  79. {
  80. int temp = _maxHp;
  81. _maxHp = value;
  82. if (temp != _maxHp) OnChangeMaxHp(_maxHp);
  83. }
  84. }
  85. private int _maxHp = 0;
  86. //初始缩放
  87. private Vector2 StartScele;
  88. //所有角色碰撞的道具
  89. private readonly List<ActivityObject> InteractiveItemList = new List<ActivityObject>();
  90.  
  91. private CheckInteractiveResult TempResultData;
  92.  
  93. /// <summary>
  94. /// 可以互动的道具
  95. /// </summary>
  96. protected ActivityObject InteractiveItem { get; private set; }
  97.  
  98. /// <summary>
  99. /// 当血量改变时调用
  100. /// </summary>
  101. protected virtual void OnChangeHp(int hp)
  102. {
  103. }
  104.  
  105. /// <summary>
  106. /// 当最大血量改变时调用
  107. /// </summary>
  108. protected virtual void OnChangeMaxHp(int maxHp)
  109. {
  110. }
  111.  
  112. /// <summary>
  113. /// 当受伤时调用
  114. /// </summary>
  115. /// <param name="damage">受到的伤害</param>
  116. public virtual void OnHit(int damage)
  117. {
  118. }
  119.  
  120. /// <summary>
  121. /// 当可互动的物体改变时调用, result 参数为 null 表示变为不可互动
  122. /// </summary>
  123. /// <param name="result">检测是否可互动时的返回值</param>
  124. protected virtual void ChangeInteractiveItem(CheckInteractiveResult result)
  125. {
  126. }
  127.  
  128. public Role() : this(ResourcePath.prefab_role_Role_tscn)
  129. {
  130. }
  131. public Role(string scenePath) : base(scenePath)
  132. {
  133. Holster = new Holster(this);
  134. }
  135. public override void _Ready()
  136. {
  137. base._Ready();
  138. AnimationPlayer = GetNode<AnimationPlayer>("AnimationPlayer");
  139. StartScele = Scale;
  140. MountPoint = GetNode<MountRotation>("MountPoint");
  141. MountPoint.Master = this;
  142. BackMountPoint = GetNode<Position2D>("BackMountPoint");
  143. //即将弃用
  144. if (OverrideTexture != null)
  145. {
  146. // 更改纹理
  147. ChangeFrameTexture(AnimatorNames.Idle, AnimatedSprite, OverrideTexture);
  148. ChangeFrameTexture(AnimatorNames.Run, AnimatedSprite, OverrideTexture);
  149. ChangeFrameTexture(AnimatorNames.ReverseRun, AnimatedSprite, OverrideTexture);
  150. }
  151. Face = FaceDirection.Right;
  152.  
  153. //连接互动物体信号
  154. InteractiveArea = GetNode<Area2D>("InteractiveArea");
  155. InteractiveArea.Connect("area_entered", this, nameof(_OnPropsEnter));
  156. InteractiveArea.Connect("area_exited", this, nameof(_OnPropsExit));
  157. }
  158.  
  159. public override void _Process(float delta)
  160. {
  161. base._Process(delta);
  162. //检查可互动的道具
  163. bool findFlag = false;
  164. for (int i = 0; i < InteractiveItemList.Count; i++)
  165. {
  166. var item = InteractiveItemList[i];
  167. if (item == null)
  168. {
  169. InteractiveItemList.RemoveAt(i--);
  170. }
  171. else
  172. {
  173. //找到可互动的道具了
  174. if (!findFlag)
  175. {
  176. var result = item.CheckInteractive(this);
  177. if (result.CanInteractive) //可以互动
  178. {
  179. findFlag = true;
  180. if (InteractiveItem != item) //更改互动物体
  181. {
  182. InteractiveItem = item;
  183. ChangeInteractiveItem(result);
  184. }
  185. else if (result.ShowIcon != TempResultData.ShowIcon) //切换状态
  186. {
  187. ChangeInteractiveItem(result);
  188. }
  189. }
  190. TempResultData = result;
  191. }
  192. }
  193. }
  194. //没有可互动的道具
  195. if (!findFlag && InteractiveItem != null)
  196. {
  197. InteractiveItem = null;
  198. ChangeInteractiveItem(null);
  199. }
  200. }
  201.  
  202. /// <summary>
  203. /// 拾起一个武器, 并且切换到这个武器
  204. /// </summary>
  205. /// <param name="weapon">武器对象</param>
  206. public virtual void PickUpWeapon(Weapon weapon)
  207. {
  208. if (Holster.PickupWeapon(weapon) != -1)
  209. {
  210. //从可互动队列中移除
  211. InteractiveItemList.Remove(weapon);
  212. }
  213. }
  214.  
  215. /// <summary>
  216. /// 切换到下一个武器
  217. /// </summary>
  218. public virtual void ExchangeNext()
  219. {
  220. Holster.ExchangeNext();
  221. }
  222.  
  223. /// <summary>
  224. /// 切换到上一个武器
  225. /// </summary>
  226. public virtual void ExchangePrev()
  227. {
  228. Holster.ExchangePrev();
  229. }
  230.  
  231. /// <summary>
  232. /// 扔掉当前使用的武器, 切换到上一个武器
  233. /// </summary>
  234. public virtual void ThrowWeapon()
  235. {
  236. var weapon = Holster.RemoveWeapon(Holster.ActiveIndex);
  237. //播放抛出效果
  238. if (weapon != null)
  239. {
  240. weapon.ThrowWeapon(this);
  241. }
  242. }
  243.  
  244. /// <summary>
  245. /// 返回是否存在可互动的物体
  246. /// </summary>
  247. public bool HasInteractive()
  248. {
  249. return InteractiveItem != null;
  250. }
  251.  
  252. /// <summary>
  253. /// 触发与碰撞的物体互动, 并返回与其互动的物体
  254. /// </summary>
  255. public ActivityObject TriggerInteractive()
  256. {
  257. if (HasInteractive())
  258. {
  259. var item = InteractiveItem;
  260. item.Interactive(this);
  261. return item;
  262. }
  263. return null;
  264. }
  265.  
  266. /// <summary>
  267. /// 触发换弹
  268. /// </summary>
  269. public virtual void Reload()
  270. {
  271. if (Holster.ActiveWeapon != null)
  272. {
  273. Holster.ActiveWeapon.Reload();
  274. }
  275. }
  276.  
  277. /// <summary>
  278. /// 触发攻击
  279. /// </summary>
  280. public virtual void Attack()
  281. {
  282. if (Holster.ActiveWeapon != null)
  283. {
  284. Holster.ActiveWeapon.Trigger();
  285. }
  286. }
  287.  
  288. /// <summary>
  289. /// 受到伤害
  290. /// </summary>
  291. /// <param name="damage">伤害的量</param>
  292. public virtual void Hit(int damage)
  293. {
  294. Hp -= damage;
  295. GD.Print("打到敌人了!");
  296. OnHit(damage);
  297. }
  298.  
  299. /// <summary>
  300. /// 设置脸的朝向
  301. /// </summary>
  302. private void SetFace(FaceDirection face)
  303. {
  304. if (_face != face)
  305. {
  306. _face = face;
  307. if (face == FaceDirection.Right)
  308. {
  309. RotationDegrees = 0;
  310. Scale = StartScele;
  311. }
  312. else
  313. {
  314. RotationDegrees = 180;
  315. Scale = new Vector2(StartScele.x, -StartScele.y);
  316. }
  317. }
  318. }
  319.  
  320. /// <summary>
  321. /// 更改指定动画的纹理
  322. /// </summary>
  323. private void ChangeFrameTexture(string anim, AnimatedSprite animatedSprite, Texture texture)
  324. {
  325. SpriteFrames spriteFrames = animatedSprite.Frames;
  326. if (spriteFrames != null)
  327. {
  328. int count = spriteFrames.GetFrameCount(anim);
  329. for (int i = 0; i < count; i++)
  330. {
  331. AtlasTexture temp = spriteFrames.GetFrame(anim, i) as AtlasTexture;
  332. temp.Atlas = OverrideTexture;
  333. }
  334. }
  335. }
  336.  
  337. /// <summary>
  338. /// 连接信号: InteractiveArea.area_entered
  339. /// 与物体碰撞
  340. /// </summary>
  341. private void _OnPropsEnter(Area2D other)
  342. {
  343. ActivityObject propObject = other.AsActivityObject();
  344. if (propObject != null)
  345. {
  346. if (!InteractiveItemList.Contains(propObject))
  347. {
  348. InteractiveItemList.Add(propObject);
  349. }
  350. }
  351. }
  352.  
  353. /// <summary>
  354. /// 连接信号: InteractiveArea.area_exited
  355. /// 物体离开碰撞区域
  356. /// </summary>
  357. private void _OnPropsExit(Area2D other)
  358. {
  359. ActivityObject propObject = other.AsActivityObject();
  360. if (propObject != null)
  361. {
  362. if (InteractiveItemList.Contains(propObject))
  363. {
  364. InteractiveItemList.Remove(propObject);
  365. }
  366. if (InteractiveItem == propObject)
  367. {
  368. InteractiveItem = null;
  369. ChangeInteractiveItem(null);
  370. }
  371. }
  372. }
  373. }