123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287 |
- using System;
- using System.Collections.Generic;
- using System.Text;
- using CommonAI.Zone;
- using CommonAI.Zone.Instance;
- using CommonAI.RTS;
- using CommonLang.Vector;
- using CommonAI.RTS.Manhattan;
- using CommonLang;
- using CommonAI.ZoneClient;
- using CommonAI.Zone.Helper;
- using CommonLang.Concurrent;
- using CommonLang.Property;
- using CommonLang.Log;
- using static CommonAI.Zone.Instance.InstanceUnit;
- using CommonAI.Data;
- namespace CommonAI.Zone.Instance
- {
- //-------------------------------------------------------------------------------------------------------//
- public abstract class InstanceZoneObject : GameEntity, IPositionObject
- {
- protected static readonly Logger log = LoggerFactory.GetDefLogger();
- private static AtomicInteger s_active_object_count = new AtomicInteger(0);
- private static AtomicInteger s_alloc_object_count = new AtomicInteger(0);
- /// <summary>
- /// 活动实例数量
- /// </summary>
- public static int ActiveObjectCount { get { return s_active_object_count.Value; } }
- /// <summary>
- /// 分配实例数量
- /// </summary>
- public static int AllocObjectCount { get { return s_alloc_object_count.Value; } }
- //------------------------------------------------------------------------------------------------
- public TemplateManager Templates { get { return mZone.Templates; } }
- /// <summary>
- /// 获得当前空间分割节点
- /// </summary>
- public SpaceDivision.SpaceCellNode CurrentSpaceCellNode { get { return mCurCellNode.cell; } }
- /// <summary>
- /// 是否为静态阻挡物
- /// </summary>
- readonly public bool IsStaticBlockable;
- private Vector2 mPos = new Vector2();
- readonly private Vector2 mPosPrevFrame = new Vector2();
- private float mPosZPrevFrame = 0;
- private bool mNeedGenSyncPos = true;
- private ObjectForceSyncPosEvent mForceSync = new ObjectForceSyncPosEvent();
- internal readonly InstanceZone mZone;
- internal readonly SpaceDivision.ObjectCellNode mCurCellNode; // 空间分割节点
- private Random mParentRandom;
- private bool mAdded = false;
- private uint mID = 0;
- private bool mMarkRemoved = false;
- private string mUnitTag = "";
- private ObjectAoiStatus mAoiStatus;
- private bool mIsPause = false;
- private TimeExpire<int> mPauseTime = null;
- private float mDirectionPrevFrame = 0;
- private float mDirection = 0;
- // 此选项表示不影响空间分割,NearChanged属性,不会对ViewTrigger造成影响
- protected bool IsAffectNearChange = true;
- private double mCurPassTimeMS = 0;
- private int mQueryPassTimeMS = 0;
- private ZoneArea mCurrentArea;
- /** 单位是否死亡 */
- public virtual bool IsDead() { return false; }
- //---------------------------------------------------------------------------------------
- public uint ID { get { return mID; } }
- public InstanceZone Parent { get { return mZone; } }
- /// <summary>
- /// 是否已被添加到场景
- /// </summary>
- public bool IsInZone { get { return mAdded; } }
- /// <summary>
- /// 是否未被从场景移除
- /// </summary>
- public bool Enable { get { return !mMarkRemoved; } }
- public float X { get { return mPos.X; } }
- public float Y { get { return mPos.Y; } }
- public float GetX()
- {
- return mPos.X;
- }
- public float GetY ()
- {
- return mPos.Y;
- }
- public float Z { get; set; }
- /// <summary>
- /// BodyBlockSize
- /// </summary>
- public float RadiusSize { get { return BodyBlockSize; } }
- /// <summary>
- /// 朝向
- /// </summary>
- virtual public float Direction { get { return mDirection; } set { mDirection = value; } }
- public Random RandomN { get { return mParentRandom; } }
- /// <summary>
- /// 总共存活了多久
- /// </summary>
- public int PassTimeMS { get { return mQueryPassTimeMS; } }
- /// <summary>
- /// 从编辑器继承过来的参数
- /// </summary>
- public string UnitTag { get { return mUnitTag; } set { this.mUnitTag = value; } }
- /// <summary>
- /// 是否被标记为暂停逻辑
- /// </summary>
- public virtual bool IsPaused { get { return mIsPause; } }
- /// <summary>
- /// IAO标记
- /// </summary>
- public virtual ObjectAoiStatus AoiStatus { get { return mAoiStatus; } }
- /** 获取绑定玩家id */
- public virtual string GetBindPlayerId() { return null; }
- [Desc("获取当前Area")]
- public ZoneArea CurrentArea { get { return mCurrentArea; } }
- public virtual String GetTemplateData() { return ""; }
- //---------------------------------------------------------------------------------------
- public InstanceZoneObject(InstanceZone zone, bool is_static_block)
- {
- s_alloc_object_count++;
- s_active_object_count++;
- this.IsStaticBlockable = is_static_block;
- this.mZone = zone;
- this.mCurCellNode = new SpaceDivision.ObjectCellNode(this);
- this.mParentRandom = mZone.RandomN;
- }
- ~InstanceZoneObject()
- {
- s_alloc_object_count--;
- }
- protected override void Disposing()
- {
- Parent.clearSpace(this);
- this.clearEvents();
- base.Disposing();
- //mCurCellNode = null;
- s_active_object_count--;
- }
- // 返回结果表示当前是否可以添加
- internal bool tryAdd(float x, float y, float direction)
- {
- if (mAdded == false)
- {
- this.mAdded = true;
- this.mMarkRemoved = false;
- this.mID = mZone.genObjectID();
- this.mPos.SetX(x);
- this.mPos.SetY(y);
- this.mPosPrevFrame.SetX(x);
- this.mPosPrevFrame.SetY(y);
- this.mDirection = direction;
- mZone.swapSpace(this, true);
- if (mZone.HasArea) changeArea();
- return true;
- }
- return false;
- }
- // 更新坐标
- internal virtual bool updatePos(InstanceZone zone)
- {
- if (mMarkRemoved) return false;
- bool ret = false;
- if (!mPosPrevFrame.Equals(mPos))
- {
- SpaceDivision.SpaceCellNode old_cell = CurrentSpaceCellNode;
- if (zone.swapSpace(this, IsAffectNearChange))
- {
- SpaceDivision.SpaceCellNode new_cell = CurrentSpaceCellNode;
- if (mOnObjectSpaceChanged != null)
- {
- mOnObjectSpaceChanged.Invoke(this, old_cell, new_cell);
- }
- }
- if (mZone.HasArea) changeArea();
- ret = true;
- }
- else if (mDirectionPrevFrame != Direction)
- {
- ret = true;
- }
- else if (mZone.IsSyncZ && mPosZPrevFrame != Z)
- {
- ret = true;
- }
- mPosPrevFrame.SetX(mPos.X);
- mPosPrevFrame.SetY(mPos.Y);
- mPosZPrevFrame = Z;
- mDirectionPrevFrame = Direction;
- mNeedGenSyncPos = ret;
- return ret;
- }
- internal void onAdded(InstanceZone zon, bool pointLv = false)
- {
- if (mOnObjectAdded != null)
- {
- mOnObjectAdded.Invoke(this);
- }
- this.onAdded(pointLv);
- }
- internal void onRemoved(InstanceZone zone)
- {
- this.mAdded = false;
- this.mMarkRemoved = true;
- this.mCurrentArea = null;
- zone.clearSpace(this);
- this.setAoiStatus(null);
- this.onRemoved();
- if (mOnObjectRemoved != null)
- {
- mOnObjectRemoved.Invoke(this);
- }
- }
- // 返回结果表示是否位移
- internal void onUpdate(InstanceZone zone, bool slowRefresh)
- {
- this.onUpdate(slowRefresh);
- if (!IsPaused)
- {
- mCurPassTimeMS += zone.UpdateIntervalMS;
- mQueryPassTimeMS = (int)mCurPassTimeMS;
- }
- else if (mPauseTime != null)
- {
- if (mPauseTime.Update(zone.UpdateIntervalMS))
- {
- mIsPause = false;
- mPauseTime = null;
- }
- }
- }
- // 获取队伍的天命属性加成
- public virtual int GetTeamFateValue(UnitFateType fateType)
- {
- return 0;
- }
- internal void onSendingEvent(ref ObjectEvent evt)
- {
- if (mOnObjectSendingEvent != null)
- {
- mOnObjectSendingEvent.Invoke(this, ref evt);
- }
- }
- private void changeArea()
- {
- ZoneArea old_area = mCurrentArea;
- ZoneArea new_area = mZone.GetArea(mPos.X, mPos.Y);
- if (new_area != old_area)
- {
- mCurrentArea = new_area;
- mZone.swapArea(this, old_area, new_area);
- onAreaChanged(old_area, new_area);
- if (mOnObjectAreaChanged != null)
- {
- mOnObjectAreaChanged.Invoke(this, old_area, new_area);
- }
- }
- }
- protected internal virtual bool GenSyncPos(ref SyncPosEvent.UnitPos ret)
- {
- if (mNeedGenSyncPos)
- {
- ret.SetObject(this);
- return true;
- }
- return false;
- }
- public SyncPosEvent.UnitPos GetSyncPos()
- {
- var ret = new SyncPosEvent.UnitPos();
- ret.SetObject(this);
- return ret;
- }
- //----------------------------------------------------------------------------------------
- /// <summary>
- /// 暂停逻辑
- /// </summary>
- /// <param name="pause"></param>
- /// <param name="timeMS"></param>
- public virtual void Pause(bool pause, int timeMS = 0)
- {
- this.mIsPause = pause;
- if (pause && timeMS > 0)
- {
- this.mPauseTime = new TimeExpire<int>(timeMS);
- }
- else { this.mPauseTime = null; }
- }
- //----------------------------------------------------------------------------------------
- #region DELEGATE
- /// <summary>
- /// 单位添加到场景
- /// </summary>
- /// <param name="obj"></param>
- public delegate void ObjectAddedHandler(InstanceZoneObject obj);
- /// <summary>
- /// 单位被移除触发
- /// </summary>
- /// <param name="obj"></param>
- public delegate void ObjectRemovedHandler(InstanceZoneObject obj);
- /// <summary>
- /// 单位空间分割区域改变时触发
- /// </summary>
- /// <param name="obj"></param>
- /// <param name="old_node"></param>
- /// <param name="new_node"></param>
- public delegate void ObjectSpaceChangedHandler(InstanceZoneObject obj, SpaceDivision.SpaceCellNode old_node, SpaceDivision.SpaceCellNode new_node);
- /// <summary>
- /// 单位空间分割区域改变时触发
- /// </summary>
- /// <param name="obj"></param>
- /// <param name="old_node"></param>
- /// <param name="new_node"></param>
- public delegate void ObjectAreaChangedHandler(InstanceZoneObject obj, ZoneArea old_node, ZoneArea new_node);
- /// <summary>
- /// 单位发送事件时触发
- /// </summary>
- /// <param name="obj"></param>
- /// <param name="evt"></param>
- public delegate void ObjectSendingEventHandler(InstanceZoneObject obj, ref ObjectEvent evt);
- private ObjectAddedHandler mOnObjectAdded;
- private ObjectRemovedHandler mOnObjectRemoved;
- private ObjectSpaceChangedHandler mOnObjectSpaceChanged;
- private ObjectAreaChangedHandler mOnObjectAreaChanged;
- private ObjectSendingEventHandler mOnObjectSendingEvent;
- public event ObjectAddedHandler OnObjectAdded { add { mOnObjectAdded += value; } remove { mOnObjectAdded -= value; } }
- public event ObjectRemovedHandler OnObjectRemoved { add { mOnObjectRemoved += value; } remove { mOnObjectRemoved -= value; } }
- public event ObjectSpaceChangedHandler OnObjectSpaceChanged { add { mOnObjectSpaceChanged += value; } remove { mOnObjectSpaceChanged -= value; } }
- public event ObjectAreaChangedHandler OnObjectAreaChanged { add { mOnObjectAreaChanged += value; } remove { mOnObjectAreaChanged -= value; } }
- public event ObjectSendingEventHandler OnObjectSendingEvent { add { mOnObjectSendingEvent += value; } remove { mOnObjectSendingEvent -= value; } }
- protected virtual void clearEvents()
- {
- mOnObjectAdded = null;
- mOnObjectRemoved = null;
- mOnObjectSpaceChanged = null;
- mOnObjectAreaChanged = null;
- mOnObjectSendingEvent = null;
- }
- #endregion
- //---------------------------------------------------------------------------------------------------------
- #region ABSTRACT
- /// <summary>
- /// 地图阻挡 ?
- /// </summary>
- abstract public bool IntersectMap { get; }
- /// <summary>
- /// 单位阻挡
- /// </summary>
- abstract public bool IntersectObj { get; }
- /// <summary>
- /// 是否可以动
- /// </summary>
- abstract public bool Moveable { get; }
- /// <summary>
- /// 自身体积(半径)
- /// </summary>
- abstract public float BodyBlockSize { get; }
- /// <summary>
- /// 受击半径
- /// </summary>
- abstract public float BodyHitSize { get; }
- /// <summary>
- /// 身体高度
- /// </summary>
- abstract public float BodyHeight { get; }
- /// <summary>
- /// 是否同步客户端
- /// </summary>
- abstract public bool ClientVisible { get; }
- abstract public float Weight { get; }
- /// <summary>
- /// 是否允许帧同步
- /// </summary>
- abstract public bool SyncPos { get; }
- abstract protected void onUpdate(bool slowRefresh);
- abstract protected void onAdded(bool pointLv);
- abstract protected void onRemoved();
- /*
- /// <summary>
- /// 被攻击到
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="attack"></param>
- /// <returns></returns>
- virtual internal bool onHitAttack(InstanceUnit sender, AttackProp attack) { return false; }
- */
- /// <summary>
- /// 获取同步信息
- /// </summary>
- abstract public SyncObjectInfo GenSyncInfo(bool network);
- #endregion
- //---------------------------------------------------------------------------------------
- /// <summary>
- /// 直接转向
- /// </summary>
- /// <param name="x"></param>
- /// <param name="y"></param>
- public virtual void faceTo(float x, float y)
- {
- if (mPos.X == x && mPos.Y == y)
- {
- return;
- }
- this.faceTo((float)(Math.Atan2(y - mPos.Y, x - mPos.X)));
- }
- /// <summary>
- /// 直接转向
- /// </summary>
- /// <param name="d"></param>
- public virtual void faceTo(float d)
- {
- this.mDirection = d;
- }
- /// <summary>
- /// 基于当前角度转向
- /// </summary>
- /// <param name="add"></param>
- public virtual void turn(float add)
- {
- this.mDirection += add;
- }
- public bool setPos(float x, float y, bool touchMap = false)
- {
- if (touchMap)
- {
- if (!mZone.TryTouchMap(this, x, y))
- {
- this.mPos.SetX(x);
- this.mPos.SetY(y);
- Parent.swapSpace(this, true);
- return true;
- }
- return false;
- }
- else
- {
- this.mPos.SetX(x);
- this.mPos.SetY(y);
- Parent.swapSpace(this, true);
- return true;
- }
- }
- public bool setPos(float x, float y, float z, bool touchMap = false)
- {
- if (touchMap)
- {
- if (!mZone.TryTouchMap(this, x, y))
- {
- this.mPos.SetX(x);
- this.mPos.SetY(y);
- this.Z = z;
- Parent.swapSpace(this, true);
- return true;
- }
- return false;
- }
- else
- {
- this.mPos.SetX(x);
- this.mPos.SetY(y);
- this.Z = z;
- Parent.swapSpace(this, true);
- return true;
- }
- }
- public void setAoiStatus(ObjectAoiStatus aoi)
- {
- if (this.mAoiStatus != aoi)
- {
- if (this.mAoiStatus != null)
- {
- try
- {
- if(mAoiStatus !=null && mAoiStatus.IsNeedNotifyClient && this is InstancePlayer)
- {
- var ce = new ChatEvent(ChatMessageType.SystemToPlayer);
- ce.ToPlayerUUID = (this as InstancePlayer).PlayerUUID;
- ce.Message = "LeaveAOI";
- this.Parent.queueEvent(ce);
- }
- this.mAoiStatus.RemoveObject(this);
- }
- catch(Exception e)
- {
- log.Warn("setAoiStatus catch: " + this.Parent.GetSceneID() + ", " + (mAoiStatus == null ? "aoi null" : mAoiStatus.ToString()) + ", " +
- this.GetTemplateData() + ", setaoI:" + (aoi == null ? "aoi null" : aoi.ToString()) + ", " + e);
- }
- }
- this.mAoiStatus = aoi;
- if (this.mAoiStatus != null)
- {
- this.mAoiStatus.AddObject(this);
- if (this is InstancePlayer && mAoiStatus.IsNeedNotifyClient)
- {
- var ce = new ChatEvent(ChatMessageType.SystemToPlayer);
- ce.ToPlayerUUID = (this as InstancePlayer).PlayerUUID;
- ce.Message = "EnterAOI";
- this.Parent.queueEvent(ce);
- }
- }
- InstancePlayer player = this as InstancePlayer;
- if(player != null)
- {
- //玩家停止技能行为
- StateSkill state = player.CurrentState as StateSkill;
- if (state != null)
- {
- PlayerSkillStopEvent evt = new PlayerSkillStopEvent(player.ID, state.SkillData.ID);
- player.queueEvent(evt);
- state.Skill.ForceIntoCD();
- player.changeState(new StateIdle(player), true);
- }
- }
- }
- }
- public virtual void SendForceSync()
- {
- mForceSync.object_id = this.ID;
- mForceSync.X = this.X;
- mForceSync.Y = this.Y;
- mForceSync.Direction = this.Direction;
- Parent.queueObjectEvent(this, mForceSync);
- }
- //---------------------------------------------------------------------------------------------------------
- protected virtual void onAreaChanged(ZoneArea old_area, ZoneArea new_area) { }
- /// <summary>
- /// 在移动时被某个单位阻挡
- /// </summary>
- /// <param name="obj"></param>
- protected virtual void onMoveBlockWithObject(InstanceZoneObject obj) { }
- /// <summary>
- /// 阻挡到其他单位移动
- /// </summary>
- /// <param name="obj"></param>
- /// <returns >通知其他单位自己可以让开</returns>
- protected virtual bool onBlockOther(InstanceZoneObject obj) { return false; }
- //---------------------------------------------------------------------------------------------------------
- /// <summary>
- /// 无碰撞移动
- /// </summary>
- /// <param name="direction"></param>
- /// <param name="speedSEC"></param>
- /// <param name="intervalMS"></param>
- public void flyTo(float direction, float speedSEC, int intervalMS)
- {
- float distance = MoveHelper.GetDistance(intervalMS, speedSEC);
- MathVector.movePolar(mPos, direction, distance);
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="x"></param>
- /// <param name="y"></param>
- /// <param name="speedSEC"></param>
- /// <param name="intervalMS"></param>
- /// <returns>是否到达终点</returns>
- public bool flyToTarget(float x, float y, float speedSEC, int intervalMS)
- {
- float distance = MoveHelper.GetDistance(intervalMS, speedSEC);
- return MathVector.moveTo(mPos, x, y, distance);
- }
- public void flyToTargetTunning(float x, float y, float speedSEC, float tunningSpeedSEC, int intervalMS)
- {
- MoveHelper.MoveToTargetTunning(ref mPos, ref mDirection, x, y, speedSEC, tunningSpeedSEC, intervalMS);
- }
- //曲线移动
- public void CurveMoveTo(Vector2 startPos, Vector2 handlePos, float endX, float endY, float fStep, float speedSEC, int intervalMS)
- {
- //float pX1 = startPos.X * (1 - fStep) + handlePos.X * fStep;
- //float pY1 = startPos.Y * (1 - fStep) + handlePos.Y * fStep;
- //float pX2 =
- //Vector3 result = (1 - fStep) * p0p1 + fStep * p1p2;
- }
- /// <summary>
- /// 越过单位跳跃
- /// </summary>
- /// <param name="direction"></param>
- /// <param name="speedSEC"></param>
- /// <param name="intervalMS"></param>
- /// <param name="ignore_z"></param>
- /// <returns>是否到达终点</returns>
- public bool jumpTo(float direction, float speedSEC, int intervalMS, bool ignore_z = true)
- {
- float distance = MoveHelper.GetDistance(intervalMS, speedSEC);
- float dx = (float)(Math.Cos(direction) * distance);
- float dy = (float)(Math.Sin(direction) * distance);
- if (IntersectMap)
- {
- float oldx = mPos.X;
- float oldy = mPos.Y;
- switch (Parent.TryMoveToMapBorder(this, ref mPos, dx, dy))
- {
- case AstarManhattan.TryMoveToMapBorderResult.BLOCK:
- return true;
- }
- if (ignore_z)
- {
- if (mZone.intersectNearStaticBlockable(this) != null)
- {
- mPos.SetY(oldy);
- mPos.SetX(oldx);
- return true;
- }
- }
- else
- {
- if (mZone.intersectNearStaticBlockableZ(this) != null)
- {
- mPos.SetY(oldy);
- mPos.SetX(oldx);
- return true;
- }
- }
- }
- else
- {
- this.mPos.AddX(dx);
- this.mPos.AddY(dy);
- }
- return false;
- }
- public bool jumpToTarget(float x, float y, float speedSEC, int intervalMS, bool ignore_z = true)
- {
- float distance = MoveHelper.GetDistance(intervalMS, speedSEC);
- float ddx = x - mPos.X;
- float ddy = y - mPos.Y;
- float direction = MathVector.getDegree(ddx, ddy);
- float dx = (float)(Math.Cos(direction) * distance);
- float dy = (float)(Math.Sin(direction) * distance);
- bool minstep = false;
- if (Math.Abs(ddx) < distance && Math.Abs(ddy) < distance)
- {
- dx = ddx;
- dy = ddy;
- minstep = true;
- }
- if (IntersectMap)
- {
- float oldx = mPos.X;
- float oldy = mPos.Y;
- switch (Parent.TryMoveToMapBorder(this, ref mPos, dx, dy))
- {
- case AstarManhattan.TryMoveToMapBorderResult.BLOCK:
- if (IntersectObj) ElasticOtherObjects();
- return true;
- }
- if (ignore_z)
- {
- if (mZone.intersectNearStaticBlockable(this) != null)
- {
- mPos.SetY(oldy);
- mPos.SetX(oldx);
- if (IntersectObj) ElasticOtherObjects();
- return true;
- }
- }
- else
- {
- if (mZone.intersectNearStaticBlockableZ(this) != null)
- {
- mPos.SetY(oldy);
- mPos.SetX(oldx);
- if (IntersectObj) ElasticOtherObjects();
- return true;
- }
- }
- }
- else
- {
- this.mPos.AddX(dx);
- this.mPos.AddY(dy);
- }
- return minstep;
- }
- //---------------------------------------------------------------------------------------------------------
- //---------------------------------------------------------------------------------------------------------
- /// <summary>
- /// 移动到目标点
- /// </summary>
- /// <param name="angle"></param>
- /// <param name="speedSEC"></param>
- /// <param name="intervalMS"></param>
- /// <returns>可以顺利移动</returns>
- public MoveBlockResult moveBlockTo(float angle, float speedSEC, int intervalMS)
- {
- float dd = MoveHelper.GetDistance(intervalMS, speedSEC);
- float dx = (float)(Math.Cos(angle) * dd);
- float dy = (float)(Math.Sin(angle) * dd);
- return moveBlock(dx, dy);
- }
- /// <summary>
- /// 移动到目标点
- /// </summary>
- /// <param name="x"></param>
- /// <param name="y"></param>
- /// <param name="speedSEC"></param>
- /// <param name="intervalMS"></param>
- /// <returns>可以顺利移动</returns>
- public MoveBlockResult moveBlockTo(float x, float y, float speedSEC, int intervalMS)
- {
- if (mPos.X == x && mPos.Y == y)
- {
- MoveBlockResult result = new MoveBlockResult(MoveResult.MOVE_RESULT_ARRIVED);
- return result;
- }
- float distance = MoveHelper.GetDistance(intervalMS, speedSEC);
- float ddx = x - mPos.X;
- float ddy = y - mPos.Y;
- if (Math.Abs(ddx) < distance && Math.Abs(ddy) < distance)
- {
- MoveBlockResult result = moveBlock(ddx, ddy);
- if ((result.result & MoveResult.RESULTS_MOVE_END) != 0)
- {
- }
- else
- {
- result.result |= MoveResult.MOVE_RESULT_ARRIVED;
- }
- return result;
- }
- else
- {
- float oldx = mPos.X;
- float oldy = mPos.Y;
- float direction = (float)(Math.Atan2(ddy, ddx));
- float dx = (float)(Math.Cos(direction) * distance);
- float dy = (float)(Math.Sin(direction) * distance);
- MoveBlockResult result = moveBlock(dx, dy);
- ddx = Math.Abs(mPos.X - oldx);
- ddy = Math.Abs(mPos.Y - oldy);
- float minstep = Parent.MinStep;
- if (ddx < minstep && ddy < minstep)
- {
- result.result |= MoveResult.MOVE_RESULT_MIN_STEP;
- }
- return result;
- }
- }
- /// <summary>
- /// 尝试碰撞移动偏移量
- /// </summary>
- /// <param name="dx"></param>
- /// <param name="dy"></param>
- /// <returns></returns>
- public MoveBlockResult moveBlock(float dx, float dy)
- {
- float oldx = mPos.X;
- float oldy = mPos.Y;
- MoveBlockResult result = new MoveBlockResult(0);
- if (IntersectMap)
- {
- //尝试地图碰撞移动//
- var res = Parent.TryMoveToMapBorder(this, ref mPos, dx, dy);
- switch (res)
- {
- case AstarManhattan.TryMoveToMapBorderResult.BLOCK:
- result.result |= MoveResult.MOVE_RESULT_TOUCH_MAP_ALL;
- result.result |= MoveResult.MOVE_RESULT_BLOCK_MAP;
- return result;
- case AstarManhattan.TryMoveToMapBorderResult.TOUCH:
- result.result |= MoveResult.MOVE_RESULT_TOUCH_MAP_ALL;
- break;
- case AstarManhattan.TryMoveToMapBorderResult.ARRIVE:
- break;
- }
- //和建筑碰撞//
- if (this.IntersectObj)
- {
- InstanceZoneObject bu = mZone.intersectNearStaticBlockable(this);
- result.obj = bu;
- if (bu != null)
- {
- mPos.SetY(oldy);
- mPos.SetX(oldx);
- result.result |= MoveResult.MOVE_RESULT_BLOCK_OBJ;
- //恢复到原来位置也碰撞的话,就弹开//
- if (mZone.TouchObject2(this, bu))
- {
- ElasticOtherObject(bu);
- }
- onMoveBlockWithObject(bu);
- }
- return result;
- }
- }
- else
- {
- this.mPos.AddX(dx);
- this.mPos.AddY(dy);
- }
- if (this.IntersectObj)
- {
- //和单位碰撞//
- InstanceZoneObject bu = mZone.intersectNearUnit(this);
- result.obj = bu;
- if (bu != null)
- {
- mPos.SetY(oldy);
- mPos.SetX(oldx);
- if (bu.onBlockOther(this))
- {
- result.result |= MoveResult.MOVE_RESULT_TOUCH_OBJ_GETAWAY;
- }
- result.result |= MoveResult.MOVE_RESULT_BLOCK_OBJ;
- if (mZone.TouchObject2(this, bu))
- {
- //恢复到原来位置也碰撞的话,就弹开//
- if (ElasticOtherObject(bu) == false)
- {
- this.mPos.AddX(dx);
- this.mPos.AddY(dy);
- }
- }
- onMoveBlockWithObject(bu);
- }
- }
- return result;
- }
- /// <summary>
- /// 挤开对方的移动方式
- /// </summary>
- /// <param name="x"></param>
- /// <param name="y"></param>
- /// <param name="speedSEC"></param>
- /// <param name="intervalMS"></param>
- /// <returns>TRUE=无法移动</returns>
- public MoveImpactResult moveImpactTo(float x, float y, float speedSEC, int intervalMS)
- {
- float minstep = Parent.MinStep;
- float distance = MoveHelper.GetDistance(intervalMS, speedSEC);
- if (Math.Abs(distance) < minstep)
- {
- return MoveImpactResult.MOVE_RESULT_MIN_STEP;
- }
- float ddx = x - mPos.X;
- float ddy = y - mPos.Y;
- if (Math.Abs(ddx) < distance && Math.Abs(ddy) < distance)
- {
- return MoveImpactResult.MOVE_RESULT_MIN_STEP;
- }
- float angle = MathVector.getDegree(ddx, ddy);
- return moveImpactInner(angle, distance, 0);
- }
- /// <summary>
- /// 挤开对方的移动方式
- /// </summary>
- /// <param name="angle"></param>
- /// <param name="speedSEC"></param>
- /// <param name="intervalMS"></param>
- /// <returns>TRUE=无法移动</returns>
- public MoveImpactResult moveImpact(float angle, float speedSEC, int intervalMS)
- {
- float minstep = Parent.MinStep;
- float distance = MoveHelper.GetDistance(intervalMS, speedSEC);
- if (Math.Abs(distance) < minstep)
- {
- return MoveImpactResult.MOVE_RESULT_MIN_STEP;
- }
- return moveImpactInner(angle, distance, 0);
- }
- public MoveImpactResult moveImpactDistance(float angle, float distance)
- {
- float minstep = Parent.MinStep;
- if (Math.Abs(distance) < minstep)
- {
- return MoveImpactResult.MOVE_RESULT_MIN_STEP;
- }
- return moveImpactInner(angle, distance, 0);
- }
- protected virtual MoveImpactResult moveImpactInner(float angle, float distance, int depth)
- {
- MoveImpactResult ret = MoveImpactResult.MOVE_SMOOTH;
- float dx = (float)(Math.Cos(angle) * distance);
- float dy = (float)(Math.Sin(angle) * distance);
- float oldx = mPos.X;
- float oldy = mPos.Y;
- if (IntersectMap)
- {
- switch (Parent.TryMoveToMapBorder(this, ref mPos, dx, dy))
- {
- case AstarManhattan.TryMoveToMapBorderResult.BLOCK:
- ret |= MoveImpactResult.MOVE_RESULT_BLOCK_MAP;
- ret |= MoveImpactResult.MOVE_RESULT_TOUCH_MAP;
- return ret;
- case AstarManhattan.TryMoveToMapBorderResult.TOUCH:
- ret |= MoveImpactResult.MOVE_RESULT_TOUCH_MAP;
- break;
- case AstarManhattan.TryMoveToMapBorderResult.ARRIVE:
- break;
- }
- }
- else
- {
- this.mPos.AddX(dx);
- this.mPos.AddY(dy);
- }
- if (!this.IntersectObj)
- {
- if (IntersectMap)
- {
- InstanceZoneObject bu = mZone.intersectNearStaticBlockable(this);
- if (bu != null)
- {
- mPos.SetY(oldy);
- mPos.SetX(oldx);
- ret |= MoveImpactResult.MOVE_RESULT_BLOCK_OBJ;
- ret |= MoveImpactResult.MOVE_RESULT_TOUCH_OBJ;
- return ret;
- }
- }
- return ret;
- }
- else
- {
- uint max_depth = Templates.CFG.GLOBAL_MOVE_IMPACT_DEPTH;
- bool touched = Parent.ForEachNearObjects(mPos.X, mPos.Y, (InstanceZoneObject o, ref bool cancel) =>
- {
- if (o != this && o.IntersectObj && Parent.TouchObject2(this, o))
- {
- ret |= MoveImpactResult.MOVE_RESULT_TOUCH_OBJ;
- if ((!o.IsStaticBlockable) && (o.Weight <= this.Weight))
- {
- if (depth < max_depth)
- {
- float targetAngle = MathVector.getDegree(this.X, this.Y, o.X, o.Y);
- float ddr = MathVector.getDistance(o.mPos, this.mPos);
- float bdr = (this.BodyBlockSize + o.BodyBlockSize);
- o.moveImpactInner(targetAngle, (bdr - ddr), depth + 1);
- }
- else
- {
- this.mPos.SetX(oldx);
- this.mPos.SetY(oldy);
- cancel = true;
- ret |= MoveImpactResult.MOVE_RESULT_BLOCK_OBJ;
- }
- }
- else
- {
- this.mPos.SetX(oldx);
- this.mPos.SetY(oldy);
- cancel = true;
- ret |= MoveImpactResult.MOVE_RESULT_BLOCK_OBJ;
- if (Parent.TouchObject2(this, o))
- {
- float targetAngle = MathVector.getDegree(o.X, o.Y, this.X, this.Y);
- float ddr = MathVector.getDistance(o.mPos, this.mPos);
- float bdr = (this.BodyBlockSize + o.BodyBlockSize);
- //强制将自己移动到某处//
- this.moveLinearMap((bdr - ddr), targetAngle);
- }
- }
- }
- });
- return ret;
- }
- }
- //-------------------------------------------------------------------------------------------------------//
- /// <summary>
- /// 线性移动,只和地图碰撞
- /// </summary>
- /// <param name="distance"></param>
- /// <param name="angle"></param>
- /// <returns>和地图碰撞</returns>
- public bool moveLinearMap(float distance, float angle)
- {
- float dx = (float)(Math.Cos(angle) * distance);
- float dy = (float)(Math.Sin(angle) * distance);
- float touch_x, touch_y, touch_d;
- if (Parent.PathFinder.GetLineTouchPoint(mPos.X, mPos.Y, mPos.X + dx, mPos.Y + dy, out touch_x, out touch_y, out touch_d))
- {
- MathVector.movePolar(ref touch_x, ref touch_y, angle, -Parent.MinStep);
- mPos.SetX(touch_x);
- mPos.SetY(touch_y);
- return true;
- }
- mPos.AddX(dx);
- mPos.AddY(dy);
- return false;
- }
- /// <summary>
- /// 线性移动,只和地图碰撞
- /// </summary>
- /// <param name="dx"></param>
- /// <param name="dy"></param>
- /// <returns>和地图碰撞</returns>
- public bool moveLinearMap2(float dx, float dy)
- {
- float touch_x, touch_y, touch_d;
- if (Parent.PathFinder.GetLineTouchPoint(mPos.X, mPos.Y, mPos.X + dx, mPos.Y + dy, out touch_x, out touch_y, out touch_d))
- {
- MathVector.movePolar(ref touch_x, ref touch_y, MathVector.getDegree(dx, dy), -Parent.MinStep);
- mPos.SetX(touch_x);
- mPos.SetY(touch_y);
- return true;
- }
- mPos.AddX(dx);
- mPos.AddY(dy);
- return false;
- }
- /// <summary>
- /// 线性移动,不会穿
- /// </summary>
- /// <param name="distance"></param>
- /// <param name="angle"></param>
- /// <param name="ignore_map"></param>
- /// <param name="ignore_obj"></param>
- /// <returns></returns>
- public MoveBlockResult moveLinear(float distance, float angle, bool ignore_map = false, bool ignore_obj = true)
- {
- MoveBlockResult ret = new MoveBlockResult();
- float dx = (float)(Math.Cos(angle) * distance);
- float dy = (float)(Math.Sin(angle) * distance);
- float dst_x = mPos.X + dx;
- float dst_y = mPos.Y + dy;
- float tgt_x = dst_x;
- float tgt_y = dst_y;
- if (!ignore_map)
- {
- float touch_x, touch_y, touch_d;
- if (Parent.PathFinder.GetLineTouchPoint(mPos.X, mPos.Y, dst_x, dst_y, out touch_x, out touch_y, out touch_d))
- {
- ret.result |= MoveResult.MOVE_RESULT_TOUCH_MAP_ALL;
- if (dst_x == touch_x && dst_y == touch_y)
- {
- ret.result |= MoveResult.MOVE_RESULT_BLOCK_MAP;
- return ret;
- }
- float minstep = Parent.MinStep;
- MathVector.movePolar(ref touch_x, ref touch_y, angle, -minstep);
- dst_x = touch_x;
- dst_y = touch_y;
- distance = (touch_d - minstep);
- }
- }
- using (var list = ListObjectPool<InstanceZoneObject>.AllocAutoRelease())
- {
- if (!ignore_obj)
- {
- Parent.getObjectsRoundLineRange<InstanceZoneObject>(
- Collider.Object_BlockBody_TouchRoundLine,
- mPos.X, mPos.Y, dst_x, dst_y, BodyBlockSize,
- list, AoiStatus);
- }
- else if (!ignore_map)
- {
- Parent.getObjectsRoundLineRange<InstanceZoneObject>((o, x1, y1, x2, y2, r) =>
- {
- if (o.IsStaticBlockable && o.IntersectObj)
- {
- return Collider.Object_BlockBody_TouchRoundLine(o, x1, y1, x2, y2, r);
- }
- return false;
- }, mPos.X, mPos.Y, dst_x, dst_y, BodyBlockSize, list, AoiStatus);
- }
- if (list.Count > 0)
- {
- list.Sort(new ObjectBodySorterNearest<InstanceZoneObject>(mPos.X, mPos.Y, this.BodyBlockSize));
- ret.result |= MoveResult.MOVE_RESULT_BLOCK_OBJ;
- ret.obj = list[0];
- distance = MathVector.getDistance(mPos.X, mPos.Y, ret.obj.X, ret.obj.Y) - this.BodyBlockSize - ret.obj.BodyBlockSize;
- distance = Math.Max(distance, 0);
- dx = (float)(Math.Cos(angle) * distance);
- dy = (float)(Math.Sin(angle) * distance);
- dst_x = mPos.X;
- dst_y = mPos.Y;
- if (!ignore_map)
- {
- Parent.TryMoveToMapBorder(this, ref dst_x, ref dst_y, dx, dy);
- }
- else
- {
- dst_x += dx;
- dst_y += dy;
- }
- }
- }
- mPos.SetX(dst_x);
- mPos.SetY(dst_y);
- if (tgt_x == dst_x && tgt_y == dst_y)
- {
- ret.result |= MoveResult.MOVE_RESULT_ARRIVED;
- }
- return ret;
- }
- public bool moveBlink(BlinkMove blink, Vector2 targetPos = null, InstanceZoneObject targetUnit = null)
- {
- switch (blink.MType)
- {
- case BlinkMove.BlinkMoveType.MoveToForward:
- moveLinear(blink.Distance,
- mDirection + blink.DirectionOffset,
- blink.NoneTouchMap || !IntersectMap,
- blink.NoneTouchObj || !IntersectObj);
- return true;
- case BlinkMove.BlinkMoveType.MoveToBackward:
- moveLinear(-blink.Distance,
- mDirection + blink.DirectionOffset,
- blink.NoneTouchMap || !IntersectMap,
- blink.NoneTouchObj || !IntersectObj);
- return true;
- case BlinkMove.BlinkMoveType.MoveToTargetPos:
- if (targetPos != null)
- {
- if (CMath.includeRoundPoint(X, Y, blink.Distance, targetUnit.X, targetUnit.Y))
- {
- float angle = MathVector.getDegree(this.X, this.Y, targetPos.X, targetPos.Y);
- float distance = Math.Max(MathVector.getDistance(this.X, this.Y, targetPos.X, targetPos.Y), blink.Distance);
- moveLinear(distance,
- angle + blink.DirectionOffset,
- blink.NoneTouchMap || !IntersectMap,
- blink.NoneTouchObj || !IntersectObj);
- return true;
- }
- }
- break;
- case BlinkMove.BlinkMoveType.MoveToTargetUnitFace:
- if (targetUnit != null)
- {
- if (CMath.includeRoundPoint(X, Y, blink.Distance, targetUnit.X, targetUnit.Y))
- {
- mPos.SetX(targetUnit.X);
- mPos.SetY(targetUnit.Y);
- mDirection = targetUnit.Direction + CMath.PI_F + blink.DirectionOffset;
- moveLinear(
- targetUnit.BodyBlockSize + this.BodyBlockSize,
- targetUnit.Direction,
- blink.NoneTouchMap || !IntersectMap,
- blink.NoneTouchObj || !IntersectObj);
- return true;
- }
- }
- break;
- case BlinkMove.BlinkMoveType.MoveToTargetUnitBack:
- if (targetUnit != null)
- {
- if (CMath.includeRoundPoint(X, Y, blink.Distance, targetUnit.X, targetUnit.Y))
- {
- mPos.SetX(targetUnit.X);
- mPos.SetY(targetUnit.Y);
- mDirection = targetUnit.Direction + blink.DirectionOffset;
- moveLinear(
- -(targetUnit.BodyBlockSize + this.BodyBlockSize),
- targetUnit.Direction,
- blink.NoneTouchMap || !IntersectMap,
- blink.NoneTouchObj || !IntersectObj);
- return true;
- }
- }
- break;
- }
- return false;
- }
- /// <summary>
- /// 挤开其他和自己重叠的单位,或者被Weight大于自己的人挤开
- /// </summary>
- /// <returns></returns>
- public bool ElasticOtherObjects()
- {
- bool force_sync = false;
- Parent.ForEachNearObjects(X, Y, (InstanceZoneObject o, ref bool cancel) =>
- {
- if ((o != this) && (o.IntersectObj) && Parent.TouchObject2(this, o))
- {
- if (ElasticOtherObject(o))
- {
- force_sync = true;
- }
- }
- });
- return force_sync;
- }
- /// <summary>
- /// 挤开其他和自己重叠的单位,或者被Weight大于自己的人挤开
- /// </summary>
- /// <param name="o"></param>
- /// <returns>自己发生位移</returns>
- public bool ElasticOtherObject(InstanceZoneObject o)
- {
- float targetAngle = (float)(RandomN.NextDouble() * CMath.PI_MUL_2);
- float ddr = MathVector.getDistance(this.X, this.Y, o.X, o.Y);
- if (ddr > 0)
- {
- targetAngle = MathVector.getDegree(this.X, this.Y, o.X, o.Y);
- }
- float bdr = (this.BodyBlockSize + o.BodyBlockSize);
- float d = (bdr - ddr);
- if (!o.Moveable)
- {
- this.moveImpactDistance(targetAngle, -d);
- return true;
- }
- else if (o.Weight > this.Weight)
- {
- this.moveImpactDistance(targetAngle, -d);
- return true;
- }
- else
- {
- o.moveImpactDistance(targetAngle, d);
- return false;
- }
- }
- }
- }
|