using System;
using System.Collections.Generic;
using CommonLang.Vector;
using CommonLang;
using CommonAI.Zone.Instance;
using CommonAI.RTS.Manhattan;
using CommonLang.IO;

namespace CommonAI.Zone.Helper
{
    public class MoveHelper
    {
        public static readonly int POS_PRECISION = 255;
		public static readonly float ToDirectionD8_VALUE = (float)POS_PRECISION /CMath.PI_MUL_2;

		/// <summary>
		/// 更新速度
		/// </summary>
		public static void UpdateSpeed(int intervalMS, ref float speedSec, float addSec, float accSec)
        {
            float add = 0;
            float acc = 0;
            if (addSec != 0)
            {
                add = MoveHelper.GetDistance(intervalMS, addSec);
            }
            if (accSec != 0)
            {
                acc = MoveHelper.GetDistance(intervalMS, speedSec * accSec);
            }
            speedSec += (add + acc);
        }
        public static void UpdateSpeed(int intervalMS, ref float speedSec, float addSec, float accSec, float speedMin, float speedMax)
        {
            float add = 0;
            float acc = 0;
            if (addSec != 0)
            {
                add = MoveHelper.GetDistance(intervalMS, addSec);
            }
            if (accSec != 0)
            {
                acc = MoveHelper.GetDistance(intervalMS, speedSec * accSec);
            }
            speedSec += (add + acc);
            if (speedSec > speedMax) { speedSec = speedMax; }
            if (speedSec < speedMin) { speedSec = speedMin; }
        }

        public static void UpdateMoveDistance(int intervalMS, ref float moveDistance, float speed)
        {
            moveDistance += MoveHelper.GetDistance(intervalMS, speed);
        }

        #region IO

        public static byte ToDirectionD8(float d)
        {
            return (byte)(CMath.OpitimizeRadians(d) * ToDirectionD8_VALUE);
		}
        public static float ToDirectionF32(byte d8)
        {
            return d8 * CMath.PI_MUL_2 / POS_PRECISION;
        }
        public static ushort ToPos16(float x)
        {
            return (ushort)(x * POS_PRECISION);
        }
        public static float ToPosF32(ushort x)
        {
            return ((float)x) / POS_PRECISION;
        }

        public static void WritePos(bool half, float x, IOutputStream output)
        {
            if (half)
            {
                output.PutU16(ToPos16(x));
            }
            else
            {
                output.PutF32(x);
            }
        }
        public static void WritePos(bool half, float x, float y, IOutputStream output)
        {
            if (half)
            {
                output.PutU16(ToPos16(x));
                output.PutU16(ToPos16(y));
            }
            else
            {
                output.PutF32(x);
                output.PutF32(y);
            }
        }
        public static void WriteDirection(bool half, float direction, IOutputStream output)
        {
            if (half)
            {
                output.PutU8(ToDirectionD8(direction));
            }
            else
            {
                output.PutF32(direction);
            }
        }
        public static void WritePosAndDirection(bool half, float x, float y, float direction, IOutputStream output)
        {
            if (half)
            {
                output.PutU16(ToPos16(x));
                output.PutU16(ToPos16(y));
                output.PutU8(ToDirectionD8(direction));
            }
            else
            {
                output.PutF32(x);
                output.PutF32(y);
                output.PutF32(direction);
            }
        }

        public static void ReadPos(bool half, out float x, IInputStream input)
        {
            if (half)
            {
                x = ToPosF32(input.GetU16());
            }
            else
            {
                x = input.GetF32();
            }
        }
        public static void ReadPos(bool half, out float x, out float y, IInputStream input)
        {
            if (half)
            {
                x = ToPosF32(input.GetU16());
                y = ToPosF32(input.GetU16());
            }
            else
            {
                x = input.GetF32();
                y = input.GetF32();
            }
        }

		public static void ReadPos(bool half, ref Vector2 pos, IInputStream input)
		{
			if (half)
			{
				pos.SetX(ToPosF32(input.GetU16()));
				pos.SetY(ToPosF32(input.GetU16()));
			}
			else
			{
				pos.SetX(input.GetF32());
				pos.SetY(input.GetF32());
			}
		}

