InstanceZoneObject.cs 48 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using CommonAI.Zone;
  5. using CommonAI.Zone.Instance;
  6. using CommonAI.RTS;
  7. using CommonLang.Vector;
  8. using CommonAI.RTS.Manhattan;
  9. using CommonLang;
  10. using CommonAI.ZoneClient;
  11. using CommonAI.Zone.Helper;
  12. using CommonLang.Concurrent;
  13. using CommonLang.Property;
  14. using CommonLang.Log;
  15. using static CommonAI.Zone.Instance.InstanceUnit;
  16. using CommonAI.Data;
  17. namespace CommonAI.Zone.Instance
  18. {
  19. //-------------------------------------------------------------------------------------------------------//
  20. public abstract class InstanceZoneObject : GameEntity, IPositionObject
  21. {
  22. protected static readonly Logger log = LoggerFactory.GetDefLogger();
  23. private static AtomicInteger s_active_object_count = new AtomicInteger(0);
  24. private static AtomicInteger s_alloc_object_count = new AtomicInteger(0);
  25. /// <summary>
  26. /// 活动实例数量
  27. /// </summary>
  28. public static int ActiveObjectCount { get { return s_active_object_count.Value; } }
  29. /// <summary>
  30. /// 分配实例数量
  31. /// </summary>
  32. public static int AllocObjectCount { get { return s_alloc_object_count.Value; } }
  33. //------------------------------------------------------------------------------------------------
  34. public TemplateManager Templates { get { return mZone.Templates; } }
  35. /// <summary>
  36. /// 获得当前空间分割节点
  37. /// </summary>
  38. public SpaceDivision.SpaceCellNode CurrentSpaceCellNode { get { return mCurCellNode.cell; } }
  39. /// <summary>
  40. /// 是否为静态阻挡物
  41. /// </summary>
  42. readonly public bool IsStaticBlockable;
  43. private Vector2 mPos = new Vector2();
  44. private Vector2 mPosPrevFrame = new Vector2();
  45. private float mPosZPrevFrame = 0;
  46. private bool mNeedGenSyncPos = true;
  47. private ObjectForceSyncPosEvent mForceSync = new ObjectForceSyncPosEvent();
  48. internal readonly InstanceZone mZone;
  49. internal readonly SpaceDivision.ObjectCellNode mCurCellNode; // 空间分割节点
  50. private Random mParentRandom;
  51. private bool mAdded = false;
  52. private uint mID = 0;
  53. private bool mMarkRemoved = false;
  54. private string mUnitTag = "";
  55. private ObjectAoiStatus mAoiStatus;
  56. private bool mIsPause = false;
  57. private TimeExpire<int> mPauseTime = null;
  58. private float mDirectionPrevFrame = 0;
  59. private float mDirection = 0;
  60. // 此选项表示不影响空间分割,NearChanged属性,不会对ViewTrigger造成影响
  61. protected bool IsAffectNearChange = true;
  62. private double mCurPassTimeMS = 0;
  63. private int mQueryPassTimeMS = 0;
  64. private ZoneArea mCurrentArea;
  65. /** 单位是否死亡 */
  66. public virtual bool IsDead() { return false; }
  67. public virtual bool IsNeedProcessDead() { return false; }
  68. //---------------------------------------------------------------------------------------
  69. public uint ID { get { return mID; } }
  70. public InstanceZone Parent { get { return mZone; } }
  71. /// <summary>
  72. /// 是否已被添加到场景
  73. /// </summary>
  74. public bool IsInZone { get { return mAdded; } }
  75. /// <summary>
  76. /// 是否未被从场景移除
  77. /// </summary>
  78. public bool Enable { get { return !mMarkRemoved; } }
  79. public float X { get { return mPos.X; } }
  80. public float Y { get { return mPos.Y; } }
  81. public float GetX()
  82. {
  83. return mPos.X;
  84. }
  85. public float GetY ()
  86. {
  87. return mPos.Y;
  88. }
  89. public float Z { get; set; }
  90. /// <summary>
  91. /// BodyBlockSize
  92. /// </summary>
  93. public float RadiusSize { get { return BodyBlockSize; } }
  94. /// <summary>
  95. /// 朝向
  96. /// </summary>
  97. virtual public float Direction { get { return mDirection; } set { mDirection = value; } }
  98. public Random RandomN { get { return mParentRandom; } }
  99. /// <summary>
  100. /// 总共存活了多久
  101. /// </summary>
  102. public int PassTimeMS { get { return mQueryPassTimeMS; } }
  103. /// <summary>
  104. /// 从编辑器继承过来的参数
  105. /// </summary>
  106. public string UnitTag { get { return mUnitTag; } set { this.mUnitTag = value; } }
  107. /// <summary>
  108. /// 是否被标记为暂停逻辑
  109. /// </summary>
  110. public virtual bool IsPaused { get { return mIsPause; } }
  111. /// <summary>
  112. /// IAO标记
  113. /// </summary>
  114. public virtual ObjectAoiStatus AoiStatus { get { return mAoiStatus; } }
  115. /** 获取绑定玩家id */
  116. public virtual string GetBindPlayerId() { return null; }
  117. [Desc("获取当前Area")]
  118. public ZoneArea CurrentArea { get { return mCurrentArea; } }
  119. public virtual String GetTemplateData() { return ""; }
  120. //---------------------------------------------------------------------------------------
  121. public InstanceZoneObject(InstanceZone zone, bool is_static_block)
  122. {
  123. s_alloc_object_count++;
  124. s_active_object_count++;
  125. this.IsStaticBlockable = is_static_block;
  126. this.mZone = zone;
  127. this.mCurCellNode = new SpaceDivision.ObjectCellNode(this);
  128. this.mParentRandom = mZone.RandomN;
  129. }
  130. ~InstanceZoneObject()
  131. {
  132. s_alloc_object_count--;
  133. }
  134. protected override void Disposing()
  135. {
  136. Parent.clearSpace(this);
  137. this.clearEvents();
  138. base.Disposing();
  139. //mCurCellNode = null;
  140. s_active_object_count--;
  141. }
  142. // 返回结果表示当前是否可以添加
  143. internal bool tryAdd(float x, float y, float direction, uint customid = 0)
  144. {
  145. if (mAdded == false)
  146. {
  147. this.mAdded = true;
  148. this.mMarkRemoved = false;
  149. this.mID = customid > 0 ? customid : mZone.genObjectID();
  150. this.mPos.SetX(x);
  151. this.mPos.SetY(y);
  152. this.mPosPrevFrame.SetX(x);
  153. this.mPosPrevFrame.SetY(y);
  154. this.mDirection = direction;
  155. mZone.swapSpace(this, true);
  156. if (mZone.HasArea) changeArea();
  157. return true;
  158. }
  159. return false;
  160. }
  161. // 更新坐标
  162. internal virtual bool updatePos(InstanceZone zone)
  163. {
  164. if (mMarkRemoved) return false;
  165. bool ret = false;
  166. if (!mPosPrevFrame.Equals(mPos))
  167. {
  168. SpaceDivision.SpaceCellNode old_cell = CurrentSpaceCellNode;
  169. if (zone.swapSpace(this, IsAffectNearChange))
  170. {
  171. SpaceDivision.SpaceCellNode new_cell = CurrentSpaceCellNode;
  172. if (mOnObjectSpaceChanged != null)
  173. {
  174. mOnObjectSpaceChanged.Invoke(this, old_cell, new_cell);
  175. }
  176. }
  177. if (mZone.HasArea) changeArea();
  178. ret = true;
  179. }
  180. else if (mDirectionPrevFrame != Direction)
  181. {
  182. ret = true;
  183. }
  184. else if (mZone.IsSyncZ && mPosZPrevFrame != Z)
  185. {
  186. ret = true;
  187. }
  188. mPosPrevFrame.SetX(mPos.X);
  189. mPosPrevFrame.SetY(mPos.Y);
  190. mPosZPrevFrame = Z;
  191. mDirectionPrevFrame = Direction;
  192. mNeedGenSyncPos = ret;
  193. return ret;
  194. }
  195. internal void onAdded(InstanceZone zon, bool pointLv = false)
  196. {
  197. if (mOnObjectAdded != null)
  198. {
  199. mOnObjectAdded.Invoke(this);
  200. }
  201. this.onAdded(pointLv);
  202. }
  203. internal void onRemoved(InstanceZone zone)
  204. {
  205. this.mAdded = false;
  206. this.mMarkRemoved = true;
  207. this.mCurrentArea = null;
  208. zone.clearSpace(this);
  209. this.setAoiStatus(null);
  210. this.onRemoved();
  211. if (mOnObjectRemoved != null)
  212. {
  213. mOnObjectRemoved.Invoke(this);
  214. }
  215. }
  216. // 返回结果表示是否位移
  217. internal void onUpdate(InstanceZone zone, bool slowRefresh)
  218. {
  219. this.onUpdate(slowRefresh);
  220. if (!IsPaused)
  221. {
  222. mCurPassTimeMS += zone.UpdateIntervalMS;
  223. mQueryPassTimeMS = (int)mCurPassTimeMS;
  224. }
  225. else if (mPauseTime != null)
  226. {
  227. if (mPauseTime.Update(zone.UpdateIntervalMS))
  228. {
  229. mIsPause = false;
  230. mPauseTime = null;
  231. }
  232. }
  233. }
  234. // 获取队伍的天命属性加成
  235. public virtual int GetTeamFateValue(UnitFateType fateType)
  236. {
  237. return 0;
  238. }
  239. internal void onSendingEvent(ref ObjectEvent evt)
  240. {
  241. if (mOnObjectSendingEvent != null)
  242. {
  243. mOnObjectSendingEvent.Invoke(this, ref evt);
  244. }
  245. }
  246. private void changeArea()
  247. {
  248. ZoneArea old_area = mCurrentArea;
  249. ZoneArea new_area = mZone.GetArea(mPos.X, mPos.Y);
  250. if (new_area != old_area)
  251. {
  252. mCurrentArea = new_area;
  253. mZone.swapArea(this, old_area, new_area);
  254. onAreaChanged(old_area, new_area);
  255. if (mOnObjectAreaChanged != null)
  256. {
  257. mOnObjectAreaChanged.Invoke(this, old_area, new_area);
  258. }
  259. }
  260. }
  261. protected internal virtual bool GenSyncPos(ref SyncPosEvent.UnitPos ret)
  262. {
  263. if (mNeedGenSyncPos)
  264. {
  265. ret.SetObject(this);
  266. return true;
  267. }
  268. return false;
  269. }
  270. public SyncPosEvent.UnitPos GetSyncPos()
  271. {
  272. var ret = new SyncPosEvent.UnitPos();
  273. ret.SetObject(this);
  274. return ret;
  275. }
  276. //----------------------------------------------------------------------------------------
  277. /// <summary>
  278. /// 暂停逻辑
  279. /// </summary>
  280. /// <param name="pause"></param>
  281. /// <param name="timeMS"></param>
  282. public virtual void Pause(bool pause, int timeMS = 0)
  283. {
  284. this.mIsPause = pause;
  285. if (pause && timeMS > 0)
  286. {
  287. this.mPauseTime = new TimeExpire<int>(timeMS);
  288. }
  289. else { this.mPauseTime = null; }
  290. }
  291. //----------------------------------------------------------------------------------------
  292. #region DELEGATE
  293. /// <summary>
  294. /// 单位添加到场景
  295. /// </summary>
  296. /// <param name="obj"></param>
  297. public delegate void ObjectAddedHandler(InstanceZoneObject obj);
  298. /// <summary>
  299. /// 单位被移除触发
  300. /// </summary>
  301. /// <param name="obj"></param>
  302. public delegate void ObjectRemovedHandler(InstanceZoneObject obj);
  303. /// <summary>
  304. /// 单位空间分割区域改变时触发
  305. /// </summary>
  306. /// <param name="obj"></param>
  307. /// <param name="old_node"></param>
  308. /// <param name="new_node"></param>
  309. public delegate void ObjectSpaceChangedHandler(InstanceZoneObject obj, SpaceDivision.SpaceCellNode old_node, SpaceDivision.SpaceCellNode new_node);
  310. /// <summary>
  311. /// 单位空间分割区域改变时触发
  312. /// </summary>
  313. /// <param name="obj"></param>
  314. /// <param name="old_node"></param>
  315. /// <param name="new_node"></param>
  316. public delegate void ObjectAreaChangedHandler(InstanceZoneObject obj, ZoneArea old_node, ZoneArea new_node);
  317. /// <summary>
  318. /// 单位发送事件时触发
  319. /// </summary>
  320. /// <param name="obj"></param>
  321. /// <param name="evt"></param>
  322. public delegate void ObjectSendingEventHandler(InstanceZoneObject obj, ref ObjectEvent evt);
  323. private ObjectAddedHandler mOnObjectAdded;
  324. private ObjectRemovedHandler mOnObjectRemoved;
  325. private ObjectSpaceChangedHandler mOnObjectSpaceChanged;
  326. private ObjectAreaChangedHandler mOnObjectAreaChanged;
  327. private ObjectSendingEventHandler mOnObjectSendingEvent;
  328. public event ObjectAddedHandler OnObjectAdded { add { mOnObjectAdded += value; } remove { mOnObjectAdded -= value; } }
  329. public event ObjectRemovedHandler OnObjectRemoved { add { mOnObjectRemoved += value; } remove { mOnObjectRemoved -= value; } }
  330. public event ObjectSpaceChangedHandler OnObjectSpaceChanged { add { mOnObjectSpaceChanged += value; } remove { mOnObjectSpaceChanged -= value; } }
  331. public event ObjectAreaChangedHandler OnObjectAreaChanged { add { mOnObjectAreaChanged += value; } remove { mOnObjectAreaChanged -= value; } }
  332. public event ObjectSendingEventHandler OnObjectSendingEvent { add { mOnObjectSendingEvent += value; } remove { mOnObjectSendingEvent -= value; } }
  333. protected virtual void clearEvents()
  334. {
  335. mOnObjectAdded = null;
  336. mOnObjectRemoved = null;
  337. mOnObjectSpaceChanged = null;
  338. mOnObjectAreaChanged = null;
  339. mOnObjectSendingEvent = null;
  340. }
  341. #endregion
  342. //---------------------------------------------------------------------------------------------------------
  343. #region ABSTRACT
  344. /// <summary>
  345. /// 地图阻挡 ?
  346. /// </summary>
  347. abstract public bool IntersectMap { get; }
  348. /// <summary>
  349. /// 单位阻挡
  350. /// </summary>
  351. abstract public bool IntersectObj { get; }
  352. /// <summary>
  353. /// 是否可以动
  354. /// </summary>
  355. abstract public bool Moveable { get; }
  356. /// <summary>
  357. /// 自身体积(半径)
  358. /// </summary>
  359. abstract public float BodyBlockSize { get; }
  360. /// <summary>
  361. /// 受击半径
  362. /// </summary>
  363. abstract public float BodyHitSize { get; }
  364. /// <summary>
  365. /// 身体高度
  366. /// </summary>
  367. abstract public float BodyHeight { get; }
  368. /// <summary>
  369. /// 是否同步客户端
  370. /// </summary>
  371. abstract public bool ClientVisible { get; }
  372. abstract public float Weight { get; }
  373. /// <summary>
  374. /// 是否允许帧同步
  375. /// </summary>
  376. abstract public bool SyncPos { get; }
  377. abstract protected void onUpdate(bool slowRefresh);
  378. abstract protected void onAdded(bool pointLv);
  379. abstract protected void onRemoved();
  380. /*
  381. /// <summary>
  382. /// 被攻击到
  383. /// </summary>
  384. /// <param name="sender"></param>
  385. /// <param name="attack"></param>
  386. /// <returns></returns>
  387. virtual internal bool onHitAttack(InstanceUnit sender, AttackProp attack) { return false; }
  388. */
  389. /// <summary>
  390. /// 获取同步信息
  391. /// </summary>
  392. abstract public SyncObjectInfo GenSyncInfo(bool network);
  393. #endregion
  394. //---------------------------------------------------------------------------------------
  395. /// <summary>
  396. /// 直接转向
  397. /// </summary>
  398. /// <param name="x"></param>
  399. /// <param name="y"></param>
  400. public virtual void faceTo(float x, float y)
  401. {
  402. if (mPos.X == x && mPos.Y == y)
  403. {
  404. return;
  405. }
  406. this.faceTo((float)(Math.Atan2(y - mPos.Y, x - mPos.X)));
  407. }
  408. /// <summary>
  409. /// 直接转向
  410. /// </summary>
  411. /// <param name="d"></param>
  412. public virtual void faceTo(float d)
  413. {
  414. this.mDirection = d;
  415. }
  416. /// <summary>
  417. /// 基于当前角度转向
  418. /// </summary>
  419. /// <param name="add"></param>
  420. public virtual void turn(float add)
  421. {
  422. this.mDirection += add;
  423. }
  424. public bool setPos(float x, float y, bool touchMap = false)
  425. {
  426. if (touchMap)
  427. {
  428. if (!mZone.TryTouchMap(this, x, y))
  429. {
  430. this.mPos.SetX(x);
  431. this.mPos.SetY(y);
  432. Parent.swapSpace(this, true);
  433. return true;
  434. }
  435. return false;
  436. }
  437. else
  438. {
  439. this.mPos.SetX(x);
  440. this.mPos.SetY(y);
  441. Parent.swapSpace(this, true);
  442. return true;
  443. }
  444. }
  445. public bool setPos(float x, float y, float z, bool touchMap = false)
  446. {
  447. if (touchMap)
  448. {
  449. if (!mZone.TryTouchMap(this, x, y))
  450. {
  451. this.mPos.SetX(x);
  452. this.mPos.SetY(y);
  453. this.Z = z;
  454. Parent.swapSpace(this, true);
  455. return true;
  456. }
  457. return false;
  458. }
  459. else
  460. {
  461. this.mPos.SetX(x);
  462. this.mPos.SetY(y);
  463. this.Z = z;
  464. Parent.swapSpace(this, true);
  465. return true;
  466. }
  467. }
  468. public void setAoiStatus(ObjectAoiStatus aoi)
  469. {
  470. if (this.mAoiStatus != aoi)
  471. {
  472. if (this.mAoiStatus != null)
  473. {
  474. try
  475. {
  476. if(mAoiStatus !=null && mAoiStatus.IsNeedNotifyClient && this is InstancePlayer)
  477. {
  478. var ce = new ChatEvent(ChatMessageType.SystemToPlayer);
  479. ce.ToPlayerUUID = (this as InstancePlayer).PlayerUUID;
  480. ce.Message = "LeaveAOI";
  481. this.Parent.queueEvent(ce);
  482. }
  483. this.mAoiStatus.RemoveObject(this);
  484. }
  485. catch(Exception e)
  486. {
  487. log.Warn("setAoiStatus catch: " + this.Parent.GetSceneID() + ", " + (mAoiStatus == null ? "aoi null" : mAoiStatus.ToString()) + ", " +
  488. this.GetTemplateData() + ", setaoI:" + (aoi == null ? "aoi null" : aoi.ToString()) + ", " + e);
  489. }
  490. }
  491. this.mAoiStatus = aoi;
  492. if (this.mAoiStatus != null)
  493. {
  494. this.mAoiStatus.AddObject(this);
  495. if (this is InstancePlayer && mAoiStatus.IsNeedNotifyClient)
  496. {
  497. var ce = new ChatEvent(ChatMessageType.SystemToPlayer);
  498. ce.ToPlayerUUID = (this as InstancePlayer).PlayerUUID;
  499. ce.Message = "EnterAOI";
  500. this.Parent.queueEvent(ce);
  501. }
  502. }
  503. InstancePlayer player = this as InstancePlayer;
  504. if(player != null)
  505. {
  506. //玩家停止技能行为
  507. StateSkill state = player.CurrentState as StateSkill;
  508. if (state != null)
  509. {
  510. PlayerSkillStopEvent evt = new PlayerSkillStopEvent(player.ID, state.SkillData.ID);
  511. player.queueEvent(evt);
  512. state.Skill.ForceIntoCD();
  513. player.changeState(new StateIdle(player), true);
  514. }
  515. }
  516. }
  517. }
  518. public virtual void SendForceSync()
  519. {
  520. mForceSync.object_id = this.ID;
  521. mForceSync.X = this.X;
  522. mForceSync.Y = this.Y;
  523. mForceSync.Direction = this.Direction;
  524. Parent.queueObjectEvent(this, mForceSync);
  525. }
  526. //---------------------------------------------------------------------------------------------------------
  527. protected virtual void onAreaChanged(ZoneArea old_area, ZoneArea new_area) { }
  528. /// <summary>
  529. /// 在移动时被某个单位阻挡
  530. /// </summary>
  531. /// <param name="obj"></param>
  532. protected virtual void onMoveBlockWithObject(InstanceZoneObject obj) { }
  533. /// <summary>
  534. /// 阻挡到其他单位移动
  535. /// </summary>
  536. /// <param name="obj"></param>
  537. /// <returns >通知其他单位自己可以让开</returns>
  538. protected virtual bool onBlockOther(InstanceZoneObject obj) { return false; }
  539. //---------------------------------------------------------------------------------------------------------
  540. /// <summary>
  541. /// 无碰撞移动
  542. /// </summary>
  543. /// <param name="direction"></param>
  544. /// <param name="speedSEC"></param>
  545. /// <param name="intervalMS"></param>
  546. public void flyTo(float direction, float speedSEC, int intervalMS)
  547. {
  548. float distance = MoveHelper.GetDistance(intervalMS, speedSEC);
  549. MathVector.movePolar(mPos, direction, distance);
  550. }
  551. /// <summary>
  552. ///
  553. /// </summary>
  554. /// <param name="x"></param>
  555. /// <param name="y"></param>
  556. /// <param name="speedSEC"></param>
  557. /// <param name="intervalMS"></param>
  558. /// <returns>是否到达终点</returns>
  559. public bool flyToTarget(float x, float y, float speedSEC, int intervalMS)
  560. {
  561. float distance = MoveHelper.GetDistance(intervalMS, speedSEC);
  562. return MathVector.moveTo(mPos, x, y, distance);
  563. }
  564. public void flyToTargetTunning(float x, float y, float speedSEC, float tunningSpeedSEC, int intervalMS)
  565. {
  566. MoveHelper.MoveToTargetTunning(ref mPos, ref mDirection, x, y, speedSEC, tunningSpeedSEC, intervalMS);
  567. }
  568. //曲线移动
  569. public void CurveMoveTo(Vector2 startPos, Vector2 handlePos, float endX, float endY, float fStep, float speedSEC, int intervalMS)
  570. {
  571. //float pX1 = startPos.X * (1 - fStep) + handlePos.X * fStep;
  572. //float pY1 = startPos.Y * (1 - fStep) + handlePos.Y * fStep;
  573. //float pX2 =
  574. //Vector3 result = (1 - fStep) * p0p1 + fStep * p1p2;
  575. }
  576. /// <summary>
  577. /// 越过单位跳跃
  578. /// </summary>
  579. /// <param name="direction"></param>
  580. /// <param name="speedSEC"></param>
  581. /// <param name="intervalMS"></param>
  582. /// <param name="ignore_z"></param>
  583. /// <returns>是否到达终点</returns>
  584. public bool jumpTo(float direction, float speedSEC, int intervalMS, bool ignore_z = true)
  585. {
  586. float distance = MoveHelper.GetDistance(intervalMS, speedSEC);
  587. float dx = (float)(Math.Cos(direction) * distance);
  588. float dy = (float)(Math.Sin(direction) * distance);
  589. if (IntersectMap)
  590. {
  591. float oldx = mPos.X;
  592. float oldy = mPos.Y;
  593. switch (Parent.TryMoveToMapBorder(this, ref mPos, dx, dy))
  594. {
  595. case AstarManhattan.TryMoveToMapBorderResult.BLOCK:
  596. return true;
  597. }
  598. if (ignore_z)
  599. {
  600. if (mZone.intersectNearStaticBlockable(this) != null)
  601. {
  602. mPos.SetY(oldy);
  603. mPos.SetX(oldx);
  604. return true;
  605. }
  606. }
  607. else
  608. {
  609. if (mZone.intersectNearStaticBlockableZ(this) != null)
  610. {
  611. mPos.SetY(oldy);
  612. mPos.SetX(oldx);
  613. return true;
  614. }
  615. }
  616. }
  617. else
  618. {
  619. this.mPos.AddX(dx);
  620. this.mPos.AddY(dy);
  621. }
  622. return false;
  623. }
  624. public bool jumpToTarget(float x, float y, float speedSEC, int intervalMS, bool ignore_z = true)
  625. {
  626. float distance = MoveHelper.GetDistance(intervalMS, speedSEC);
  627. float ddx = x - mPos.X;
  628. float ddy = y - mPos.Y;
  629. float direction = MathVector.getDegree(ddx, ddy);
  630. float dx = (float)(Math.Cos(direction) * distance);
  631. float dy = (float)(Math.Sin(direction) * distance);
  632. bool minstep = false;
  633. if (Math.Abs(ddx) < distance && Math.Abs(ddy) < distance)
  634. {
  635. dx = ddx;
  636. dy = ddy;
  637. minstep = true;
  638. }
  639. if (IntersectMap)
  640. {
  641. float oldx = mPos.X;
  642. float oldy = mPos.Y;
  643. switch (Parent.TryMoveToMapBorder(this, ref mPos, dx, dy))
  644. {
  645. case AstarManhattan.TryMoveToMapBorderResult.BLOCK:
  646. if (IntersectObj) ElasticOtherObjects();
  647. return true;
  648. }
  649. if (ignore_z)
  650. {
  651. if (mZone.intersectNearStaticBlockable(this) != null)
  652. {
  653. mPos.SetY(oldy);
  654. mPos.SetX(oldx);
  655. if (IntersectObj) ElasticOtherObjects();
  656. return true;
  657. }
  658. }
  659. else
  660. {
  661. if (mZone.intersectNearStaticBlockableZ(this) != null)
  662. {
  663. mPos.SetY(oldy);
  664. mPos.SetX(oldx);
  665. if (IntersectObj) ElasticOtherObjects();
  666. return true;
  667. }
  668. }
  669. }
  670. else
  671. {
  672. this.mPos.AddX(dx);
  673. this.mPos.AddY(dy);
  674. }
  675. return minstep;
  676. }
  677. //---------------------------------------------------------------------------------------------------------
  678. //---------------------------------------------------------------------------------------------------------
  679. /// <summary>
  680. /// 移动到目标点
  681. /// </summary>
  682. /// <param name="angle"></param>
  683. /// <param name="speedSEC"></param>
  684. /// <param name="intervalMS"></param>
  685. /// <returns>可以顺利移动</returns>
  686. public MoveBlockResult moveBlockTo(float angle, float speedSEC, int intervalMS)
  687. {
  688. float dd = MoveHelper.GetDistance(intervalMS, speedSEC);
  689. float dx = (float)(Math.Cos(angle) * dd);
  690. float dy = (float)(Math.Sin(angle) * dd);
  691. return moveBlock(dx, dy);
  692. }
  693. /// <summary>
  694. /// 移动到目标点
  695. /// </summary>
  696. /// <param name="x"></param>
  697. /// <param name="y"></param>
  698. /// <param name="speedSEC"></param>
  699. /// <param name="intervalMS"></param>
  700. /// <returns>可以顺利移动</returns>
  701. public MoveBlockResult moveBlockTo(float x, float y, float speedSEC, int intervalMS)
  702. {
  703. if (mPos.X == x && mPos.Y == y)
  704. {
  705. MoveBlockResult result = new MoveBlockResult(MoveResult.MOVE_RESULT_ARRIVED);
  706. return result;
  707. }
  708. float distance = MoveHelper.GetDistance(intervalMS, speedSEC);
  709. float ddx = x - mPos.X;
  710. float ddy = y - mPos.Y;
  711. if (Math.Abs(ddx) < distance && Math.Abs(ddy) < distance)
  712. {
  713. MoveBlockResult result = moveBlock(ddx, ddy);
  714. if ((result.result & MoveResult.RESULTS_MOVE_END) != 0)
  715. {
  716. }
  717. else
  718. {
  719. result.result |= MoveResult.MOVE_RESULT_ARRIVED;
  720. }
  721. return result;
  722. }
  723. else
  724. {
  725. float oldx = mPos.X;
  726. float oldy = mPos.Y;
  727. float direction = (float)(Math.Atan2(ddy, ddx));
  728. float dx = (float)(Math.Cos(direction) * distance);
  729. float dy = (float)(Math.Sin(direction) * distance);
  730. MoveBlockResult result = moveBlock(dx, dy);
  731. ddx = Math.Abs(mPos.X - oldx);
  732. ddy = Math.Abs(mPos.Y - oldy);
  733. float minstep = Parent.MinStep;
  734. if (ddx > 0 || ddy > 0)
  735. {
  736. if (ddx < minstep && ddy < minstep)
  737. {
  738. result.result |= MoveResult.MOVE_RESULT_MIN_STEP;
  739. }
  740. }
  741. return result;
  742. }
  743. }
  744. /// <summary>
  745. /// 尝试碰撞移动偏移量
  746. /// </summary>
  747. /// <param name="dx"></param>
  748. /// <param name="dy"></param>
  749. /// <returns></returns>
  750. public MoveBlockResult moveBlock(float dx, float dy)
  751. {
  752. float oldx = mPos.X;
  753. float oldy = mPos.Y;
  754. MoveBlockResult result = new MoveBlockResult(0);
  755. if (IntersectMap)
  756. {
  757. //尝试地图碰撞移动//
  758. var res = Parent.TryMoveToMapBorder(this, ref mPos, dx, dy);
  759. switch (res)
  760. {
  761. case AstarManhattan.TryMoveToMapBorderResult.BLOCK:
  762. result.result |= MoveResult.MOVE_RESULT_TOUCH_MAP_ALL;
  763. result.result |= MoveResult.MOVE_RESULT_BLOCK_MAP;
  764. return result;
  765. case AstarManhattan.TryMoveToMapBorderResult.TOUCH:
  766. result.result |= MoveResult.MOVE_RESULT_TOUCH_MAP_ALL;
  767. break;
  768. case AstarManhattan.TryMoveToMapBorderResult.ARRIVE:
  769. break;
  770. }
  771. //和建筑碰撞//
  772. if (this.IntersectObj)
  773. {
  774. InstanceZoneObject bu = mZone.intersectNearStaticBlockable(this);
  775. result.obj = bu;
  776. if (bu != null)
  777. {
  778. mPos.SetY(oldy);
  779. mPos.SetX(oldx);
  780. result.result |= MoveResult.MOVE_RESULT_BLOCK_OBJ;
  781. //恢复到原来位置也碰撞的话,就弹开//
  782. if (mZone.TouchObject2(this, bu))
  783. {
  784. ElasticOtherObject(bu);
  785. }
  786. onMoveBlockWithObject(bu);
  787. }
  788. return result;
  789. }
  790. }
  791. else
  792. {
  793. this.mPos.AddX(dx);
  794. this.mPos.AddY(dy);
  795. }
  796. if (this.IntersectObj)
  797. {
  798. //和单位碰撞//
  799. InstanceZoneObject bu = mZone.intersectNearUnit(this);
  800. result.obj = bu;
  801. if (bu != null)
  802. {
  803. mPos.SetY(oldy);
  804. mPos.SetX(oldx);
  805. if (bu.onBlockOther(this))
  806. {
  807. result.result |= MoveResult.MOVE_RESULT_TOUCH_OBJ_GETAWAY;
  808. }
  809. result.result |= MoveResult.MOVE_RESULT_BLOCK_OBJ;
  810. if (mZone.TouchObject2(this, bu))
  811. {
  812. //恢复到原来位置也碰撞的话,就弹开//
  813. if (ElasticOtherObject(bu) == false)
  814. {
  815. this.mPos.AddX(dx);
  816. this.mPos.AddY(dy);
  817. }
  818. }
  819. onMoveBlockWithObject(bu);
  820. }
  821. }
  822. return result;
  823. }
  824. /// <summary>
  825. /// 挤开对方的移动方式
  826. /// </summary>
  827. /// <param name="x"></param>
  828. /// <param name="y"></param>
  829. /// <param name="speedSEC"></param>
  830. /// <param name="intervalMS"></param>
  831. /// <returns>TRUE=无法移动</returns>
  832. public MoveImpactResult moveImpactTo(float x, float y, float speedSEC, int intervalMS)
  833. {
  834. float minstep = Parent.MinStep;
  835. float distance = MoveHelper.GetDistance(intervalMS, speedSEC);
  836. if (Math.Abs(distance) < minstep)
  837. {
  838. return MoveImpactResult.MOVE_RESULT_MIN_STEP;
  839. }
  840. float ddx = x - mPos.X;
  841. float ddy = y - mPos.Y;
  842. if (Math.Abs(ddx) < distance && Math.Abs(ddy) < distance)
  843. {
  844. return MoveImpactResult.MOVE_RESULT_MIN_STEP;
  845. }
  846. float angle = MathVector.getDegree(ddx, ddy);
  847. return moveImpactInner(angle, distance, 0);
  848. }
  849. /// <summary>
  850. /// 挤开对方的移动方式
  851. /// </summary>
  852. /// <param name="angle"></param>
  853. /// <param name="speedSEC"></param>
  854. /// <param name="intervalMS"></param>
  855. /// <returns>TRUE=无法移动</returns>
  856. public MoveImpactResult moveImpact(float angle, float speedSEC, int intervalMS)
  857. {
  858. float minstep = Parent.MinStep;
  859. float distance = MoveHelper.GetDistance(intervalMS, speedSEC);
  860. if (Math.Abs(distance) < minstep)
  861. {
  862. return MoveImpactResult.MOVE_RESULT_MIN_STEP;
  863. }
  864. return moveImpactInner(angle, distance, 0);
  865. }
  866. public MoveImpactResult moveImpactDistance(float angle, float distance)
  867. {
  868. float minstep = Parent.MinStep;
  869. if (Math.Abs(distance) < minstep)
  870. {
  871. return MoveImpactResult.MOVE_RESULT_MIN_STEP;
  872. }
  873. return moveImpactInner(angle, distance, 0);
  874. }
  875. protected virtual MoveImpactResult moveImpactInner(float angle, float distance, int depth)
  876. {
  877. MoveImpactResult ret = MoveImpactResult.MOVE_SMOOTH;
  878. float dx = (float)(Math.Cos(angle) * distance);
  879. float dy = (float)(Math.Sin(angle) * distance);
  880. float oldx = mPos.X;
  881. float oldy = mPos.Y;
  882. if (IntersectMap)
  883. {
  884. switch (Parent.TryMoveToMapBorder(this, ref mPos, dx, dy))
  885. {
  886. case AstarManhattan.TryMoveToMapBorderResult.BLOCK:
  887. ret |= MoveImpactResult.MOVE_RESULT_BLOCK_MAP;
  888. ret |= MoveImpactResult.MOVE_RESULT_TOUCH_MAP;
  889. return ret;
  890. case AstarManhattan.TryMoveToMapBorderResult.TOUCH:
  891. ret |= MoveImpactResult.MOVE_RESULT_TOUCH_MAP;
  892. break;
  893. case AstarManhattan.TryMoveToMapBorderResult.ARRIVE:
  894. break;
  895. }
  896. }
  897. else
  898. {
  899. this.mPos.AddX(dx);
  900. this.mPos.AddY(dy);
  901. }
  902. if (!this.IntersectObj)
  903. {
  904. if (IntersectMap)
  905. {
  906. InstanceZoneObject bu = mZone.intersectNearStaticBlockable(this);
  907. if (bu != null)
  908. {
  909. mPos.SetY(oldy);
  910. mPos.SetX(oldx);
  911. ret |= MoveImpactResult.MOVE_RESULT_BLOCK_OBJ;
  912. ret |= MoveImpactResult.MOVE_RESULT_TOUCH_OBJ;
  913. return ret;
  914. }
  915. }
  916. return ret;
  917. }
  918. else
  919. {
  920. uint max_depth = Templates.CFG.GLOBAL_MOVE_IMPACT_DEPTH;
  921. bool touched = Parent.ForEachNearObjects(mPos.X, mPos.Y, (InstanceZoneObject o, ref bool cancel) =>
  922. {
  923. if (o != this && o.IntersectObj && Parent.TouchObject2(this, o))
  924. {
  925. ret |= MoveImpactResult.MOVE_RESULT_TOUCH_OBJ;
  926. if ((!o.IsStaticBlockable) && (o.Weight <= this.Weight))
  927. {
  928. if (depth < max_depth)
  929. {
  930. float targetAngle = MathVector.getDegree(this.X, this.Y, o.X, o.Y);
  931. float ddr = MathVector.getDistance(o.mPos, this.mPos);
  932. float bdr = (this.BodyBlockSize + o.BodyBlockSize);
  933. o.moveImpactInner(targetAngle, (bdr - ddr), depth + 1);
  934. }
  935. else
  936. {
  937. this.mPos.SetX(oldx);
  938. this.mPos.SetY(oldy);
  939. cancel = true;
  940. ret |= MoveImpactResult.MOVE_RESULT_BLOCK_OBJ;
  941. }
  942. }
  943. else
  944. {
  945. this.mPos.SetX(oldx);
  946. this.mPos.SetY(oldy);
  947. cancel = true;
  948. ret |= MoveImpactResult.MOVE_RESULT_BLOCK_OBJ;
  949. if (Parent.TouchObject2(this, o))
  950. {
  951. float targetAngle = MathVector.getDegree(o.X, o.Y, this.X, this.Y);
  952. float ddr = MathVector.getDistance(o.mPos, this.mPos);
  953. float bdr = (this.BodyBlockSize + o.BodyBlockSize);
  954. //强制将自己移动到某处//
  955. this.moveLinearMap((bdr - ddr), targetAngle);
  956. }
  957. }
  958. }
  959. });
  960. return ret;
  961. }
  962. }
  963. //-------------------------------------------------------------------------------------------------------//
  964. /// <summary>
  965. /// 线性移动,只和地图碰撞
  966. /// </summary>
  967. /// <param name="distance"></param>
  968. /// <param name="angle"></param>
  969. /// <returns>和地图碰撞</returns>
  970. public bool moveLinearMap(float distance, float angle)
  971. {
  972. float dx = (float)(Math.Cos(angle) * distance);
  973. float dy = (float)(Math.Sin(angle) * distance);
  974. float touch_x, touch_y, touch_d;
  975. if (Parent.PathFinder.GetLineTouchPoint(mPos.X, mPos.Y, mPos.X + dx, mPos.Y + dy, out touch_x, out touch_y, out touch_d))
  976. {
  977. MathVector.movePolar(ref touch_x, ref touch_y, angle, -Parent.MinStep);
  978. mPos.SetX(touch_x);
  979. mPos.SetY(touch_y);
  980. return true;
  981. }
  982. mPos.AddX(dx);
  983. mPos.AddY(dy);
  984. return false;
  985. }
  986. /// <summary>
  987. /// 线性移动,只和地图碰撞
  988. /// </summary>
  989. /// <param name="dx"></param>
  990. /// <param name="dy"></param>
  991. /// <returns>和地图碰撞</returns>
  992. public bool moveLinearMap2(float dx, float dy)
  993. {
  994. float touch_x, touch_y, touch_d;
  995. if (Parent.PathFinder.GetLineTouchPoint(mPos.X, mPos.Y, mPos.X + dx, mPos.Y + dy, out touch_x, out touch_y, out touch_d))
  996. {
  997. MathVector.movePolar(ref touch_x, ref touch_y, MathVector.getDegree(dx, dy), -Parent.MinStep);
  998. mPos.SetX(touch_x);
  999. mPos.SetY(touch_y);
  1000. return true;
  1001. }
  1002. mPos.AddX(dx);
  1003. mPos.AddY(dy);
  1004. return false;
  1005. }
  1006. /// <summary>
  1007. /// 线性移动,不会穿
  1008. /// </summary>
  1009. /// <param name="distance"></param>
  1010. /// <param name="angle"></param>
  1011. /// <param name="ignore_map"></param>
  1012. /// <param name="ignore_obj"></param>
  1013. /// <returns></returns>
  1014. public MoveBlockResult moveLinear(float distance, float angle, bool ignore_map = false, bool ignore_obj = true)
  1015. {
  1016. MoveBlockResult ret = new MoveBlockResult();
  1017. float dx = (float)(Math.Cos(angle) * distance);
  1018. float dy = (float)(Math.Sin(angle) * distance);
  1019. float dst_x = mPos.X + dx;
  1020. float dst_y = mPos.Y + dy;
  1021. float tgt_x = dst_x;
  1022. float tgt_y = dst_y;
  1023. if (!ignore_map)
  1024. {
  1025. float touch_x, touch_y, touch_d;
  1026. if (Parent.PathFinder.GetLineTouchPoint(mPos.X, mPos.Y, dst_x, dst_y, out touch_x, out touch_y, out touch_d))
  1027. {
  1028. ret.result |= MoveResult.MOVE_RESULT_TOUCH_MAP_ALL;
  1029. if (dst_x == touch_x && dst_y == touch_y)
  1030. {
  1031. ret.result |= MoveResult.MOVE_RESULT_BLOCK_MAP;
  1032. return ret;
  1033. }
  1034. float minstep = Parent.MinStep;
  1035. MathVector.movePolar(ref touch_x, ref touch_y, angle, -minstep);
  1036. dst_x = touch_x;
  1037. dst_y = touch_y;
  1038. distance = (touch_d - minstep);
  1039. }
  1040. }
  1041. using (var list = ListObjectPool<InstanceZoneObject>.AllocAutoRelease())
  1042. {
  1043. if (!ignore_obj)
  1044. {
  1045. Parent.getObjectsRoundLineRange<InstanceZoneObject>(
  1046. Collider.Object_BlockBody_TouchRoundLine,
  1047. mPos.X, mPos.Y, dst_x, dst_y, BodyBlockSize,
  1048. list, AoiStatus);
  1049. }
  1050. else if (!ignore_map)
  1051. {
  1052. Parent.getObjectsRoundLineRange<InstanceZoneObject>((o, x1, y1, x2, y2, r) =>
  1053. {
  1054. if (o.IsStaticBlockable && o.IntersectObj)
  1055. {
  1056. return Collider.Object_BlockBody_TouchRoundLine(o, x1, y1, x2, y2, r);
  1057. }
  1058. return false;
  1059. }, mPos.X, mPos.Y, dst_x, dst_y, BodyBlockSize, list, AoiStatus);
  1060. }
  1061. if (list.Count > 0)
  1062. {
  1063. list.Sort(new ObjectBodySorterNearest<InstanceZoneObject>(mPos.X, mPos.Y, this.BodyBlockSize));
  1064. ret.result |= MoveResult.MOVE_RESULT_BLOCK_OBJ;
  1065. ret.obj = list[0];
  1066. distance = MathVector.getDistance(mPos.X, mPos.Y, ret.obj.X, ret.obj.Y) - this.BodyBlockSize - ret.obj.BodyBlockSize;
  1067. distance = Math.Max(distance, 0);
  1068. dx = (float)(Math.Cos(angle) * distance);
  1069. dy = (float)(Math.Sin(angle) * distance);
  1070. dst_x = mPos.X;
  1071. dst_y = mPos.Y;
  1072. if (!ignore_map)
  1073. {
  1074. Parent.TryMoveToMapBorder(this, ref dst_x, ref dst_y, dx, dy);
  1075. }
  1076. else
  1077. {
  1078. dst_x += dx;
  1079. dst_y += dy;
  1080. }
  1081. }
  1082. }
  1083. mPos.SetX(dst_x);
  1084. mPos.SetY(dst_y);
  1085. if (tgt_x == dst_x && tgt_y == dst_y)
  1086. {
  1087. ret.result |= MoveResult.MOVE_RESULT_ARRIVED;
  1088. }
  1089. return ret;
  1090. }
  1091. public bool moveBlink(BlinkMove blink, Vector2 targetPos = null, InstanceZoneObject targetUnit = null)
  1092. {
  1093. switch (blink.MType)
  1094. {
  1095. case BlinkMove.BlinkMoveType.MoveToForward:
  1096. moveLinear(blink.Distance,
  1097. mDirection + blink.DirectionOffset,
  1098. blink.NoneTouchMap || !IntersectMap,
  1099. blink.NoneTouchObj || !IntersectObj);
  1100. return true;
  1101. case BlinkMove.BlinkMoveType.MoveToBackward:
  1102. moveLinear(-blink.Distance,
  1103. mDirection + blink.DirectionOffset,
  1104. blink.NoneTouchMap || !IntersectMap,
  1105. blink.NoneTouchObj || !IntersectObj);
  1106. return true;
  1107. case BlinkMove.BlinkMoveType.MoveToTargetPos:
  1108. if (targetPos != null)
  1109. {
  1110. if (CMath.includeRoundPoint(X, Y, blink.Distance, targetUnit.X, targetUnit.Y))
  1111. {
  1112. float angle = MathVector.getDegree(this.X, this.Y, targetPos.X, targetPos.Y);
  1113. float distance = Math.Max(MathVector.getDistance(this.X, this.Y, targetPos.X, targetPos.Y), blink.Distance);
  1114. moveLinear(distance,
  1115. angle + blink.DirectionOffset,
  1116. blink.NoneTouchMap || !IntersectMap,
  1117. blink.NoneTouchObj || !IntersectObj);
  1118. return true;
  1119. }
  1120. }
  1121. break;
  1122. case BlinkMove.BlinkMoveType.MoveToTargetUnitFace:
  1123. if (targetUnit != null)
  1124. {
  1125. if (CMath.includeRoundPoint(X, Y, blink.Distance, targetUnit.X, targetUnit.Y))
  1126. {
  1127. mPos.SetX(targetUnit.X);
  1128. mPos.SetY(targetUnit.Y);
  1129. mDirection = targetUnit.Direction + CMath.PI_F + blink.DirectionOffset;
  1130. moveLinear(
  1131. targetUnit.BodyBlockSize + this.BodyBlockSize,
  1132. targetUnit.Direction,
  1133. blink.NoneTouchMap || !IntersectMap,
  1134. blink.NoneTouchObj || !IntersectObj);
  1135. return true;
  1136. }
  1137. }
  1138. break;
  1139. case BlinkMove.BlinkMoveType.MoveToTargetUnitBack:
  1140. if (targetUnit != null)
  1141. {
  1142. if (CMath.includeRoundPoint(X, Y, blink.Distance, targetUnit.X, targetUnit.Y))
  1143. {
  1144. mPos.SetX(targetUnit.X);
  1145. mPos.SetY(targetUnit.Y);
  1146. mDirection = targetUnit.Direction + blink.DirectionOffset;
  1147. moveLinear(
  1148. -(targetUnit.BodyBlockSize + this.BodyBlockSize),
  1149. targetUnit.Direction,
  1150. blink.NoneTouchMap || !IntersectMap,
  1151. blink.NoneTouchObj || !IntersectObj);
  1152. return true;
  1153. }
  1154. }
  1155. break;
  1156. }
  1157. return false;
  1158. }
  1159. /// <summary>
  1160. /// 挤开其他和自己重叠的单位,或者被Weight大于自己的人挤开
  1161. /// </summary>
  1162. /// <returns></returns>
  1163. public bool ElasticOtherObjects()
  1164. {
  1165. bool force_sync = false;
  1166. Parent.ForEachNearObjects(X, Y, (InstanceZoneObject o, ref bool cancel) =>
  1167. {
  1168. if ((o != this) && (o.IntersectObj) && Parent.TouchObject2(this, o))
  1169. {
  1170. if (ElasticOtherObject(o))
  1171. {
  1172. force_sync = true;
  1173. }
  1174. }
  1175. });
  1176. return force_sync;
  1177. }
  1178. /// <summary>
  1179. /// 挤开其他和自己重叠的单位,或者被Weight大于自己的人挤开
  1180. /// </summary>
  1181. /// <param name="o"></param>
  1182. /// <returns>自己发生位移</returns>
  1183. public bool ElasticOtherObject(InstanceZoneObject o)
  1184. {
  1185. float targetAngle = (float)(RandomN.NextDouble() * CMath.PI_MUL_2);
  1186. float ddr = MathVector.getDistance(this.X, this.Y, o.X, o.Y);
  1187. if (ddr > 0)
  1188. {
  1189. targetAngle = MathVector.getDegree(this.X, this.Y, o.X, o.Y);
  1190. }
  1191. float bdr = (this.BodyBlockSize + o.BodyBlockSize);
  1192. float d = (bdr - ddr);
  1193. if (!o.Moveable)
  1194. {
  1195. this.moveImpactDistance(targetAngle, -d);
  1196. return true;
  1197. }
  1198. else if (o.Weight > this.Weight)
  1199. {
  1200. this.moveImpactDistance(targetAngle, -d);
  1201. return true;
  1202. }
  1203. else
  1204. {
  1205. o.moveImpactDistance(targetAngle, d);
  1206. return false;
  1207. }
  1208. }
  1209. }
  1210. }