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