using RichCreator.Utility; using RichCreator.Utility.InputControl; using RichCreator.Utility.Structs; using RichCreator.Jobs.StateMachines; using RichCreator.Maps; using RichCreator.Utilitys; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using static RichCreator.Jobs.StateMachines.KillMonsterStateMachine; using Utils = RichCreator.Utilitys.Utils; namespace RichCreator.StateMachines { public class MoveState { private const Int32 PaddingLeft = 140;//左边框内边距 private const Int32 PaddingRight = 140;//右边框内边距 public MoveState(ZTRectangle gameRect, MapHouse house) { this.gameRect = gameRect; this.house = house; minCenterLineY = this.gameRect.End.Y + this.house.HouseCenterMoveLine - centerLineErrorRange; maxCenterLineY = this.gameRect.End.Y + this.house.HouseCenterMoveLine + centerLineErrorRange; } /// /// 步行速度,每100毫秒 /// public static readonly ZTSizeDouble SpeedOfStep = new ZTSizeDouble(0.29d, 0.24d); /// /// 跑速度,每100毫秒 /// public static readonly ZTSizeDouble SpeedOfRun = new ZTSizeDouble(0.66d, 0); /// /// 开始跑的阀值 /// public static readonly double RunThresold = SpeedOfStep.Width*RandomUtils.KeyPressDurationMax+SpeedOfRun.Width*RandomUtils.KeyPressDurationMax; /// /// 左侧随机移动距离 /// public static readonly Int32 LeftRandomMoveDistance = 600; /// /// 左侧随机移动毫秒数 /// public static readonly double LeftRandomMoveMillSecond = LeftRandomMoveDistance / SpeedOfStep.Width; /// /// 上边随机移动距离 /// public static readonly Int32 TopRandomMoveDistance = 300; /// /// 上边随机移动毫秒数 /// public static readonly double TopRandomMoveMillSecond = TopRandomMoveDistance / SpeedOfStep.Height; /// /// 右侧随机移动距离 /// public static readonly Int32 RightRandomMoveDistance = 600; /// /// 右侧随机移动毫秒数 /// public static readonly double RightRandomMoveMillSecond = RightRandomMoveDistance / SpeedOfStep.Width; /// /// 下边随机移动距离 /// public static readonly Int32 BottomRandomMoveDistance = 300; /// /// 下边随机移动毫秒数 /// public static readonly double BottomRandomMoveMillSecond = BottomRandomMoveDistance / SpeedOfStep.Height; private Int32 minCenterLineY; private Int32 maxCenterLineY; private Int32 centerLineErrorRange = 35;//中间性可允许的误差 private MapHouse house; private ZTRectangle gameRect = ZTRectangle.Empty; private HIDCode moveKey = HIDCode.NoEvent; private MoveIntent movingIntent = MoveIntent.ToAttack;//移动意图 private MoveMethod movingMethod= MoveMethod.Vertical;//移动方式,默认垂直移动 private ZTSize movingDistance;//移动距离 /// /// 按下的键,0:横向,1:纵向 /// private HIDCode[] pressKeys = new HIDCode[] { HIDCode.NoEvent, HIDCode.NoEvent }; private bool isRuning = false; /// /// 移动方式 /// public enum MoveMethod { Vertical,//默认垂直移动 ToLeft,//左移动 ToRight,//右移动 Fixed//固定离动距离 } /// /// 移动意图 /// public enum MoveIntent { None,//没移动 ToAttack,//去攻击 ToFindDoor,//去找门 ToFindRole,//找主角 ToPickup//去拾取 } /// /// 是否移动中 /// public bool IsMoving { get { return pressKeys[0]!=HIDCode.NoEvent||pressKeys[1]!=HIDCode.NoEvent; } } /// /// 是否正在攻击移动 /// /// public bool IsAttackMoving { get { if (IsMoving && movingIntent == MoveIntent.ToAttack) { return true; } return false; } } /// /// 是否正在查门移动 /// /// public bool IsFindDoorMoving { get { if (IsMoving && movingIntent == MoveIntent.ToFindDoor) { return true; } return false; } } /// /// 是否正在查找主角移动 /// /// public bool IsFindRoleMoving { get { if (IsMoving && movingIntent == MoveIntent.ToFindRole) { return true; } return false; } } /// /// 是否正在去拾取移动 /// /// public bool IsPickupMoving { get { if (IsMoving && movingIntent == MoveIntent.ToPickup) { return true; } return false; } } /// /// 攻击移动 /// /// public void AttackMove(ZTSize moveDistance) { PutKey(moveDistance); movingIntent = MoveIntent.ToAttack; } private Int32 RandomDirRun = 0;//随机行走的方向 private const Int32 FindRoleMaxDelayMillSecond = 1000;//找角色开始移动最大延迟 private DateTime FindRoleMoveTimeout = DateTime.MinValue;//方向移动过期时间 private DateTime FindRoleStartTimeout = DateTime.MinValue;//开始查找主角移动过期时间 /// /// 查找主角移动 /// /// public void FindRoleMove() { bool recomputationTimeoutTime = false; //延迟开始找角色 if (!IsMoving) { if (FindRoleStartTimeout == DateTime.MinValue) { //开始计时 FindRoleStartTimeout = DateTime.Now.AddMilliseconds(FindRoleMaxDelayMillSecond); return; } if (DateTime.Now < FindRoleStartTimeout) { //未超过延迟时间 return; } //计算超时 recomputationTimeoutTime = true; } if (DateTime.Now>=FindRoleMoveTimeout) { //转换方向,计算超时 RandomDirRun++; recomputationTimeoutTime = true; } HIDCode dirKey = HIDCode.NoEvent; switch (RandomDirRun % 4) { case 0: dirKey = HIDCode.LeftArrow; if (recomputationTimeoutTime) { FindRoleMoveTimeout = DateTime.Now.AddMilliseconds(LeftRandomMoveMillSecond); } //movingDistance = new ZTPoint(-MoveMonitor.LeftRandomMoveDistance, 0); break; case 1: dirKey = HIDCode.UpArrow; if (recomputationTimeoutTime) { FindRoleMoveTimeout = DateTime.Now.AddMilliseconds(TopRandomMoveMillSecond); } //movingDistance = new ZTPoint(0, -MoveMonitor.TopRandomMoveDistance); break; case 2: dirKey = HIDCode.RightArrow; if (recomputationTimeoutTime) { FindRoleMoveTimeout = DateTime.Now.AddMilliseconds(RightRandomMoveMillSecond); } //movingDistance = new ZTPoint(MoveMonitor.RightRandomMoveDistance, 0); break; case 3: dirKey = HIDCode.DownArrow; if (recomputationTimeoutTime) { FindRoleMoveTimeout = DateTime.Now.AddMilliseconds(BottomRandomMoveMillSecond); } //movingDistance = new ZTPoint(0, MoveMonitor.BottomRandomMoveDistance); break; } if (!IsMoving || (IsMoving && dirKey != moveKey)) { G.Instance.InputControl.PutDown(false, false, false, false, false, false, false, false, dirKey); moveKey = dirKey; } movingIntent = MoveIntent.ToFindRole; } /// /// 拾起物品移动 /// public void PickupMove(ZTPoint rolePosition,ZTPoint thingItemPosition) { ZTSize moveDistance = new ZTSize(thingItemPosition.X - rolePosition.X, thingItemPosition.Y - rolePosition.Y - 97); if (Math.Abs(moveDistance.Width) < 100 && Math.Abs(moveDistance.Height)<100) { //距离允许,就近距离移动并X G.Instance.DebugWriter("distance ok"); SyncMove(moveDistance); G.Instance.InputControl.PressKey(RandomUtils.G(400, 500), HIDCode.X); return; } //G.Instance.DebugWriter("pickup distance:" + moveDistance.ToString()); PutKey(moveDistance); movingIntent = MoveIntent.ToPickup; } /// /// 找门找怪移动 /// /// public void FindDoorMove(ZTPoint rolePosition) { ComputeMoveInfo(rolePosition); HIDCode dirKey = HIDCode.NoEvent; switch (movingMethod) { case MoveMethod.ToLeft: dirKey = HIDCode.LeftArrow; break; case MoveMethod.ToRight: dirKey = HIDCode.RightArrow; break; case MoveMethod.Vertical: dirKey = movingDistance.Height > 0 ? HIDCode.DownArrow : HIDCode.UpArrow; break; case MoveMethod.Fixed: SyncMove(movingDistance); ReleaseKey(); return; } PutKey(movingDistance); movingIntent = MoveIntent.ToFindDoor; } private ZTPoint roleLastPosition = ZTPoint.Empty; private bool StaticTimerIsStart = false;//静止计时是否开始 private Int32 StaticTimerCounter = 0;//静止计时计数器 private DateTime DetectLastNoMoveTime = DateTime.MaxValue;//最后没移动时间 private const Int32 NoMoveMaxMillSecond = 2000;//最大未移动容忍毫秒数 /// /// 得到循环移动的距离 /// /// private void ComputeMoveInfo(ZTPoint rolePosition) { ZTRectangle limitRect = ZTRectangle.Empty; //达到未移动阀值,可能有障碍物,先攻击,如果攻击后还是无效则上下左右移 if (rolePosition == this.roleLastPosition) { if (StaticTimerIsStart) { if ((DateTime.Now - DetectLastNoMoveTime).TotalMilliseconds > NoMoveMaxMillSecond) { G.Instance.DebugWriter($"find door not move,role position:{rolePosition.ToString()}"); this.StopMove(); if (StaticTimerCounter==0) { //清除障碍物 G.Instance.InputControl.PressKey(RandomUtils.KeyPressDuration, HIDCode.X); } else { //无法清除障碍物,随机移动一下 switch (StaticTimerCounter % 4) { case 0: G.Instance.DebugWriter("random up"); //上 movingDistance = new ZTSize(0, -TopRandomMoveDistance); break; case 1: //右 movingDistance = new ZTSize(RightRandomMoveDistance, 0); break; case 2: //下 movingDistance = new ZTSize(0, BottomRandomMoveDistance); break; case 3: //左 movingDistance = new ZTSize(-LeftRandomMoveDistance, 0); break; } movingMethod = MoveMethod.Fixed; } StaticTimerCounter++; DetectLastNoMoveTime = DateTime.Now; if (StaticTimerCounter > 1) { return; } } } else if (!StaticTimerIsStart) { //没开始计时 则 开始计时 StaticTimerIsStart = true; DetectLastNoMoveTime = DateTime.Now; } } else { //移动了 取消计时 this.roleLastPosition = rolePosition; StaticTimerIsStart = false; StaticTimerCounter = 0; } if (!IsMoving) { //刚开始移动 movingMethod = MoveMethod.Vertical; } if (movingMethod == MoveMethod.Vertical && rolePosition.Y >= minCenterLineY && rolePosition.Y <= maxCenterLineY) { //不需要上下移动,计算左右 if (this.house.DoorDirection[0] == Direction.Left) { movingMethod = MoveMethod.ToLeft; } else if (this.house.DoorDirection[0] == Direction.Right) { movingMethod = MoveMethod.ToRight; } else { //计算是向左还是右,哪边大往哪边 if (rolePosition.X > (this.gameRect.Start.X + (this.gameRect.End.X - this.gameRect.Start.X) / 2)) { //左边空间大 movingMethod = MoveMethod.ToLeft; } else { movingMethod = MoveMethod.ToRight; } } } if (movingMethod == MoveMethod.ToLeft) { //计算左边界范围 limitRect = new ZTRectangle(gameRect.Start.X, gameRect.Start.Y, gameRect.Start.X + PaddingLeft, gameRect.End.Y); //判断是否到左边界 if (Utils.IsInRect(rolePosition, limitRect)) { //到左边界就向右走 movingMethod = MoveMethod.ToRight; movingDistance = new ZTSize(gameRect.End.X - rolePosition.X, 0); } else { //没到继续向左走 movingMethod = MoveMethod.ToLeft; movingDistance = new ZTSize(limitRect.Start.X - rolePosition.X, 0); } } else if (movingMethod == MoveMethod.ToRight) { //计算右边界范围 limitRect = new ZTRectangle(gameRect.End.X - PaddingRight, gameRect.Start.Y, gameRect.End.X, gameRect.End.Y); //判断是否到右边界 if (Utils.IsInRect(rolePosition, limitRect)) { //到右边界就向左走 G.Instance.InfoWriter($"in limit rect,role position:{rolePosition.ToString()},limit:{limitRect.ToString()}"); movingMethod = MoveMethod.ToLeft; movingDistance = new ZTSize(gameRect.Start.X - rolePosition.X, 0); } else { //没到继续向右走 movingMethod = MoveMethod.ToRight; movingDistance = new ZTSize(gameRect.End.X - rolePosition.X, 0); } } else { //向点移动 Int32 targetY = gameRect.End.Y + this.house.HouseCenterMoveLine; movingDistance = new ZTSize(0, targetY - rolePosition.Y); } } /// /// 停止移动 /// public void StopMove() { if (IsMoving) { //停止 ReleaseKey(); } } /// /// 同步移动指定距离 /// /// public void SyncMove(ZTSize distance) { HIDCode horizontal = HIDCode.NoEvent; HIDCode vertical = HIDCode.NoEvent; bool isRun = false; int runms, stepms; Int32 xsig = Math.Sign(distance.Width); Int32 ysig = Math.Sign(distance.Height); if (Math.Abs(distance.Width) >= RunThresold) { isRun = true; } if (distance.Height > 0) { vertical = HIDCode.DownArrow; } if (distance.Height < 0) { vertical = HIDCode.UpArrow; } if (distance.Width > 0) { horizontal = HIDCode.RightArrow; } if (distance.Width < 0) { horizontal = HIDCode.LeftArrow; } PutKey(out stepms, out runms, horizontal, vertical, isRun); if (stepms > 0) { Int32 mdistance = (Int32)(stepms * SpeedOfStep.Width); if (runms > 0) { mdistance += (Int32)(runms * SpeedOfRun.Width); } distance = new ZTSize(distance.Width - xsig*mdistance, distance.Height); } int ytime = (Int32)(Math.Abs(distance.Height) / SpeedOfStep.Height); Int32 xtime = (Int32)(Math.Abs(distance.Width) / SpeedOfStep.Width); if (isRun) { xtime = (Int32)(Math.Abs(distance.Width) / SpeedOfRun.Width); } Int32 mintime = Math.Min(xtime, ytime); if (xtime <= 0) { mintime = ytime; } if (ytime <= 0) { mintime = xtime; } Thread.Sleep(mintime); xtime -= mintime; ytime -= mintime; if (xtime > 0) { PutKey(out stepms, out runms, horizontal, HIDCode.NoEvent, isRun); Thread.Sleep(xtime); } if (ytime > 0) { PutKey(out stepms, out runms, HIDCode.NoEvent, vertical, isRun); Thread.Sleep(ytime); } StopMove(); } /// /// 同步移动指定距离 /// /// public void SyncMove(ZTPoint distance) { SyncMove(new ZTSize(distance.X, distance.Y)); } #region 八方向移动 /// /// 按下按键 /// /// private void PutKey(ZTSize distance) { HIDCode horizontal = HIDCode.NoEvent; HIDCode vertical = HIDCode.NoEvent; bool isRun = false; if (distance.Width < 0) { horizontal = HIDCode.LeftArrow; } if (distance.Width > 0) { horizontal = HIDCode.RightArrow; } if (Math.Abs(distance.Width) >= RunThresold) { isRun = true; } if (distance.Height < 0) { vertical = HIDCode.UpArrow; } if (distance.Height > 0) { vertical = HIDCode.DownArrow; } Int32 stepms, runms; PutKey(out stepms,out runms,horizontal, vertical, isRun); } /// /// 按下按键 /// /// /// private void PutKey(out Int32 stepMS,out Int32 runMS,HIDCode horizontal, HIDCode vertical,bool isRun) { stepMS = 0; runMS = 0; if (horizontal == vertical) { return; } if (horizontal == pressKeys[0] && vertical == pressKeys[1]) { return; } int keyCount = horizontal != HIDCode.NoEvent && vertical != HIDCode.NoEvent ? 2 : 1; Int32 tempwait = 0; if (isRun) { //跑 if (!isRuning || horizontal != pressKeys[0]) { //如果之前没有跑,或跑的方向不一样,则开始跑 G.Instance.InputControl.PutDown(false, false, false, false, false, false, false, false, horizontal); tempwait = RandomUtils.KeyPressDuration; stepMS += tempwait; Thread.Sleep(tempwait); G.Instance.InputControl.PutDown(false, false, false, false, false, false, false, false); Thread.Sleep(RandomUtils.KeyPressDuration); G.Instance.InputControl.PutDown(false, false, false, false, false, false, false, false, horizontal); isRuning = true; if (keyCount == 2) { tempwait = RandomUtils.KeyPressDuration; runMS += tempwait; Thread.Sleep(tempwait); G.Instance.InputControl.PutDown(false, false, false, false, false, false, false, false, horizontal, vertical); } } else { //奔跑方向不变 int afterKeyCount = pressKeys[0] != HIDCode.NoEvent && pressKeys[1] != HIDCode.NoEvent ? 2 : 1; if (afterKeyCount != keyCount) { //如果跟原来按键数量不一样 if (keyCount == 1) { G.Instance.InputControl.PutDown(false, false, false, false, false, false, false, false, horizontal); } else { G.Instance.InputControl.PutDown(false, false, false, false, false, false, false, false, horizontal, vertical); } } } } else { //走 if (keyCount == 1) { G.Instance.InputControl.PutDown(false, false, false, false, false, false, false, false, horizontal != HIDCode.NoEvent?horizontal:vertical); } else { G.Instance.InputControl.PutDown(false, false, false, false, false, false, false, false, horizontal, vertical); } } pressKeys[0] = horizontal; pressKeys[1] = vertical; } /// /// 释放按键 /// private void ReleaseKey() { G.Instance.InputControl.PutDown(false, false, false, false, false, false, false, false); pressKeys[0] = HIDCode.NoEvent; pressKeys[1] = HIDCode.NoEvent; isRuning = false; } #endregion } }