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