InstanceZone.Terrain.cs 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using CommonLang;
  6. using CommonAI.RTS.Manhattan;
  7. using CommonAI.Zone.Helper;
  8. using CommonAI.RTS;
  9. using CommonLang.Vector;
  10. using CommonAI.Zone.Interface;
  11. using static CommonAI.ZoneServer.JSGModule.MSpaceNodeCache;
  12. using CommonAI.ZoneServer.JSGModule;
  13. namespace CommonAI.Zone.Instance
  14. {
  15. partial class InstanceZone
  16. {
  17. #region COLLIDE
  18. /// <summary>
  19. /// 2个单位是否碰撞
  20. /// </summary>
  21. /// <param name="s"></param>
  22. /// <param name="d"></param>
  23. /// <returns></returns>
  24. public virtual bool TouchObject2(InstanceZoneObject s, InstanceZoneObject d)
  25. {
  26. if (s == d) return false;
  27. float w = s.X - d.X;
  28. float h = s.Y - d.Y;
  29. float r = s.BodyBlockSize + d.BodyBlockSize;
  30. if (w * w + h * h <= r * r)
  31. {
  32. return true;
  33. }
  34. return false;
  35. }
  36. /// <summary>
  37. /// 单位和地图碰撞检测
  38. /// </summary>
  39. /// <param name="o"></param>
  40. /// <returns></returns>
  41. public virtual bool TouchMap(InstanceZoneObject o)
  42. {
  43. return path_finder.TouchMapBlock(
  44. (int)((o.X) / m_TerrainSrc.GridCellW),
  45. (int)((o.Y) / m_TerrainSrc.GridCellH));
  46. }
  47. /// <summary>
  48. /// 单位尝试用心的坐标和地图碰撞
  49. /// </summary>
  50. /// <param name="o"></param>
  51. /// <param name="x"></param>
  52. /// <param name="y"></param>
  53. /// <returns></returns>
  54. public virtual bool TryTouchMap(InstanceZoneObject o, float x, float y)
  55. {
  56. return path_finder.TouchMapBlock(
  57. (int)((x) / m_TerrainSrc.GridCellW),
  58. (int)((y) / m_TerrainSrc.GridCellH));
  59. }
  60. /// <summary>
  61. /// 单位尝试移动,并自动对齐到地图边界
  62. /// </summary>
  63. /// <param name="o"></param>
  64. /// <param name="x"></param>
  65. /// <param name="y"></param>
  66. /// <param name="dx"></param>
  67. /// <param name="dy"></param>
  68. /// <returns></returns>
  69. public virtual CommonAI.RTS.Manhattan.AstarManhattan.TryMoveToMapBorderResult TryMoveToMapBorder(InstanceZoneObject o, ref float x, ref float y, float dx, float dy)
  70. {
  71. return path_finder.TryMoveToMapBorder(ref x, ref y, dx, dy);
  72. }
  73. public virtual CommonAI.RTS.Manhattan.AstarManhattan.TryMoveToMapBorderResult TryMoveToMapBorder(InstanceZoneObject o, ref Vector2 pos, float dx, float dy)
  74. {
  75. float x = pos.X;
  76. float y = pos.Y;
  77. var result = path_finder.TryMoveToMapBorder(ref x, ref y, dx, dy);
  78. pos.SetX(x);
  79. pos.SetY(y);
  80. return result;
  81. }
  82. /// <summary>
  83. /// 单位视线是否和地图相交
  84. /// </summary>
  85. /// <param name="src"></param>
  86. /// <param name="sx"></param>
  87. /// <param name="sy"></param>
  88. /// <param name="dx"></param>
  89. /// <param name="dy"></param>
  90. /// <returns></returns>
  91. public virtual bool RaycastMap(InstanceUnit src, float sx, float sy, float dx, float dy)
  92. {
  93. if (CMath.includeRectPoint(0, 0, m_TerrainSrc.TotalWidth, m_TerrainSrc.TotalHeight, sx, sy) &&
  94. CMath.includeRectPoint(0, 0, m_TerrainSrc.TotalWidth, m_TerrainSrc.TotalHeight, dx, dy))
  95. {
  96. return path_finder.TouchMapLine(sx, sy, dx, dy);
  97. }
  98. return false;
  99. }
  100. public bool intersectMapByBlock(int bx, int by)
  101. {
  102. return path_finder.TouchMapBlock(bx, by);
  103. }
  104. public bool intersectMapByPos(float x, float y)
  105. {
  106. return path_finder.TouchMapBlock(
  107. (int)((x) / m_TerrainSrc.GridCellW),
  108. (int)((y) / m_TerrainSrc.GridCellH));
  109. }
  110. /// <summary>
  111. /// 当前单位是否和建筑碰撞
  112. /// </summary>
  113. /// <param name="a"></param>
  114. /// <returns></returns>
  115. public InstanceZoneObject intersectNearStaticBlockable(InstanceZoneObject a)
  116. {
  117. InstanceZoneObject ret = null;
  118. ForEachNearObjects(a.X, a.Y, (InstanceZoneObject o, ref bool cancel) =>
  119. {
  120. if (o.IsStaticBlockable && o.IntersectObj && TouchObject2(a, o))
  121. {
  122. ret = o;
  123. cancel = true;
  124. }
  125. });
  126. return ret;
  127. }
  128. /// <summary>
  129. /// 包含身体高度和建筑碰撞
  130. /// </summary>
  131. /// <param name="a"></param>
  132. /// <returns></returns>
  133. public InstanceZoneObject intersectNearStaticBlockableZ(InstanceZoneObject a)
  134. {
  135. InstanceZoneObject ret = null;
  136. ForEachNearObjects(a.X, a.Y, (InstanceZoneObject o, ref bool cancel) =>
  137. {
  138. if (o.IsStaticBlockable && o.IntersectObj)
  139. {
  140. if (CMath.IsIntersect2(a.Z, a.BodyHeight, o.Z, o.BodyHeight) && TouchObject2(a, o))
  141. {
  142. ret = o;
  143. cancel = true;
  144. }
  145. }
  146. });
  147. return ret;
  148. }
  149. /// <summary>
  150. /// 当前单位是否和单位碰撞
  151. /// </summary>
  152. /// <param name="a"></param>
  153. /// <returns></returns>
  154. public InstanceZoneObject intersectNearUnit(InstanceZoneObject a)
  155. {
  156. InstanceZoneObject ret = null;
  157. ForEachNearObjects(a.X, a.Y, (InstanceZoneObject o, ref bool cancel) =>
  158. {
  159. if ((o.IntersectObj) && TouchObject2(a, o))
  160. {
  161. ret = o;
  162. cancel = true;
  163. }
  164. });
  165. return ret;
  166. }
  167. #endregion
  168. //-------------------------------------------------------------------------------------------------------//
  169. #region MANHATTAN_MAP
  170. private ZoneManhattanMap path_terrain_data;
  171. private AstarManhattan path_finder;
  172. private ManhattanMapAreaGenerator path_terrain_area_gen;
  173. protected virtual void InitTerrain(ZoneEditor.SceneData data, int spaceDiv, out ZoneManhattanMap terrain_data, out AstarManhattan path_finder, out ManhattanMapAreaGenerator area_gen)
  174. {
  175. terrain_data = new ZoneManhattanMap(m_TerrainSrc.Clone() as ZoneInfo, Templates.TerrainDefinition);
  176. path_finder = new AstarManhattan(data.TemplateID, terrain_data, true, spaceDiv);
  177. area_gen = new ManhattanMapAreaGenerator(terrain_data.Data);
  178. }
  179. protected virtual void DisposeTerrain()
  180. {
  181. this.path_finder.Dispose();
  182. this.path_terrain_data.Dispose();
  183. this.path_finder = null;
  184. this.path_terrain_data = null;
  185. this.path_terrain_area_gen = null;
  186. this.sync_pos_list.Clear();
  187. }
  188. public AstarManhattan PathFinder
  189. {
  190. get { return path_finder; }
  191. }
  192. public ZoneManhattanMap PathFinderTerrain
  193. {
  194. get { return path_terrain_data; }
  195. }
  196. public ManhattanMapAreaGenerator TerrainAreaGenerator
  197. {
  198. get { return path_terrain_area_gen; }
  199. }
  200. public AstarManhattan.MWayPoint findPath(float sx, float sy, float dx, float dy)
  201. {
  202. AstarManhattan.MWayPoint ret;
  203. var result = path_finder.findPath(sx, sy, dx, dy, out ret);
  204. switch (result)
  205. {
  206. case AstarManhattan.FindPathResult.Cross:
  207. case AstarManhattan.FindPathResult.Destination:
  208. return ret;
  209. default:
  210. return null;
  211. }
  212. }
  213. public ZoneArea GetArea(float x, float y)
  214. {
  215. var node = PathFinder.GetMapNodeByPos(x, y) as ZoneMapNode;
  216. if (node != null)
  217. {
  218. return node.ServerArea;
  219. }
  220. return null;
  221. }
  222. public ZoneArea GetAreaByBlock(int bx, int by)
  223. {
  224. var node = PathFinder.GetMapNode(bx, by) as ZoneMapNode;
  225. if (node != null)
  226. {
  227. return node.ServerArea;
  228. }
  229. return null;
  230. }
  231. #endregion
  232. //-------------------------------------------------------------------------------------------------------//
  233. #region SPACE_DIVISION
  234. public int SpaceXCount { get { return mSpaceDiv.SpaceXCount; } }
  235. public int SpaceYCount { get { return mSpaceDiv.SpaceYCount; } }
  236. /// <summary>
  237. /// 按坐标取分割块
  238. /// </summary>
  239. /// <param name="x"></param>
  240. /// <param name="y"></param>
  241. /// <returns></returns>
  242. public SpaceDivision.SpaceCellNode GetSpaceCellNode(float x, float y)
  243. {
  244. return mSpaceDiv.GetSpaceCellNode(x, y);
  245. }
  246. /// <summary>
  247. /// 按格取分割块
  248. /// </summary>
  249. /// <param name="bx"></param>
  250. /// <param name="by"></param>
  251. /// <returns></returns>
  252. public SpaceDivision.SpaceCellNode GetSpaceCellNodeByBlock(int bx, int by)
  253. {
  254. return mSpaceDiv.GetSpaceCellNodeByBlock(bx, by);
  255. }
  256. public List<SpaceDivision.SpaceCellNode> ListSpaceCellNodes()
  257. {
  258. return mSpaceDiv.ListSpaceCellNodes();
  259. }
  260. /// <summary>
  261. /// 刷新空间分割位置为有改变
  262. /// </summary>
  263. /// <param name="obj"></param>
  264. internal void nearChange(InstanceZoneObject obj)
  265. {
  266. mSpaceDiv.NearChange(obj.mCurCellNode);
  267. }
  268. /// <summary>
  269. /// 清除空间位置
  270. /// </summary>
  271. /// <param name="obj"></param>
  272. internal void clearSpace(InstanceZoneObject obj)
  273. {
  274. mSpaceDiv.ClearSpace(obj.mCurCellNode);
  275. }
  276. internal bool swapSpace(InstanceZoneObject obj, bool nearchange)
  277. {
  278. SpaceDivision.SpaceCellNode old_cell = obj.CurrentSpaceCellNode;
  279. if (mSpaceDiv.SwapSpace(obj.mCurCellNode, obj.X, obj.Y, nearchange))
  280. {
  281. if (mOnObjectSpaceChanged != null)
  282. {
  283. SpaceDivision.SpaceCellNode new_cell = obj.CurrentSpaceCellNode;
  284. mOnObjectSpaceChanged.Invoke(this, obj, old_cell, new_cell);
  285. }
  286. return true;
  287. }
  288. return false;
  289. }
  290. internal void swapArea(InstanceZoneObject obj, ZoneArea o, ZoneArea n)
  291. {
  292. if (o != null && o.Enable) { o.do_onUnitLeave(obj); }
  293. if (n != null && n.Enable) { n.do_onUnitEnter(obj); }
  294. if (mOnObjectAreaChanged != null)
  295. {
  296. mOnObjectAreaChanged.Invoke(this, obj, o, n);
  297. }
  298. }
  299. /// <summary>
  300. /// 判断是否附近有位置变化
  301. /// </summary>
  302. /// <param name="x"></param>
  303. /// <param name="y"></param>
  304. /// <returns></returns>
  305. public bool IsNearChanged(float x, float y)
  306. {
  307. return mSpaceDiv.IsNearChanged(x, y);
  308. }
  309. public bool IsNearChanged(float x, float y, float r)
  310. {
  311. return mSpaceDiv.IsNearChanged(x, y, r);
  312. }
  313. public bool IsNearChanged(float x1, float y1, float x2, float y2)
  314. {
  315. return mSpaceDiv.IsNearChanged(x1, y1, x2, y2);
  316. }
  317. /// <summary>
  318. /// 获取当前坐标附近的所有单位容量
  319. /// </summary>
  320. /// <param name="x"></param>
  321. /// <param name="y"></param>
  322. /// <returns></returns>
  323. public int getNearObjectsCapacity(float x, float y)
  324. {
  325. return mSpaceDiv.GetNearObjectsCapacity(x, y);
  326. }
  327. /**
  328. * 以目标点为中心,circle为半径,找可行走区域。找到了返回true;找不到返回false;
  329. * sx, sy 起始位置
  330. * dstx, dsty 目标位置
  331. * circle 搜寻半径
  332. * outx, outy修改后的目标点
  333. */
  334. public bool GetNearWay(float sx, float sy, float dstx, float dsty, float circle, ref float outx, ref float outy)
  335. {
  336. //以目标点为中心,一圈一圈向外查找可行走的块
  337. //起始点与终点连线方向上的点优先
  338. int W = Terrain.GridCellW;
  339. int H = Terrain.GridCellH;
  340. float squCircle = circle * circle;
  341. int dr = ((int)circle) / W;
  342. float vx = sx > dstx ? 1 : -1;
  343. float vy = sy > dsty ? 1 : -1;
  344. bool f = true;
  345. for (int r = 1; r <= dr; r++)
  346. {
  347. for (int v = 1; v <= 4; v++)
  348. {
  349. float xx = dstx + W * r * vx;
  350. float yy = dsty + H * r * vy;
  351. for (int dx = f ? 0 : 1; f ? dx <= r : dx < r; dx++)
  352. {
  353. float x = dstx + dx * W * vx;
  354. if (MathVector.getDistanceSquare(x, yy, dstx, dsty) < squCircle)
  355. {
  356. if (!path_finder.TouchMapBlock(((int)x) / W, ((int)yy) / H) && findPath(sx, sy, x, yy) != null)
  357. {
  358. outx = x;
  359. outy = yy;
  360. return true;
  361. }
  362. }
  363. }
  364. for (int dy = f ? 1 : 0; f ? dy < r : dy <= r; dy++)
  365. {
  366. float y = dsty + dy * H * vy;
  367. if (MathVector.getDistanceSquare(xx, y, dstx, dsty) < squCircle)
  368. {
  369. if (!path_finder.TouchMapBlock(((int)xx) / W, ((int)y) / H) && findPath(sx, sy, xx, y) != null)
  370. {
  371. outx = xx;
  372. outy = y;
  373. return true;
  374. }
  375. }
  376. }
  377. if (f) vy *= -1;
  378. else vx *= -1;
  379. f = !f;
  380. }
  381. }
  382. outx = -1;
  383. outy = -1;
  384. return false;
  385. }
  386. //---------------------------------------------------------------------------------------------------------------
  387. #region _Deprecated_
  388. /// <summary>
  389. /// 获取当前坐标附近的所有单位
  390. /// </summary>
  391. /// <param name="x"></param>
  392. /// <param name="y"></param>
  393. /// <returns></returns>
  394. [Obsolete("use {@link #ForEachNearObjects} for best performance!")]
  395. public List<InstanceZoneObject> getNearObjects(float x, float y)
  396. {
  397. List<InstanceZoneObject> list = new List<InstanceZoneObject>(getNearObjectsCapacity(x, y));
  398. getNearObjects(x, y, list);
  399. return list;
  400. }
  401. /// <summary>
  402. /// 获取当前圆形坐标附近所有单位
  403. /// </summary>
  404. /// <param name="x"></param>
  405. /// <param name="y"></param>
  406. /// <param name="r"></param>
  407. /// <returns></returns>
  408. [Obsolete("use {@link #ForEachNearObjects} for best performance!")]
  409. public List<InstanceZoneObject> getNearObjects(float x, float y, float r)
  410. {
  411. List<InstanceZoneObject> list = new List<InstanceZoneObject>(getNearObjectsCapacity(x, y));
  412. getNearObjects(x, y, r, list);
  413. return list;
  414. }
  415. /// <summary>
  416. /// 获取当前矩形附近所有单位
  417. /// </summary>
  418. /// <param name="x1"></param>
  419. /// <param name="y1"></param>
  420. /// <param name="x2"></param>
  421. /// <param name="y2"></param>
  422. /// <returns></returns>
  423. [Obsolete("use {@link #ForEachNearObjectsRect} for best performance!")]
  424. public List<InstanceZoneObject> getNearObjectsRect(float x1, float y1, float x2, float y2)
  425. {
  426. List<InstanceZoneObject> list = new List<InstanceZoneObject>();
  427. getNearObjectsRect(x1, y1, x2, y2, list);
  428. return list;
  429. }
  430. //----------------------------------------------------------------------------------------------------------------------------
  431. /// <summary>
  432. /// 获取当前坐标附近的所有单位
  433. /// </summary>
  434. /// <param name="x"></param>
  435. /// <param name="y"></param>
  436. /// <param name="list"></param>
  437. [Obsolete]
  438. private void getNearObjects(float x, float y, List<InstanceZoneObject> list)
  439. {
  440. SpaceDivision.SpaceCellNode node = mSpaceDiv.GetSpaceCellNode(x, y);
  441. if (node != null)
  442. {
  443. list.AddRange(node.AsChildList<InstanceZoneObject>());
  444. for (int i = node.nears.Count - 1; i >= 0; --i)
  445. {
  446. list.AddRange(node.nears[i].AsChildList<InstanceZoneObject>());
  447. }
  448. }
  449. }
  450. /// <summary>
  451. /// 获取当前坐标附近的所有单位
  452. /// </summary>
  453. /// <param name="x"></param>
  454. /// <param name="y"></param>
  455. /// <param name="r"></param>
  456. /// <param name="list"></param>
  457. [Obsolete]
  458. private void getNearObjects(float x, float y, float r, List<InstanceZoneObject> list)
  459. {
  460. if (r < mSpaceDiv.SpaceCellW && r < mSpaceDiv.SpaceCellH)
  461. {
  462. SpaceDivision.SpaceCellNode node = mSpaceDiv.GetSpaceCellNode(x, y);
  463. if (node != null)
  464. {
  465. list.AddRange(node.AsChildList<InstanceZoneObject>());
  466. for (int i = node.nears.Count - 1; i >= 0; --i)
  467. {
  468. list.AddRange(node.nears[i].AsChildList<InstanceZoneObject>());
  469. }
  470. }
  471. }
  472. else
  473. {
  474. int cx1 = ((int)((x - r) / mSpaceDiv.SpaceCellW)) - 1;
  475. int cy1 = ((int)((y - r) / mSpaceDiv.SpaceCellH)) - 1;
  476. int cx2 = ((int)((x + r) / mSpaceDiv.SpaceCellW)) + 1;
  477. int cy2 = ((int)((y + r) / mSpaceDiv.SpaceCellH)) + 1;
  478. cx1 = Math.Max(cx1, 0);
  479. cy1 = Math.Max(cy1, 0);
  480. cx2 = Math.Min(cx2, mSpaceDiv.SpaceXCount - 1);
  481. cy2 = Math.Min(cy2, mSpaceDiv.SpaceYCount - 1);
  482. for (int cx = cx1; cx <= cx2; ++cx)
  483. {
  484. for (int cy = cy1; cy <= cy2; ++cy)
  485. {
  486. SpaceDivision.SpaceCellNode cn = mSpaceDiv.GetSpaceCellNodeByBlock(cx, cy);
  487. list.AddRange(cn.AsChildList<InstanceZoneObject>());
  488. }
  489. }
  490. }
  491. }
  492. /// <summary>
  493. /// 获取当前坐标附近的所有单位
  494. /// </summary>
  495. /// <param name="x1"></param>
  496. /// <param name="y1"></param>
  497. /// <param name="x2"></param>
  498. /// <param name="y2"></param>
  499. /// <param name="list"></param>
  500. [Obsolete]
  501. private void getNearObjectsRect(float x1, float y1, float x2, float y2, List<InstanceZoneObject> list)
  502. {
  503. int cx1 = ((int)((Math.Min(x1, x2)) / mSpaceDiv.SpaceCellW)) - 1;
  504. int cy1 = ((int)((Math.Min(y1, y2)) / mSpaceDiv.SpaceCellH)) - 1;
  505. int cx2 = ((int)((Math.Max(x1, x2)) / mSpaceDiv.SpaceCellW)) + 1;
  506. int cy2 = ((int)((Math.Max(y1, y2)) / mSpaceDiv.SpaceCellH)) + 1;
  507. cx1 = Math.Max(cx1, 0);
  508. cy1 = Math.Max(cy1, 0);
  509. cx2 = Math.Min(cx2, mSpaceDiv.SpaceXCount - 1);
  510. cy2 = Math.Min(cy2, mSpaceDiv.SpaceYCount - 1);
  511. for (int cx = cx1; cx <= cx2; ++cx)
  512. {
  513. for (int cy = cy1; cy <= cy2; ++cy)
  514. {
  515. SpaceDivision.SpaceCellNode cn = mSpaceDiv.GetSpaceCellNodeByBlock(cx, cy);
  516. list.AddRange(cn.AsChildList<InstanceZoneObject>());
  517. }
  518. }
  519. }
  520. #endregion
  521. //----------------------------------------------------------------------------------------------------------------------------
  522. /// <summary>
  523. /// 获取当前坐标附近的所有单位
  524. /// </summary>
  525. /// <param name="x"></param>
  526. /// <param name="y"></param>
  527. /// <param name="indexer"></param>
  528. /// <returns>is cancel</returns>
  529. public bool ForEachNearObjects<T>(float x, float y, SpaceDivision.ObjectForEachAction<T> indexer) where T : InstanceZoneObject
  530. {
  531. return mSpaceDiv.ForEachNearObjects(x, y, indexer);
  532. }
  533. /// <summary>
  534. /// 获取当前坐标附近的所有单位
  535. /// </summary>
  536. /// <param name="x"></param>
  537. /// <param name="y"></param>
  538. /// <param name="r"></param>
  539. /// <param name="indexer"></param>
  540. /// <returns>is cancel</returns>
  541. public bool ForEachNearObjects<T>(float x, float y, float r, SpaceDivision.ObjectForEachAction<T> indexer) where T : InstanceZoneObject
  542. {
  543. return mSpaceDiv.ForEachNearObjects(x, y, r, indexer);
  544. }
  545. /// <summary>
  546. /// 获取当前坐标附近的所有单位
  547. /// </summary>
  548. /// <param name="x1"></param>
  549. /// <param name="y1"></param>
  550. /// <param name="x2"></param>
  551. /// <param name="y2"></param>
  552. /// <param name="indexer"></param>
  553. /// <returns>is cancel</returns>
  554. public bool ForEachNearObjectsRect<T>(float x1, float y1, float x2, float y2, SpaceDivision.ObjectForEachAction<T> indexer) where T : InstanceZoneObject
  555. {
  556. return mSpaceDiv.ForEachNearObjectsRect(x1, y1, x2, y2, indexer);
  557. }
  558. //----------------------------------------------------------------------------------------------------------------------------
  559. /// <summary>
  560. /// 获取【矩形】范围内的所有单位
  561. /// </summary>
  562. /// <typeparam name="T"></typeparam>
  563. /// <param name="func"></param>
  564. /// <param name="x1"></param>
  565. /// <param name="y1"></param>
  566. /// <param name="x2"></param>
  567. /// <param name="y2"></param>
  568. /// <param name="list"></param>
  569. /// <param name="aoi"></param>
  570. /// <returns></returns>
  571. public int getObjectsRectRange<T>(
  572. Collider.ObjectBodyTouchRect func,
  573. float x1, float y1,
  574. float x2, float y2,
  575. List<T> list, ObjectAoiStatus aoi) where T : InstanceZoneObject
  576. {
  577. int count = 0;
  578. ForEachNearObjectsRect<T>(x1, y1, x2, y2, (T o, ref bool cancel) =>
  579. {
  580. if (o.AoiStatus == aoi && func(o, x1, y1, x2, y2))
  581. {
  582. if (list != null) list.Add(o as T);
  583. count++;
  584. }
  585. });
  586. return count;
  587. }
  588. [Obsolete]
  589. public List<T> getObjectsRectRange<T>(
  590. Collider.ObjectBodyTouchRect func,
  591. float x1, float y1,
  592. float x2, float y2, ObjectAoiStatus aoi) where T : InstanceZoneObject
  593. {
  594. List<T> ret = new List<T>(getNearObjectsCapacity(x1, y1));
  595. getObjectsRectRange<T>(func, x1, y1, x2, y2, ret, aoi);
  596. return ret;
  597. }
  598. public int getObjectsCountRectRange<T>(
  599. Collider.ObjectBodyTouchRect func,
  600. float x1, float y1,
  601. float x2, float y2, ObjectAoiStatus aoi) where T : InstanceZoneObject
  602. {
  603. return getObjectsRectRange<T>(func, x1, y1, x2, y2, null, aoi);
  604. }
  605. /// <summary>
  606. /// 获取【圆形】范围内的所有单位
  607. /// </summary>
  608. /// <typeparam name="T"></typeparam>
  609. /// <param name="func"></param>
  610. /// <param name="x"></param>
  611. /// <param name="y"></param>
  612. /// <param name="r"></param>
  613. /// <param name="list"></param>
  614. /// <param name="aoi"></param>
  615. /// <returns></returns>
  616. public int getObjectsRoundRange<T>(
  617. Collider.ObjectBodyTouchRound func,
  618. float x, float y, float r,
  619. List<T> list, ObjectAoiStatus aoi) where T : InstanceZoneObject
  620. {
  621. int count = 0;
  622. ForEachNearObjects(x, y, r, (T o, ref bool cancel) =>
  623. {
  624. if (o.AoiStatus == aoi && func(o, x, y, r))
  625. {
  626. if (list != null) list.Add(o as T);
  627. count++;
  628. }
  629. });
  630. return count;
  631. }
  632. //单位是否在范围内
  633. public InstanceUnit isUnitInRoundRange<T>(int unitID, float x, float y, float r, ObjectAoiStatus aoi) where T : InstanceUnit
  634. {
  635. InstanceUnit unit = null;
  636. ForEachNearObjects(x, y, r, (T o, ref bool cancel) =>
  637. {
  638. if (o.AoiStatus == aoi && o.Info.TemplateID == unitID)
  639. {
  640. cancel = true;
  641. unit = o;
  642. }
  643. });
  644. return unit;
  645. }
  646. [Obsolete]
  647. public List<T> getObjectsRoundRange<T>(
  648. Collider.ObjectBodyTouchRound func,
  649. float x, float y, float r, ObjectAoiStatus aoi) where T : InstanceZoneObject
  650. {
  651. List<T> ret = new List<T>(getNearObjectsCapacity(x, y));
  652. getObjectsRoundRange<T>(func, x, y, r, ret, aoi);
  653. return ret;
  654. }
  655. public int getObjectsCountRoundRange<T>(
  656. Collider.ObjectBodyTouchRound func,
  657. float x, float y, float r, ObjectAoiStatus aoi) where T : InstanceZoneObject
  658. {
  659. return getObjectsRoundRange<T>(func, x, y, r, null, aoi);
  660. }
  661. /// <summary>
  662. /// 获取【扇形】范围内的所有单位,扇形范围为【弧度】
  663. /// </summary>
  664. /// <typeparam name="T"></typeparam>
  665. /// <param name="func"></param>
  666. /// <param name="x"></param>
  667. /// <param name="y"></param>
  668. /// <param name="distance"></param>
  669. /// <param name="startAngle"></param>
  670. /// <param name="endAngle"></param>
  671. /// <param name="list"></param>
  672. /// <param name="aoi"></param>
  673. /// <returns></returns>
  674. public int getObjectsFanRange<T>(
  675. Collider.ObjectBodyTouchFan func,
  676. float x, float y, float distance,
  677. float startAngle, float endAngle,
  678. List<T> list, ObjectAoiStatus aoi) where T : InstanceZoneObject
  679. {
  680. int count = 0;
  681. ForEachNearObjects(x, y, distance, (T o, ref bool cancel) =>
  682. {
  683. if (o.AoiStatus == aoi && func(o, x, y, distance, startAngle, endAngle))
  684. {
  685. if (list != null) list.Add(o as T);
  686. count++;
  687. }
  688. });
  689. return count;
  690. }
  691. [Obsolete]
  692. public List<T> getObjectsFanRange<T>(
  693. Collider.ObjectBodyTouchFan func,
  694. float x, float y, float distance,
  695. float startAngle, float endAngle, ObjectAoiStatus aoi) where T : InstanceZoneObject
  696. {
  697. List<T> ret = new List<T>(getNearObjectsCapacity(x, y));
  698. getObjectsFanRange<T>(func, x, y, distance, startAngle, endAngle, ret, aoi);
  699. return ret;
  700. }
  701. /// <summary>
  702. /// 获取【直线】穿过范围内的所有单位(粗线段)
  703. /// </summary>
  704. /// <typeparam name="T"></typeparam>
  705. /// <param name="func"></param>
  706. /// <param name="x1"></param>
  707. /// <param name="y1"></param>
  708. /// <param name="x2"></param>
  709. /// <param name="y2"></param>
  710. /// <param name="line_r"></param>
  711. /// <param name="list"></param>
  712. /// <param name="aoi"></param>
  713. /// <returns></returns>
  714. public int getObjectsRectLineRange<T>(
  715. Collider.ObjectBodyTouchRectLine func,
  716. float x1, float y1, float x2, float y2, float line_r,
  717. List<T> list, ObjectAoiStatus aoi) where T : InstanceZoneObject
  718. {
  719. int count = 0;
  720. ForEachNearObjectsRect(x1, y1, x2, y2, (T o, ref bool cancel) =>
  721. {
  722. if (o.AoiStatus == aoi && func(o, x1, y1, x2, y2, line_r))
  723. {
  724. if (list != null) list.Add(o as T);
  725. count++;
  726. }
  727. });
  728. return count;
  729. }
  730. [Obsolete]
  731. public List<T> getObjectsRectLineRange<T>(
  732. Collider.ObjectBodyTouchRectLine func,
  733. float x1, float y1, float x2, float y2, float line_r, ObjectAoiStatus aoi) where T : InstanceZoneObject
  734. {
  735. List<T> ret = new List<T>(getNearObjectsCapacity(x1, y1));
  736. getObjectsRectLineRange(func, x1, y1, x2, y2, line_r, ret, aoi);
  737. return ret;
  738. }
  739. /// <summary>
  740. /// 单位【运动轨迹】从A点移动到B点经过的碰撞
  741. /// </summary>
  742. /// <typeparam name="T"></typeparam>
  743. /// <param name="func"></param>
  744. /// <param name="sx"></param>
  745. /// <param name="sy"></param>
  746. /// <param name="dx"></param>
  747. /// <param name="dy"></param>
  748. /// <param name="line_r"></param>
  749. /// <param name="list"></param>
  750. /// <param name="aoi"></param>
  751. /// <returns></returns>
  752. public int getObjectsRoundLineRange<T>(
  753. Collider.ObjectBodyTouchRoundLine func,
  754. float sx, float sy, float dx, float dy, float line_r,
  755. List<T> list , ObjectAoiStatus aoi) where T : InstanceZoneObject
  756. {
  757. int count = 0;
  758. ForEachNearObjectsRect(sx, sy, dx, dy, (T o, ref bool cancel) =>
  759. {
  760. if (aoi == o.AoiStatus && func(o, sx, sy, dx, dy, line_r))
  761. {
  762. if (list != null) list.Add(o as T);
  763. count++;
  764. }
  765. });
  766. return count;
  767. }
  768. [Obsolete]
  769. public List<T> getObjectsRoundLineRange<T>(
  770. Collider.ObjectBodyTouchRoundLine func,
  771. float sx, float sy, float dx, float dy, float line_r, ObjectAoiStatus aoi) where T : InstanceZoneObject
  772. {
  773. List<T> ret = new List<T>(getNearObjectsCapacity(sx, sy));
  774. getObjectsRoundLineRange<T>(func, sx, sy, dx, dy, line_r, ret , aoi);
  775. return ret;
  776. }
  777. #endregion
  778. //-------------------------------------------------------------------------------------------------------//
  779. protected List<SyncPosEvent.UnitPos> m_UnitsPos = new List<SyncPosEvent.UnitPos>();
  780. protected List<SyncPosEvent.UnitState> m_UnitsStates = new List<SyncPosEvent.UnitState>();
  781. #region SYNC_POS
  782. /// <summary>
  783. /// 获得场景当前所有装饰物状态
  784. /// </summary>
  785. /// <returns></returns>
  786. public ZoneClient.SyncFlagsEvent GetSyncFlagsEvent()
  787. {
  788. var ret = new ZoneClient.SyncFlagsEvent();
  789. foreach (InstanceFlag flag in mFlags.Values)
  790. {
  791. if (flag is ZoneDecoration)
  792. {
  793. ZoneDecoration d = flag as ZoneDecoration;
  794. if (!d.Enable)
  795. {
  796. ret.ClosedDecorations.Add(d.Name);
  797. }
  798. }
  799. if (flag.Tag != flag.SrcTag)
  800. {
  801. ret.ChangedTags.Add(flag.Name, flag.Tag);
  802. }
  803. }
  804. return ret;
  805. }
  806. /// <summary>
  807. /// 获得所有单位同步信息,一般在进入场景时同步
  808. /// </summary>
  809. /// <param name="exclude"></param>
  810. /// <returns></returns>
  811. public ZoneClient.SyncObjectsEvent GetSyncUnitsEvent(InstanceUnit exclude = null)
  812. {
  813. var objs = mObjects.Objects;
  814. ZoneClient.SyncObjectsEvent ret = new ZoneClient.SyncObjectsEvent(mObjects.ObjectsCount);
  815. foreach (InstanceZoneObject o in objs)
  816. {
  817. if ((exclude == null || o != exclude) && o.ClientVisible)
  818. {
  819. var sync = o.GenSyncInfo(true);
  820. ret.Objects.Add(sync);
  821. }
  822. }
  823. return ret;
  824. }
  825. /// <summary>
  826. /// 获得半径内所有单位同步信息
  827. /// </summary>
  828. /// <param name="x"></param>
  829. /// <param name="y"></param>
  830. /// <param name="r"></param>
  831. /// <param name="exclude"></param>
  832. /// <returns></returns>
  833. public ZoneClient.SyncObjectsEvent GetSyncUnitsEventInRange(float x, float y, float r, InstanceUnit exclude = null)
  834. {
  835. ZoneClient.SyncObjectsEvent ret = new ZoneClient.SyncObjectsEvent(getNearObjectsCapacity(x, y));
  836. ForEachNearObjects(x, y, r, (InstanceZoneObject o, ref bool cancel) =>
  837. {
  838. if ((exclude == null || o != exclude) && o.ClientVisible)
  839. {
  840. if (Collider.Object_Pos_IncludeInRound(o, x, y, r))
  841. {
  842. var sync = o.GenSyncInfo(true);
  843. ret.Objects.Add(sync);
  844. }
  845. }
  846. });
  847. return ret;
  848. }
  849. /// <summary>
  850. /// 获得空间分割块所有单位同步信息
  851. /// </summary>
  852. /// <param name="bx"></param>
  853. /// <param name="by"></param>
  854. /// <param name="exclude"></param>
  855. /// <returns></returns>
  856. public ZoneClient.SyncObjectsEvent GetSyncUnitsEventBySpace(int bx, int by, InstanceUnit exclude = null)
  857. {
  858. SpaceDivision.SpaceCellNode space = GetSpaceCellNodeByBlock(bx, by);
  859. if (space != null)
  860. {
  861. ZoneClient.SyncObjectsEvent ret = new ZoneClient.SyncObjectsEvent(space.Count);
  862. space.ForEach((InstanceZoneObject o, ref bool cancel) =>
  863. {
  864. if ((exclude == null || o != exclude) && o.ClientVisible)
  865. {
  866. var sync = o.GenSyncInfo(true);
  867. ret.Objects.Add(sync);
  868. }
  869. });
  870. return ret;
  871. }
  872. return null;
  873. }
  874. public ZoneClient.SyncObjectsEvent GetSyncObjectsEvent(ICollection<InstanceZoneObject> objs)
  875. {
  876. ZoneClient.SyncObjectsEvent ret = new ZoneClient.SyncObjectsEvent(objs.Count);
  877. foreach (InstanceZoneObject o in objs)
  878. {
  879. if (o.ClientVisible)
  880. {
  881. var sync = o.GenSyncInfo(true);
  882. ret.Objects.Add(sync);
  883. }
  884. }
  885. return ret;
  886. }
  887. /// <summary>
  888. /// 得到半径范围内的所有移动信息
  889. /// </summary>
  890. /// <param name="x"></param>
  891. /// <param name="y"></param>
  892. /// <param name="range"></param>
  893. /// <returns></returns>
  894. public SyncPosEvent GetSyncPosEventInRange(float x, float y, float range)
  895. {
  896. using (var units = ListObjectPool<SyncPosEvent.UnitPos>.AllocAutoRelease())
  897. using (var units_st = ListObjectPool<SyncPosEvent.UnitState>.AllocAutoRelease())
  898. {
  899. SyncPosEvent.UnitPos pos = new SyncPosEvent.UnitPos();
  900. SyncPosEvent.UnitState st = new SyncPosEvent.UnitState();
  901. ForEachNearObjects(x, y, range, (InstanceZoneObject u, ref bool cancel) =>
  902. {
  903. if (u.ClientVisible && u.SyncPos && u.mCurCellNode.PosDirty())
  904. {
  905. if (Collider.Object_Pos_IncludeInRound(u, x, y, range))
  906. {
  907. if (u.GenSyncPos(ref pos))
  908. {
  909. units.Add(pos);
  910. }
  911. if (u is InstanceUnit)
  912. {
  913. InstanceUnit unit = u as InstanceUnit;
  914. if (unit.GenSyncState(ref st))
  915. {
  916. units_st.Add(st);
  917. }
  918. }
  919. }
  920. }
  921. });
  922. if (units.Count > 0 || units_st.Count > 0)
  923. {
  924. SyncPosEvent ret = new SyncPosEvent(IsHalfSync, IsSyncZ, (uint)PassTimeMS);
  925. ret.units_pos = units.ToArray();
  926. ret.units_st = units_st.ToArray();
  927. return ret;
  928. }
  929. }
  930. return null;
  931. }
  932. /// <summary>
  933. /// 得到空间分割块范围内的所有移动信息
  934. /// </summary>
  935. /// <param name="bx"></param>
  936. /// <param name="by"></param>
  937. /// <returns></returns>
  938. public SyncPosEvent GetSyncPosEventBySpace(int bx, int by)
  939. {
  940. SpaceDivision.SpaceCellNode space = GetSpaceCellNodeByBlock(bx, by);
  941. if (space != null)
  942. {
  943. List<SyncPosEvent.UnitPos> units = new List<SyncPosEvent.UnitPos>(space.Count);
  944. List<SyncPosEvent.UnitState> units_st = new List<SyncPosEvent.UnitState>(space.Count);
  945. SyncPosEvent.UnitPos pos = new SyncPosEvent.UnitPos();
  946. SyncPosEvent.UnitState st = new SyncPosEvent.UnitState();
  947. space.ForEach((InstanceZoneObject u, ref bool cancel) =>
  948. {
  949. if (u.mCurCellNode.PosDirty() && u.ClientVisible && u.SyncPos)
  950. {
  951. if (u.GenSyncPos(ref pos))
  952. {
  953. units.Add(pos);
  954. }
  955. if (u is InstanceUnit)
  956. {
  957. InstanceUnit unit = u as InstanceUnit;
  958. if (unit.GenSyncState(ref st))
  959. {
  960. units_st.Add(st);
  961. }
  962. }
  963. }
  964. });
  965. if (units.Count > 0 || units_st.Count > 0)
  966. {
  967. SyncPosEvent ret = new SyncPosEvent(IsHalfSync, IsSyncZ, (uint)PassTimeMS);
  968. ret.units_pos = units.ToArray();
  969. ret.units_st = units_st.ToArray();
  970. return ret;
  971. }
  972. }
  973. return null;
  974. }
  975. public SyncPosEvent GetSyncPosEvent(ICollection<InstanceZoneObject> objs, InstancePlayer Actor, PlayerClientObject playerClient)
  976. {
  977. if (objs.Count > 0)
  978. {
  979. //using (var units = ListObjectPool<SyncPosEvent.UnitPos>.AllocAutoRelease())
  980. //using (var units_st = ListObjectPool<SyncPosEvent.UnitState>.AllocAutoRelease())
  981. m_UnitsPos.Clear();
  982. m_UnitsStates.Clear();
  983. {
  984. SyncPosEvent.UnitPos pos = new SyncPosEvent.UnitPos();
  985. SyncPosEvent.UnitState st = new SyncPosEvent.UnitState();
  986. foreach (InstanceZoneObject u in objs)
  987. {
  988. if (u.mCurCellNode.PosDirty() && u.ClientVisible && u.SyncPos)
  989. {
  990. InstanceUnit unitTemp = u as InstanceUnit;
  991. if(unitTemp != null && unitTemp.CurrentActionSubstate != 0 && Actor.CurrentActionSubstate != unitTemp.CurrentActionSubstate)
  992. {
  993. if (playerClient.RemoveInRange(u))
  994. {
  995. continue;
  996. }
  997. }
  998. if (u.GenSyncPos(ref pos))
  999. {
  1000. m_UnitsPos.Add(pos);
  1001. }
  1002. if (u is InstanceUnit)
  1003. {
  1004. InstanceUnit unit = u as InstanceUnit;
  1005. if (unit.GenSyncState(ref st))
  1006. {
  1007. m_UnitsStates.Add(st);
  1008. }
  1009. }
  1010. }
  1011. }
  1012. if (m_UnitsPos.Count > 0 || m_UnitsStates.Count > 0)
  1013. {
  1014. SyncPosEvent ret = new SyncPosEvent(IsHalfSync, IsSyncZ, PassTimeMS);
  1015. ret.units_pos = m_UnitsPos.ToArray();
  1016. ret.units_st = m_UnitsStates.ToArray();
  1017. return ret;
  1018. }
  1019. }
  1020. }
  1021. return null;
  1022. }
  1023. readonly private PositionList sync_pos_list = new PositionList();
  1024. internal class PositionList
  1025. {
  1026. public bool Enable = true;
  1027. private List<InstanceZoneObject> units = new List<InstanceZoneObject>();
  1028. public void Add(InstanceZoneObject u)
  1029. {
  1030. if (Enable)
  1031. {
  1032. units.Add(u);
  1033. }
  1034. }
  1035. public void Clear()
  1036. {
  1037. units.Clear();
  1038. }
  1039. public SyncPosEvent AsEvent(InstanceZone zone)
  1040. {
  1041. if (Enable)
  1042. {
  1043. using (var units_pos = ListObjectPool<SyncPosEvent.UnitPos>.AllocAutoRelease())
  1044. using (var units_st = ListObjectPool<SyncPosEvent.UnitState>.AllocAutoRelease())
  1045. {
  1046. SyncPosEvent.UnitPos pos = new SyncPosEvent.UnitPos();
  1047. SyncPosEvent.UnitState st = new SyncPosEvent.UnitState();
  1048. for (int i = units.Count - 1; i >= 0; --i)
  1049. {
  1050. InstanceZoneObject obj = units[i];
  1051. if (obj.GenSyncPos(ref pos))
  1052. {
  1053. units_pos.Add(pos);
  1054. }
  1055. if (obj is InstanceUnit)
  1056. {
  1057. InstanceUnit unit = obj as InstanceUnit;
  1058. if (unit.GenSyncState(ref st))
  1059. {
  1060. units_st.Add(st);
  1061. }
  1062. }
  1063. }
  1064. SyncPosEvent ret = new SyncPosEvent(zone.IsHalfSync, zone.IsSyncZ, (uint)zone.PassTimeMS);
  1065. ret.units_pos = units_pos.ToArray();
  1066. ret.units_st = units_st.ToArray();
  1067. return ret;
  1068. }
  1069. }
  1070. return null;
  1071. }
  1072. public int Count { get { return units.Count; } }
  1073. }
  1074. #endregion
  1075. }
  1076. }