		public static void ReadDirection(bool half, out float direction, IInputStream input)
        {
            if (half)
            {
                direction = ToDirectionF32(input.GetU8());
            }
            else
            {
                direction = input.GetF32();
            }
        }
        public static void ReadPosAndDirection(bool half, out float x, out float y, out float direction, IInputStream input)
        {
            if (half)
            {
                x = ToPosF32(input.GetU16());
                y = ToPosF32(input.GetU16());
                direction = ToDirectionF32(input.GetU8());
            }
            else
            {
                x = input.GetF32();
                y = input.GetF32();
                direction = input.GetF32();
            }
        }

        #endregion
        //------------------------------------------------------------------------------------

        public static float GetDistance(int timeMS, float speedSEC)
        {
            return speedSEC * timeMS / 1000f;
        }

        /// <summary>
        /// 转身算法
        /// </summary>
        /// <param name="dstD">目标角度</param>
        /// <param name="curD">当前角度</param>
        /// <param name="turnSpeedSEC">角速度</param>
        /// <param name="intervalMS">时间间隔</param>
        /// <returns></returns>
        public static float DirectionChange(float dstD, float curD, float turnSpeedSEC, int intervalMS)
        {
            if (turnSpeedSEC > 0)
            {
                float delta = turnSpeedSEC * intervalMS / 1000f;
                float dd = CMath.OpitimizeRadians(dstD) + CMath.PI_MUL_2;
                float cd = CMath.OpitimizeRadians(curD) + CMath.PI_MUL_2;
                float distanceL = Math.Abs(dd - cd);
                float distanceR = CMath.PI_MUL_2 - distanceL;
                if (distanceL > distanceR)
                {
                    if (distanceR <= delta)
                    {
                        return dstD;
                    }
                    if (dd > cd)
                    {
                        curD -= delta;
                    }
                    else
                    {
                        curD += delta;
                    }
                }
                else
                {
                    if (distanceL <= delta)
                    {
                        return dstD;
                    }
                    if (dd > cd)
                    {
                        curD += delta;
                    }
                    else
                    {
                        curD -= delta;
                    }
                }
                return curD;
            }
            return dstD;
        }

        /// <summary>
        /// 导弹一样飞向目标,并自动调整方向
        /// </summary>
        /// <param name="pos"></param>
        /// <param name="direction"></param>
        /// <param name="targetX"></param>
        /// <param name="targetY"></param>
        /// <param name="speedSEC"></param>
        /// <param name="turnSpeedSEC"></param>
        /// <param name="intervalMS"></param>
        public static void MoveToTargetTunning(ref Vector2 sPos, ref float direction, float targetX, float targetY, float speedSEC, float turnSpeedSEC, int intervalMS)
        {
            float dstD = MathVector.getDegree(targetX - sPos.X, targetY - sPos.Y);
            direction = DirectionChange(dstD, direction, turnSpeedSEC, intervalMS);
            MathVector.movePolar(ref sPos, direction, speedSEC, intervalMS);
        }


        /// <summary>
        /// 预估击飞到落下的时间
        /// </summary>
        /// <param name="z">要计算的高度</param>
        /// <param name="z_speed">Z速度</param>
        /// <param name="z_limit">Z坐标上限</param>
        /// <param name="gravity">重力加速度</param>
        /// <param name="intervalMS">时间精度,越小越精确,一般10足够精度</param>
        /// <returns></returns>
        public static int CalculateFlyTimeMS(float z, float z_speed, float z_limit, float gravity, int intervalMS = 10)
        {
            int time = 0;
            float tick_g = GetDistance(intervalMS, gravity);
            do
            {
                time += intervalMS;
                float sd = GetDistance(intervalMS, z_speed);
                z += sd;
                if (z < 0)
                {
                    time -= (int)Math.Abs(intervalMS * (z / sd));
                }
                if (z_limit != 0 && z_speed > 0 && z > z_limit)
                {
                    z_speed = 0;
                }
                z_speed -= tick_g;
            }
            while (z > 0);
            return time;
        }
        /// <summary>
        /// 给定最大距离和总时间,计算当前抛物线高度
        /// y = ax2 + bx + c;
        /// </summary>
        /// <param name="maxHeight"></param>
        /// <param name="totalTimeMS"></param>
        /// <param name="currentTimeMS"></param>
        /// <returns></returns>
        public static float CalulateParabolicHeight(float maxHeight, int totalTimeMS, int currentTimeMS)
        {
            float pct = currentTimeMS / (float)totalTimeMS;
            // 用正弦函数模拟 //
            float y = (float)(Math.Sin(pct * CMath.PI_F) * maxHeight);
            return y;
        }

