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