1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024 |
- 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;
- }
- }
- }
- }
|