        /// <summary>
        /// 计算单位击退方向
        /// </summary>
        /// <param name="damage">受击者</param>
        /// <param name="attacker">攻击者</param>
        /// <param name="mtype"></param>
        /// <returns></returns>
        public static float CalculateHitMoveDirection(InstanceUnit damage, InstanceZoneObject attacker, AttackProp.HitMoveType mtype)
        {
            switch (mtype)
            {
                case AttackProp.HitMoveType.BySenderPosition:
                    return MathVector.getDegree(attacker.X, attacker.Y, damage.X, damage.Y);
                case AttackProp.HitMoveType.BySenderDirection:
                    return attacker.Direction;
                case AttackProp.HitMoveType.BySenderLeftRight:
                    float fx = attacker.X;
                    float fy = attacker.Y;
                    MathVector.movePolar(ref fx, ref fy, attacker.Direction, 10);
                    if (CMath.PointOnLine(attacker.X, attacker.Y, fx, fy, damage.X, damage.Y) == CMath.PointOnLineResult.Left)
                    {
                        return attacker.Direction - CMath.PI_DIV_2;
                    }
                    else
                    {
                        return attacker.Direction + CMath.PI_DIV_2;
                    }
                case AttackProp.HitMoveType.ToSenderCenter:
                case AttackProp.HitMoveType.ToSenderBodySize:
                    return attacker.Direction + CMath.PI_F;
            }
            return damage.Direction + CMath.PI_F;
        }

    }



    public class PopupKeyFrames<K> : IComparer<K> where K : BaseKeyFrame
    {
        readonly private List<K> list = new List<K>();

        public int Count
        {
            get { return list.Count; }
        }

        public PopupKeyFrames()
        {
        }

        public void AddRange(ICollection<K> frames)
        {
            list.AddRange(frames);
            list.Sort(this);
        }

        /// <summary>
        /// 取出所有到时间的关键帧
        /// </summary>
        /// <param name="passTimeMS"></param>
        /// <param name="ret"></param>
        /// <returns></returns>
        public int PopKeyFrames(int passTimeMS, List<K> ret = null)
        {
            int count = 0;
            while (list.Count > 0)
            {
                int i = list.Count - 1;
                K kf = list[i];

				//不足一帧的,当帧处理
                if (kf.FrameMS <= passTimeMS + XmdsConstConfig.GAME_UPDATE_INTERVAL_MS)
                {
                    list.RemoveAt(i);
                    if (ret != null) { ret.Add(kf); }
                    count++;
                }
                else
                {
                    return count;
                }
            }
            return count;
        }

        public int Compare(K x, K y)
        {
            return y.FrameMS - x.FrameMS;
        }

    }

    public enum MoveResult : byte
    {
        MOVE_SMOOTH = 0,
        /// <summary>
        /// 标志状态,本次移动任何方向接触过地图
        /// </summary>
        MOVE_RESULT_TOUCH_MAP_ALL = 0x10,
        /// <summary>
        /// 标志状态,阻挡的单位同意让开
        /// </summary>
        MOVE_RESULT_TOUCH_OBJ_GETAWAY = 0x20,
        /// <summary>
        /// 标志状态,本次移动等等
        /// </summary>
        MOVE_RESULT_HOLD = 0x40,
        /// <summary>
        /// 标志状态,无法移动
        /// </summary>
        MOVE_RESULT_NO_WAY = 0x80,

