12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292 |
- 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();
- 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 virtual bool IsNeedProcessDead() { 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, uint customid = 0)
- {
- if (mAdded == false)
- {
- this.mAdded = true;
- this.mMarkRemoved = false;
- this.mID = customid > 0 ? customid : 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 > 0 || ddy > 0)
- {
- 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;
- }
- }
- }
- }
|