InstanceZoneObject.cs 47 KB

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