        /// <summary>
        /// 标志判断,到达目标
        /// </summary>
        MOVE_RESULT_ARRIVED = 0x01,
        /// <summary>
        /// 标志判断,被单位阻挡
        /// </summary>
        MOVE_RESULT_BLOCK_OBJ = 0x02,
        /// <summary>
        /// 标志判断,被地图阻挡
        /// </summary>
        MOVE_RESULT_BLOCK_MAP = 0x04,
        /// <summary>
        /// 标志判断,没有达到预期距离或者移动距离太小
        /// </summary>
        MOVE_RESULT_MIN_STEP = 0x08,

        /// <summary>
        /// 【标志判断组】,被任何东西阻挡
        /// </summary>
        RESULTS_BLOCK_ANY = MOVE_RESULT_BLOCK_OBJ | MOVE_RESULT_BLOCK_MAP,
        /// <summary>
        /// 【标志判断】,移动结束(被阻挡或者到达目标)
        /// </summary>
        RESULTS_MOVE_END = MOVE_RESULT_ARRIVED | MOVE_RESULT_BLOCK_OBJ | MOVE_RESULT_BLOCK_MAP | MOVE_RESULT_NO_WAY,
    }

    public enum MoveImpactResult : byte
    {
        MOVE_SMOOTH = MoveResult.MOVE_SMOOTH,

        /// <summary>
        /// 标志状态,本次移动任何方向接触过地图
        /// </summary>
        MOVE_RESULT_TOUCH_MAP = MoveResult.MOVE_RESULT_TOUCH_MAP_ALL,
        /// <summary>
        /// 标志状态,阻挡的单位同意让开
        /// </summary>
        MOVE_RESULT_TOUCH_OBJ = MoveResult.MOVE_RESULT_TOUCH_OBJ_GETAWAY,


        /// <summary>
        /// 标志判断,被单位阻挡
        /// </summary>
        MOVE_RESULT_BLOCK_OBJ = MoveResult.MOVE_RESULT_BLOCK_OBJ,
        /// <summary>
        /// 标志判断,被地图阻挡
        /// </summary>
        MOVE_RESULT_BLOCK_MAP = MoveResult.MOVE_RESULT_BLOCK_MAP,
        /// <summary>
        /// 标志判断,没有达到预期距离或者移动距离太小
        /// </summary>
        MOVE_RESULT_MIN_STEP = MoveResult.MOVE_RESULT_MIN_STEP,

        /// <summary>
        /// 【标志判断组】,被任何东西阻挡
        /// </summary>
        RESULTS_CAN_NOT_MOVE = MOVE_RESULT_BLOCK_OBJ | MOVE_RESULT_BLOCK_MAP | MOVE_RESULT_MIN_STEP,
    }

    public struct MoveBlockResult
    {
        public MoveResult result;
        public InstanceZoneObject obj;

        public MoveBlockResult(MoveResult r)
        {
            this.result = r;
            this.obj = null;
        }
        public bool HasFlag(MoveResult flag)
        {
            return (result & flag) != 0;
        }
    }

    public struct TMoveTarget : IPositionObject
    {
        private float x;
        private float y;
        public TMoveTarget(float x, float y)
        {
            this.x = x;
            this.y = y;
        }
        public float X { get { return x; } }
        public float Y { get { return y; } }
        public float Direction { get { return 0; } }
        public float RadiusSize { get { return 0; } }
    }


    public class MoveAI
    {
        public readonly InstanceUnit unit;
        public readonly InstanceZone zone;

        private MoveTurnPosObject turnLR;
        private MoveTurnPosMapBlock turnMap;
        private AstarManhattan.MWayPoint next_path;
        private TimeExpire<int> holdTime;
        private bool mPause = true;
        private bool mOverrideActionStatus;

        private readonly int hold_time;
        private readonly int hold_max_time;
        private readonly int hold_min_time;

        public IPositionObject Target { get; private set; }

        public bool IsBypass { get; set; }
        public bool IsTurnLR { get { return turnLR != null; } }
        public float TargetX { get { return Target.X; } }
        public float TargetY { get { return Target.Y; } }
        public bool IsNoWay { get; private set; }
        public bool IsNoWayAutoFindNear { get; set; }

