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