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. private readonly List<IProp> InteractiveItemList = new List<IProp>();
  94.  
  95. /// <summary>
  96. /// 当血量改变时调用
  97. /// </summary>
  98. protected abstract void OnChangeHp(int hp);
  99. /// <summary>
  100. /// 当最大血量改变时调用
  101. /// </summary>
  102. protected abstract void OnChangeMaxHp(int maxHp);
  103.  
  104. public override void _Ready()
  105. {
  106. StartScele = Scale;
  107. AnimatedSprite = GetNode<AnimatedSprite>("AnimatedSprite");
  108. MountPoint = GetNode<Position2D>("MountPoint");
  109. BackMountPoint = GetNode<Position2D>("BackMountPoint");
  110. // 更改纹理
  111. ChangeFrameTexture(AnimatorNames.Idle, AnimatedSprite, Texture);
  112. ChangeFrameTexture(AnimatorNames.Run, AnimatedSprite, Texture);
  113. ChangeFrameTexture(AnimatorNames.ReverseRun, AnimatedSprite, Texture);
  114.  
  115. Holster = new Holster(this);
  116. Face = FaceDirection.Right;
  117. }
  118.  
  119. /// <summary>
  120. /// 拾起一个武器, 并且切换到这个武器
  121. /// </summary>
  122. /// <param name="gun">武器对象</param>
  123. public void PickUpGun(Gun gun)
  124. {
  125. Holster.PickupGun(gun);
  126. }
  127.  
  128. /// <summary>
  129. /// 切换到下一个武器
  130. /// </summary>
  131. public void TriggerExchangeNext()
  132. {
  133. Holster.ExchangeNext();
  134. }
  135.  
  136. /// <summary>
  137. /// 切换到上一个武器
  138. /// </summary>
  139. public void ExchangePrev()
  140. {
  141. Holster.ExchangePrev();
  142. }
  143.  
  144. /// <summary>
  145. /// 扔掉当前使用的武器, 切换到上一个武器
  146. /// </summary>
  147. public void TriggerThrowGun()
  148. {
  149. var gun = Holster.RmoveGun(Holster.ActiveIndex);
  150. //播放抛出效果
  151. if (gun != null)
  152. {
  153. if (Face == FaceDirection.Left)
  154. {
  155. gun.Scale *= new Vector2(1, -1);
  156. gun.RotationDegrees = 180;
  157. }
  158. gun.Position = Vector2.Zero;
  159. var temp = new ThrowGun();
  160. var startPos = GlobalPosition + new Vector2(0, 0);
  161. var startHeight = 6;
  162. var direction = GlobalRotationDegrees + MathUtils.RandRangeInt(-20, 20);
  163. var xf = 30;
  164. var yf = MathUtils.RandRangeInt(60, 120);
  165. var rotate = MathUtils.RandRangeInt(-180, 180);
  166. temp.InitThrow(new Vector2(20, 20), startPos, startHeight, direction, xf, yf, rotate, gun, gun.GunSprite);
  167. RoomManager.Current.SortRoot.AddChild(temp);
  168. }
  169. }
  170.  
  171. /// <summary>
  172. /// 返回是否存在可互动的物体
  173. /// </summary>
  174. public bool HasTnteractive()
  175. {
  176. return InteractiveItemList.Count > 0;
  177. }
  178.  
  179. /// <summary>
  180. /// 触发与碰撞的物体互动
  181. /// </summary>
  182. public void TriggerTnteractive()
  183. {
  184. if (HasTnteractive())
  185. {
  186. var item = InteractiveItemList[InteractiveItemList.Count - 1];
  187. item.Tnteractive(this);
  188. }
  189. }
  190.  
  191. /// <summary>
  192. /// 触发换弹
  193. /// </summary>
  194. public void TriggerReload()
  195. {
  196. if (Holster.ActiveGun != null)
  197. {
  198. Holster.ActiveGun._Reload();
  199. }
  200. }
  201.  
  202. /// <summary>
  203. /// 触发攻击
  204. /// </summary>
  205. public void TriggerAttack()
  206. {
  207. if (Holster.ActiveGun != null)
  208. {
  209. Holster.ActiveGun.Trigger();
  210. }
  211. }
  212.  
  213. /// <summary>
  214. /// 设置脸的朝向
  215. /// </summary>
  216. private void SetFace(FaceDirection face)
  217. {
  218. if (_face != face)
  219. {
  220. _face = face;
  221. if (face == FaceDirection.Right)
  222. {
  223. RotationDegrees = 0;
  224. Scale = StartScele;
  225. }
  226. else
  227. {
  228. RotationDegrees = 180;
  229. Scale = new Vector2(StartScele.x, -StartScele.y);
  230. }
  231. }
  232. }
  233.  
  234. /// <summary>
  235. /// 更改指定动画的纹理
  236. /// </summary>
  237. private void ChangeFrameTexture(string anim, AnimatedSprite animatedSprite, Texture texture)
  238. {
  239. SpriteFrames spriteFrames = animatedSprite.Frames as SpriteFrames;
  240. if (spriteFrames != null)
  241. {
  242. int count = spriteFrames.GetFrameCount(anim);
  243. for (int i = 0; i < count; i++)
  244. {
  245. AtlasTexture temp = spriteFrames.GetFrame(anim, i) as AtlasTexture;
  246. temp.Atlas = Texture;
  247. }
  248. }
  249. }
  250.  
  251. /// <summary>
  252. /// 连接信号: InteractiveArea.area_entered
  253. /// 与道具碰撞
  254. /// </summary>
  255. private void _OnPropsEnter(Area2D other)
  256. {
  257. if (other is IProp prop)
  258. {
  259. if (!InteractiveItemList.Contains(prop))
  260. {
  261. InteractiveItemList.Add(prop);
  262. }
  263. }
  264. }
  265.  
  266. /// <summary>
  267. /// 连接信号: InteractiveArea.area_exited
  268. /// 道具离开碰撞区域
  269. /// </summary>
  270. private void _OnPropsExit(Area2D other)
  271. {
  272. if (other is IProp prop)
  273. {
  274. if (InteractiveItemList.Contains(prop))
  275. {
  276. InteractiveItemList.Remove(prop);
  277. }
  278. }
  279. }
  280.  
  281. }