        public MoveAI(InstanceUnit owner, bool overrideActionStatus = true, int holdTimeMS = -1)
        {
            this.unit = owner;
            this.zone = owner.Parent;
            this.mOverrideActionStatus = overrideActionStatus;
            if (holdTimeMS < 0)
            {
                hold_time = unit.Templates.CFG.AI_MOVE_AI_HOLD_TIME_MS;
            }
            else
            {
                hold_time = holdTimeMS;
            }
            this.holdTime = new TimeExpire<int>(hold_time);
            this.turnLR = new MoveTurnPosObject(unit);
            this.turnMap = new MoveTurnPosMapBlock(unit);
            this.holdTime.End();
            this.hold_max_time = hold_time;
            this.hold_min_time = hold_time / 2;
            this.IsNoWayAutoFindNear = true;
        }

        public void Hold(int timeMS = 0)
        {
            if (timeMS <= 0)
            {
                timeMS = unit.RandomN.Next(hold_min_time, hold_max_time);
            }
            holdTime.Reset(timeMS);
        }

        public void FindPath(float x, float y)
        {
            this.FindPath(new TMoveTarget(x, y));
        }
        public void FindPath(IPositionObject target)
        {
            if (target != null)
            {
                this.Target = target;
                this.next_path = zone.findPath(unit.X, unit.Y, TargetX, TargetY);
                if (next_path == null)
                {
                    holdTime.Reset(hold_time);
                    IsNoWay = true;

                    var dis = MathVector.getDistance(unit.X, unit.Y, TargetX, TargetY);
                    //如果不能到达目的地,则找个靠近点
                    float fixx = -1, fixy = -1;
                    if (zone.GetNearWay(unit.X, unit.Y, TargetX, TargetY, dis - 1, ref fixx, ref fixy))
                    {
                        Target = new TMoveTarget(fixx, fixy);
                        next_path = zone.findPath(unit.X, unit.Y, TargetX, TargetY);
                        IsNoWay = next_path == null;
                    }
                }
                this.mPause = false;
            }
        }

        public void Pause()
        {
            this.next_path = null;
            this.turnLR.Stop();
            this.turnMap.Stop();
            this.holdTime.End();
            this.mPause = true;
        }

        public bool IsDirectLookTarget()
        {
            //if ((Target is InstanceUnit) && CMath.includeRoundPoint(unit.X, unit.Y, unit.Info.GuardRangeLimit, TargetX, TargetY))
           if ((Target is InstanceUnit))
           {
                // 地图连线无阻挡 //
                if (!zone.RaycastMap(unit, unit.X, unit.Y, TargetX, TargetY))
                {
                    return true;
                }
            }
            return false;
        }

