Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / activity / package / Package.cs
@小李xl 小李xl on 23 Nov 2023 11 KB 添加敌人属性表
  1. using System;
  2. using System.Collections.Generic;
  3.  
  4. /// <summary>
  5. /// 物体背包类
  6. /// </summary>
  7. public class Package<T, S> : Component<S> where T : ActivityObject, IPackageItem<S> where S : Role
  8. {
  9. /// <summary>
  10. /// 当前使用对象改变时回调
  11. /// </summary>
  12. public event Action<T> ChangeActiveItemEvent;
  13.  
  14. /// <summary>
  15. /// 当前使用的物体对象
  16. /// </summary>
  17. public T ActiveItem
  18. {
  19. get => _activeItem;
  20. set
  21. {
  22. if (value != _activeItem)
  23. {
  24. _activeItem = value;
  25. if (ChangeActiveItemEvent != null)
  26. {
  27. ChangeActiveItemEvent(value);
  28. }
  29. }
  30. }
  31. }
  32.  
  33. private T _activeItem;
  34.  
  35. /// <summary>
  36. /// 当前使用的物体的索引
  37. /// </summary>
  38. public int ActiveIndex { get; private set; } = 0;
  39.  
  40. /// <summary>
  41. /// 物体背包容量
  42. /// </summary>
  43. public int Capacity { get; private set; } = 0;
  44.  
  45. /// <summary>
  46. /// 物体插槽
  47. /// </summary>
  48. public T[] ItemSlot { get; private set; }
  49.  
  50. /// <summary>
  51. /// 修改物体背包容量
  52. /// </summary>
  53. public void SetCapacity(int capacity)
  54. {
  55. if (capacity < 0)
  56. {
  57. capacity = 0;
  58. }
  59. if (ItemSlot == null)
  60. {
  61. ItemSlot = new T[capacity];
  62. }
  63. else if (capacity == Capacity)
  64. {
  65. return;
  66. }
  67. else if (ItemSlot.Length > capacity) //删减格子
  68. {
  69. var newArray = new T[capacity];
  70. for (var i = 0; i < ItemSlot.Length; i++)
  71. {
  72. var packageItem = ItemSlot[i];
  73. if (i < capacity)
  74. {
  75. newArray[i] = packageItem;
  76. }
  77. else if (packageItem != null) //溢出的item
  78. {
  79. packageItem.OnOverflowItem();
  80. packageItem.Master = null;
  81. packageItem.PackageIndex = -1;
  82. }
  83. }
  84.  
  85. ItemSlot = newArray;
  86. }
  87. else //添加格子
  88. {
  89. var newArray = new T[capacity];
  90. for (var i = 0; i < ItemSlot.Length; i++)
  91. {
  92. newArray[i] = ItemSlot[i];
  93. }
  94. ItemSlot = newArray;
  95. }
  96. Capacity = capacity;
  97. }
  98.  
  99. /// <summary>
  100. /// 返回当前物体背包是否是空的
  101. /// </summary>
  102. public bool IsEmpty()
  103. {
  104. for (var i = 0; i < ItemSlot.Length; i++)
  105. {
  106. if (ItemSlot[i] != null)
  107. {
  108. return false;
  109. }
  110. }
  111.  
  112. return true;
  113. }
  114. /// <summary>
  115. /// 返回当前物体背包是否还有空位
  116. /// </summary>
  117. public bool HasVacancy()
  118. {
  119. for (var i = 0; i < ItemSlot.Length; i++)
  120. {
  121. if (ItemSlot[i] == null)
  122. {
  123. return true;
  124. }
  125. }
  126.  
  127. return false;
  128. }
  129.  
  130. /// <summary>
  131. /// 根据索引获取物体
  132. /// </summary>
  133. public T GetItem(int index)
  134. {
  135. if (index < 0 || index >= ItemSlot.Length)
  136. {
  137. return null;
  138. }
  139. return ItemSlot[index];
  140. }
  141.  
  142. /// <summary>
  143. /// 根据物体id查找物体背包中该物体所在的位置, 如果没有, 则返回 -1
  144. /// </summary>
  145. /// <param name="id">物体id</param>
  146. public int FindIndex(string id)
  147. {
  148. for (var i = 0; i < ItemSlot.Length; i++)
  149. {
  150. var item = ItemSlot[i];
  151. if (item != null && item.ActivityBase.Id == id)
  152. {
  153. return i;
  154. }
  155. }
  156. return -1;
  157. }
  158.  
  159. /// <summary>
  160. /// 通过回调函数查询物体在物体背包中的位置, 如果没有, 则返回 -1
  161. /// </summary>
  162. public int FindIndex(Func<T, int, bool> handler)
  163. {
  164. for (var i = 0; i < ItemSlot.Length; i++)
  165. {
  166. var item = ItemSlot[i];
  167. if (item != null && handler(item, i))
  168. {
  169. return i;
  170. }
  171. }
  172. return -1;
  173. }
  174.  
  175. /// <summary>
  176. /// 遍历所有物体
  177. /// </summary>
  178. public void ForEach(Action<T, int> handler)
  179. {
  180. for (var i = 0; i < ItemSlot.Length; i++)
  181. {
  182. var item = ItemSlot[i];
  183. if (item != null)
  184. {
  185. handler(item, i);
  186. }
  187. }
  188. }
  189.  
  190. /// <summary>
  191. /// 从物体背包中移除所有物体, 并返回
  192. /// </summary>
  193. public T[] GetAndClearItem()
  194. {
  195. var items = new List<T>();
  196. for (var i = 0; i < ItemSlot.Length; i++)
  197. {
  198. var item = ItemSlot[i];
  199. if (item != null)
  200. {
  201. //触发移除物体
  202. item.OnRemoveItem();
  203. item.Master = null;
  204. item.PackageIndex = -1;
  205.  
  206. items.Add(item);
  207. ItemSlot[i] = null;
  208. }
  209. }
  210.  
  211. return items.ToArray();
  212. }
  213.  
  214. /// <summary>
  215. /// 拾起物体, 存入物体背包中, 返回存放在物体背包的位置, 如果容不下这个物体, 则会返回 -1
  216. /// </summary>
  217. /// <param name="item">物体对象</param>
  218. /// <param name="exchange">是否立即切换到该物体, 默认 true </param>
  219. public int PickupItem(T item, bool exchange = true)
  220. {
  221. //已经被拾起了
  222. if (item.Master != null)
  223. {
  224. return -1;
  225. }
  226. for (var i = 0; i < ItemSlot.Length; i++)
  227. {
  228. var tempItem = ItemSlot[i];
  229. if (tempItem == null)
  230. {
  231. ItemSlot[i] = item;
  232. item.Master = Master;
  233. item.PackageIndex = i;
  234. item.OnPickUpItem();
  235. if (exchange)
  236. {
  237. ExchangeByIndex(i);
  238. }
  239.  
  240. return i;
  241. }
  242. }
  243. return -1;
  244. }
  245.  
  246. /// <summary>
  247. /// 移除指定位置的物体, 并返回这个物体对象, 如果移除正在使用的这个物体, 则会自动切换到上一个物体
  248. /// </summary>
  249. /// <param name="index">所在物体背包的位置索引</param>
  250. public T RemoveItem(int index)
  251. {
  252. if (index < 0 || index >= ItemSlot.Length)
  253. {
  254. return null;
  255. }
  256. var item = ItemSlot[index];
  257. if (item == null)
  258. {
  259. return null;
  260. }
  261. ItemSlot[index] = null;
  262.  
  263. //如果是当前手持的物体, 就需要调用切换物体操作
  264. if (index == ActiveIndex)
  265. {
  266. //没有其他物体了
  267. if (ExchangePrev(true) == index)
  268. {
  269. ActiveIndex = 0;
  270. ActiveItem = null;
  271. }
  272. }
  273. //移除物体
  274. item.OnRemoveItem();
  275. item.Master = null;
  276. item.PackageIndex = -1;
  277. // item.GetParent().RemoveChild(item);
  278. // item.Remove();
  279. return item;
  280. }
  281.  
  282. /// <summary>
  283. /// 移除指定位置的物体, 并返回这个物体对象, 如果移除正在使用的这个物体, 则会自动切换到上一个物体
  284. /// </summary>
  285. public T RemoveItem(T item)
  286. {
  287. return RemoveItem(IndexOf(item));
  288. }
  289.  
  290. /// <summary>
  291. /// 切换到上一个物体
  292. /// </summary>
  293. public int ExchangePrev()
  294. {
  295. return ExchangePrev(false);
  296. }
  297. private int ExchangePrev(bool removeFlag)
  298. {
  299. var index = ActiveIndex - 1;
  300. do
  301. {
  302. if (index < 0)
  303. {
  304. index = ItemSlot.Length - 1;
  305. }
  306. if (ExchangeByIndex(index, removeFlag))
  307. {
  308. return index;
  309. }
  310. } while (index-- != ActiveIndex);
  311. return -1;
  312. }
  313.  
  314. /// <summary>
  315. /// 切换到下一个物体,
  316. /// </summary>
  317. public int ExchangeNext()
  318. {
  319. var index = ActiveIndex + 1;
  320. do
  321. {
  322. if (index >= ItemSlot.Length)
  323. {
  324. index = 0;
  325. }
  326. if (ExchangeByIndex(index))
  327. {
  328. return index;
  329. }
  330. } while (index++ != ActiveIndex);
  331. return -1;
  332. }
  333.  
  334. /// <summary>
  335. /// 切换到指定索引的物体
  336. /// </summary>
  337. public bool ExchangeByIndex(int index)
  338. {
  339. return ExchangeByIndex(index, false);
  340. }
  341.  
  342. private bool ExchangeByIndex(int index, bool removeFlag)
  343. {
  344. if (index == ActiveIndex && ActiveItem != null) return true;
  345. if (index < 0 || index > ItemSlot.Length) return false;
  346. var item = ItemSlot[index];
  347. if (item == null) return false;
  348.  
  349. //将上一个物体放到背后
  350. if (!removeFlag && ActiveItem != null)
  351. {
  352. //收起物体
  353. ActiveItem.OnConcealItem();
  354. }
  355.  
  356. //切换物体
  357. ActiveItem = item;
  358. ActiveIndex = index;
  359. ActiveItem.OnActiveItem();
  360. return true;
  361. }
  362.  
  363. /// <summary>
  364. /// 返回背包中是否有指定物体
  365. /// </summary>
  366. public bool Contains(T item)
  367. {
  368. if (ItemSlot == null)
  369. {
  370. return false;
  371. }
  372.  
  373. foreach (var packageItem in ItemSlot)
  374. {
  375. if (packageItem == item)
  376. {
  377. return true;
  378. }
  379. }
  380.  
  381. return false;
  382. }
  383.  
  384. /// <summary>
  385. /// 返回指定物体在当前背包中的索引, 如果不在背包中, 则返回 -1
  386. /// </summary>
  387. public int IndexOf(T item)
  388. {
  389. if (ItemSlot == null)
  390. {
  391. return -1;
  392. }
  393.  
  394. for (var i = 0; i < ItemSlot.Length; i++)
  395. {
  396. var packageItem = ItemSlot[i];
  397. if (packageItem == item)
  398. {
  399. return i;
  400. }
  401. }
  402.  
  403. return -1;
  404. }
  405.  
  406. /// <summary>
  407. /// 返回指定 id 的物体在背包中的索引, 如果不在背包中, 则返回 -1
  408. /// </summary>
  409. public int IndexOfByItemId(string itemId)
  410. {
  411. if (ItemSlot == null)
  412. {
  413. return -1;
  414. }
  415.  
  416. for (var i = 0; i < ItemSlot.Length; i++)
  417. {
  418. var packageItem = ItemSlot[i];
  419. if (packageItem != null && packageItem.ActivityBase.Id == itemId)
  420. {
  421. return i;
  422. }
  423. }
  424.  
  425. return -1;
  426. }
  427.  
  428. /// <summary>
  429. /// 获取背包中指定 id 的物体, 如果有多个相同 id 的物体, 则返回第一个匹配的物体
  430. /// </summary>
  431. public T GetItemById(string itemId)
  432. {
  433. if (ItemSlot == null)
  434. {
  435. return null;
  436. }
  437.  
  438. for (var i = 0; i < ItemSlot.Length; i++)
  439. {
  440. var packageItem = ItemSlot[i];
  441. if (packageItem != null && packageItem.ActivityBase.Id == itemId)
  442. {
  443. return packageItem;
  444. }
  445. }
  446.  
  447. return null;
  448. }
  449. public override void OnDestroy()
  450. {
  451. for (var i = 0; i < ItemSlot.Length; i++)
  452. {
  453. var activityObject = ItemSlot[i];
  454. if (activityObject != null)
  455. {
  456. activityObject.Destroy();
  457. ItemSlot[i] = null;
  458. }
  459. }
  460. }
  461. }