        public MoveBlockResult Update()
        {
            MoveBlockResult result = new MoveBlockResult();
            if (Target == null)
            {
                result.result = MoveResult.MOVE_RESULT_HOLD;
                return result;
            }
            if (mPause)
            {
                result.result = MoveResult.MOVE_RESULT_HOLD;
                return result;
            }
            else if (IsNoWay)
            {
                if (IsNoWayAutoFindNear && holdTime.Update(zone.UpdateIntervalMS))
                {
                    this.next_path = zone.findPath(
                        unit.X,
                        unit.Y,
                        TargetX + (float)(unit.Parent.GridCellW * ((unit.Parent.RandomN.NextDouble() * 2) - 1)),
                        TargetY + (float)(unit.Parent.GridCellH * ((unit.Parent.RandomN.NextDouble() * 2) - 1)));
                    IsNoWay = next_path == null;
                }
				//else
				//{
				//    unit.faceTo(Target.X, Target.Y);
				//    result = unit.moveBlockTo(Target.X, Target.Y, unit.MoveSpeedSEC, zone.UpdateIntervalMS);
				//    result.result = result.result | MoveResult.MOVE_RESULT_NO_WAY;
				//    return result;
				//}

				if (IsNoWay)
				{
					if (this.unit.IsFollowMaster() && mOverrideActionStatus && unit.CurrentActionStatus != UnitActionStatus.Idle)
					{
						this.unit.Virtual.SendMsgToClient(CommonAI.XmdsConstConfig.TIPS_FOLLOW_FAIL);
						unit.SetActionStatus(UnitActionStatus.Idle);
					}
						

					result.result = result.result | MoveResult.MOVE_RESULT_NO_WAY;
					return result;
				}				
			}


            //if (!holdTime.Update(zone.UpdateIntervalMS))
            //{
                //result.result = MoveResult.MOVE_RESULT_HOLD;
                //if (mOverrideActionStatus) unit.SetActionStatus(UnitActionStatus.Idle);
			//}
			//else
			//{
			if (mOverrideActionStatus) unit.SetActionStatus(UnitActionStatus.Move);
                if (!turnMap.IsEnd)
                {
                    // 如果向目标移动过程中被地块阻挡,则向左或右调整一段距离 //
                    if (turnMap.move(unit.MoveSpeedSEC, zone.UpdateIntervalMS, out result))
                    {
                        return result;
                    }
                }
                else if (!turnLR.IsEnd)
                {
                    // 如果向目标移动过程中被单位阻挡,则向左或右调整一段距离 //
                    if (turnLR.move(unit.MoveSpeedSEC, zone.UpdateIntervalMS, out result))
                    {
                        if ((result.result & MoveResult.MOVE_RESULT_ARRIVED) != 0)
                        {
                            result.result ^= MoveResult.MOVE_RESULT_ARRIVED;
                        }
                        if ((result.result & MoveResult.MOVE_RESULT_TOUCH_OBJ_GETAWAY) != 0)
                        {
                            Hold();
                            return result;
                        }
                        else if ((result.result & MoveResult.MOVE_RESULT_BLOCK_MAP) != 0)
                        {
                            Hold();
                        }
                    }
                }
                else if (next_path != null)
                {
                    //if (IsDirectLookTarget())
                    //{
                    //    next_path = null;
                    //}
                    //else
                    //{
                        // 如果向目标移动过程中被地图阻挡,则寻路 //
                        result = unit.moveBlockTo(next_path.PosX, next_path.PosY, unit.MoveSpeedSEC, zone.UpdateIntervalMS);
                        if ((result.result & MoveResult.MOVE_RESULT_MIN_STEP) != 0 ||
                            (result.result & MoveResult.MOVE_RESULT_ARRIVED) != 0)
                        {
                        }
                        else
                        {
                            unit.faceTo(next_path.PosX, next_path.PosY);
                        }
                        if ((result.result & MoveResult.MOVE_RESULT_ARRIVED) != 0)
                        {
                            next_path = next_path.Next;
                            if (next_path != null)
                            {
                                result.result ^= MoveResult.MOVE_RESULT_ARRIVED;
                                if (IsDirectLookTarget())
                                {
                                    next_path = null;
                                }
                            }
                            else
                            {
                                next_path = zone.findPath(unit.X, unit.Y, TargetX, TargetY);
                                if (next_path == null)
                                {
                                    Hold();
                                    IsNoWay = true;
                                }
                            }
                        }
                        else if ((result.result & MoveResult.MOVE_RESULT_TOUCH_MAP_ALL) != 0 && (result.result & MoveResult.MOVE_RESULT_MIN_STEP) != 0)
                        {
                            turnMap.Start(next_path.PosX, next_path.PosY);
                        }
                        else if ((result.result & MoveResult.MOVE_RESULT_NO_WAY) != 0)
                        {
                            next_path = null;
                            IsNoWay = true;
                            //unit.faceTo(TargetX, TargetY);
                            //result = unit.moveBlockTo(TargetX, TargetY, unit.MoveSpeedSEC, zone.UpdateIntervalMS);
                        }
                        else if ((result.result & MoveResult.MOVE_RESULT_BLOCK_MAP) != 0)
                        {
                            Hold();
                            next_path = null;
                            IsNoWay = true;
                            return result;
                        }
                    //}
                }
                else
                {
                    if (!IsDirectLookTarget())
                    {
                        next_path = zone.findPath(unit.X, unit.Y, TargetX, TargetY);
                        if (next_path == null)
                        {
                            Hold();
                            IsNoWay = true;
                        }
                    }
                    else
                    {
                        unit.faceTo(TargetX, TargetY);
                        result = unit.moveBlockTo(TargetX, TargetY, unit.MoveSpeedSEC, zone.UpdateIntervalMS);
                    }
                }
            //}
            return result;
        }

        /// <summary>
        /// 如果向目标移动过程中被单位阻挡,则向左或右调整一段距离
        /// </summary>
        private class MoveTurnPosObject
        {
            public InstanceUnit Owner { get; private set; }
            public InstanceZoneObject Touched { get; private set; }
            public bool IsEnd { get; private set; }

            public float TargetX { get; private set; }
            public float TargetY { get; private set; }
            public bool FaceTo { get; private set; }

            public int TouchCount { get { return touched_list.Count; } }

            private Vector2 TargetPos;
            private HashMap<uint, InstanceZoneObject> touched_list = new HashMap<uint, InstanceZoneObject>();

            public MoveTurnPosObject(InstanceUnit owner)
            {
                this.Owner = owner;
                this.IsEnd = true;
            }

            public void Start(float targetX, float targetY, InstanceZoneObject touched)
            {
                this.Touched = touched;
                this.IsEnd = false;
                this.TargetPos = new Vector2(targetX, targetY);
                this.touched_list.Clear();
                TurnNearBypass();
            }


            public void Stop()
            {
                this.IsEnd = true;
            }

            /// <summary>
            /// 绕过某个单位移动
            /// </summary>
            /// <param name="speedSEC"></param>
            /// <param name="intervalMS"></param>
            /// <param name="result"></param>
            /// <returns>是否移动结束</returns>
            public bool move(float speedSEC, int intervalMS, out MoveBlockResult result)
            {
                Owner.faceTo(TargetX, TargetY);
                result = Owner.moveBlockTo(TargetX, TargetY, speedSEC, intervalMS);
                if (result.obj != null)
                {
                    Touched = result.obj;
                }
                if ((result.result & (MoveResult.MOVE_RESULT_BLOCK_MAP)) != 0)
                {
                    this.IsEnd = true;
                    return true;
                }
                else if ((result.result & (MoveResult.MOVE_RESULT_ARRIVED)) != 0)
                {
                    if (this.TargetX == Owner.X && this.TargetY == Owner.Y)
                    {
                        this.TargetX = TargetPos.X;
                        this.TargetY = TargetPos.Y;
                        this.IsEnd = true;
                        return true;
                    }
                }
                if (result.obj != null)
                {
                    //换一种躲避方法//
                    if (touched_list.ContainsKey(result.obj.ID))
                    {
                        TurnRandomBypass();
                    }
                    else
                    {
                        TurnNearBypass();
                        touched_list.Put(Touched.ID, Touched);
                    }
                }
                return false;
            }

            /// <summary>
            /// 获取绕过去,离目标最近的点
            /// </summary>
            /// <returns></returns>
            private Vector2 GetNearTurnPos(InstanceZoneObject obj)
            {
                float bodysize = Math.Max(Touched.BodyBlockSize, Owner.BodyBlockSize);
                float angle = MathVector.getDegree(obj.X - Owner.X, obj.Y - Owner.Y);
                Vector2 turnL = new Vector2(Owner.X, Owner.Y);
                Vector2 turnR = new Vector2(Owner.X, Owner.Y);
                MathVector.movePolar(turnL, angle + CMath.PI_DIV_2, bodysize);
                MathVector.movePolar(turnR, angle - CMath.PI_DIV_2, bodysize);
                float dl = MathVector.getDistanceSquare(turnL, TargetPos);
                float dr = MathVector.getDistanceSquare(turnR, TargetPos);
                if (dl < dr)
                {
                    return turnL;
                }
                else
                {
                    return turnR;
                }
            }

            /// <summary>
            /// 碰到障碍时,绕过去
            /// </summary>
            /// <param name="unit"></param>
            private void TurnRandomBypass()
            {
                float bodysize = (Touched.BodyBlockSize + Owner.BodyBlockSize); // 1~2个身位 //
                float distance = bodysize + (float)(Owner.RandomN.NextDouble() * bodysize);
                float angle = MathVector.getDegree(Touched.X, Touched.Y, Owner.X, Owner.Y);
                float factor = (float)(Owner.RandomN.NextDouble() * (CMath.PI_DIV_2 / 2f));
                if (Owner.RandomN.Next(0, 10) % 2 == 0)
                {
                    angle += CMath.PI_DIV_2 - factor;
                }
                else
                {
                    angle -= CMath.PI_DIV_2 + factor;
                }
                Vector2 turnLR = new Vector2(Owner.X, Owner.Y);
                MathVector.movePolar(turnLR, angle, distance);
                this.TargetX = turnLR.X;
                this.TargetY = turnLR.Y;
            }
            /// <summary>
            /// 从最近点绕过去
            /// </summary>
            private void TurnNearBypass()
            {
                float bodysize = Math.Max(Touched.BodyBlockSize, Owner.BodyBlockSize); // 1~2个身位 //
                float distance = bodysize + (float)(Owner.RandomN.NextDouble() * bodysize);
                float angle = MathVector.getDegree(Touched.X, Touched.Y, Owner.X, Owner.Y);
                Vector2 turnL = new Vector2(Owner.X, Owner.Y);
                Vector2 turnR = new Vector2(Owner.X, Owner.Y);
                MathVector.movePolar(turnL, angle + CMath.PI_DIV_2, distance);
                MathVector.movePolar(turnR, angle - CMath.PI_DIV_2, distance);
                float dl = MathVector.getDistanceSquare(turnL, TargetPos);
                float dr = MathVector.getDistanceSquare(turnR, TargetPos);
                if (dl < dr)
                {
                    this.TargetX = turnL.X;
                    this.TargetY = turnL.Y;
                }
                else
                {
                    this.TargetX = turnR.X;
                    this.TargetY = turnR.Y;
                }
            }




        }

        /// <summary>
        /// 如果向目标移动过程中被单位阻挡,则向左或右调整一段距离
        /// </summary>
        private class MoveTurnPosMapBlock
        {
            public InstanceUnit Owner { get; private set; }
            public bool IsEnd { get; private set; }

            private float tx;
            private float ty;

            public MoveTurnPosMapBlock(InstanceUnit owner)
            {
                this.Owner = owner;
                this.IsEnd = true;
            }

            public void Start(float target_x, float target_y)
            {
                float tdx = (target_x - Owner.X);
                float tdy = (target_y - Owner.Y);
                int ddx = (int)CMath.getDirect(tdx);
                int ddy = (int)CMath.getDirect(tdy);
                if (Math.Abs(tdx) < Math.Abs(tdy))
                {
                    float tw = ddx * (float)(Owner.Parent.GridCellW + (Owner.RandomN.NextDouble() * Owner.Parent.GridCellW / 2f));
                    tx = Owner.X + tw;
                    ty = Owner.Y;
                }
                else
                {
                    float th = ddy * (float)(Owner.Parent.GridCellH + (Owner.RandomN.NextDouble() * Owner.Parent.GridCellH / 2f));
                    tx = Owner.X;
                    ty = Owner.Y + th;
                }
                this.IsEnd = false;
            }

            public void Stop()
            {
                this.IsEnd = true;
            }

            /// <summary>
            /// 绕过某个单位移动
            /// </summary>
            /// <param name="speedSEC"></param>
            /// <param name="intervalMS"></param>
            /// <param name="result"></param>
            /// <returns>是否移动结束</returns>
            public bool move(float speedSEC, int intervalMS, out MoveBlockResult result)
            {
                Owner.faceTo(tx, ty);
                MoveImpactResult rst = Owner.moveImpactTo(tx, ty, speedSEC, intervalMS);
                result = new MoveBlockResult();
                result.result = (MoveResult)((byte)rst);

                if ((rst & MoveImpactResult.RESULTS_CAN_NOT_MOVE) != 0)
                {
                    this.IsEnd = true;
                    return true;
                }
                return false;
            }
        }
    }



}