From 2aeab450471cb80b59002da7da80faf251a0c4f4 Mon Sep 17 00:00:00 2001
From: asmrobot <asmrobot@hotmail.com>
Date: Mon, 25 Nov 2019 15:02:53 +0000
Subject: [PATCH] sigle computer

---
 src/RichCreator/StateMachines/KillMonsterStateMachine.cs |  269 +++++++++++++++++++++++++++++++----------------------
 1 files changed, 155 insertions(+), 114 deletions(-)

diff --git a/src/RichCreator/StateMachines/KillMonsterStateMachine.cs b/src/RichCreator/StateMachines/KillMonsterStateMachine.cs
index 49ddf2c..2b6cee4 100644
--- a/src/RichCreator/StateMachines/KillMonsterStateMachine.cs
+++ b/src/RichCreator/StateMachines/KillMonsterStateMachine.cs
@@ -2,10 +2,12 @@
 using Emgu.CV.Structure;
 using RichCreator.Dnf;
 using RichCreator.Maps.Kalete;
+using RichCreator.Models;
 using RichCreator.StateMachines;
 using RichCreator.Utility;
 using RichCreator.Utility.Captures;
 using RichCreator.Utility.CV;
+using RichCreator.Utility.Dnf;
 using RichCreator.Utility.InputControl;
 using RichCreator.Utility.Maps;
 using RichCreator.Utility.Skills;
@@ -51,6 +53,11 @@
 
         public KillMonsterStateMachine(MapInfo map,HouseInfo house, DnfRole role)
         {
+            if (house.HousePathInfo.LoopPoint.Equals(ZTPoint.Empty))
+            {
+                throw new ArgumentOutOfRangeException("寻路中不存在循环点");
+            }
+
             this.map = map;
             this.house = house;
             this.role = role;
@@ -72,10 +79,9 @@
         /// <param name="cancellationToken"></param>
         /// <param name="timeoutMillSecond"></param>
         /// <returns></returns>
-        public ZTResult Work(Int32 timeoutMillSecond,Int32 preHouseIndex,Int32 runningStep)
+        public ZTResult Work(Int32 timeoutMillSecond,Int32 fromHouseIndex,Int32 runningStep)
         {
             bool imageIsChange = false;//图像是否改变
-            Int32 nextGate = 0;
             DateTime expireTime = DateTime.Now.AddMilliseconds(timeoutMillSecond);
             
             while (true)
@@ -83,14 +89,14 @@
                 if (map.CancelToken.IsCancellationRequested)
                 {
                     G.Instance.DebugWriter("取消刷图");
-                    this.role.StopMove();
+                    this.role.StopMove("cancel");
                     return ZTResult.Cancel;
                 }
 
                 if (DateTime.Now > expireTime)
                 {
                     G.Instance.DebugWriter("刷图超时");
-                    this.role.StopMove();
+                    this.role.StopMove("timeout");
                     return ZTResult.Timeout;
                 }
 
@@ -112,7 +118,10 @@
                 {
                     case KillMonsterStates.Start:
                         //开始
-                        this.map.EntryHousePrework(this.house.Index, preHouseIndex);
+                        if (this.house.FromHouseIndex == fromHouseIndex)
+                        {
+                            this.map.EntryHousePrework(this.house.Index, fromHouseIndex);
+                        }                        
                         SetState(KillMonsterStates.IsLastHouse, true);
                         break;
                     case KillMonsterStates.IsLastHouse:
@@ -136,7 +145,6 @@
                         //是否有奖励界面
                         if (DnfCVHelper.IsJiangli(image, map.GameRect))
                         {
-                            G.Instance.InfoWriter("has jiangli");
                             SetState(KillMonsterStates.TurnAroundCard, false);
                         }
                         else
@@ -178,7 +186,6 @@
                         break;
                     case KillMonsterStates.FindRole:
                         //主角
-
                         //定位点
                         if (this.house.WithoutNumber.Count <= 0)
                         {
@@ -201,26 +208,32 @@
                         ZTPoint roleCBPosition = DnfCVHelper.FindRole(hsvImage, map.GameRect);
                         if (roleCBPosition.Equals(ZTPoint.Empty))
                         {
-                            SetState(KillMonsterStates.FindRoleMove, false);
+                            //未找到角色
+                            if (!this.role.IsMoving)
+                            {
+                                SetState(KillMonsterStates.FindRoleMove, false);
+                            }
+                            else
+                            {
+                                SetState(KillMonsterStates.IsLastHouse, true);
+                            }
                         }
                         else
                         {
-                            if (this.role.IsMoveIntent(Utility.Dnf.MoveIntent.FindRoleMove))
+                            if (this.role.IsMoveIntent(MoveIntent.FindRoleMove))
                             {
-                                this.role.StopMove();
+                                this.role.StopMove("update cb position");
                             }
                             role.UpdatePosition(roleCBPosition);
                             SetState(KillMonsterStates.FindMonster, false);
                         }
                         break;
                     case KillMonsterStates.FindRoleMove:
-                        //todo:让主角移动(原:有怪攻击一下,无怪移动一下)
                         FindRoleMove();
                         break;
                     case KillMonsterStates.FindMonster:
-                        //找怪                        
+                        //找怪   
                         this.stateMonsters = DnfCVHelper.FindMonster(hsvImage, map.GameRect);
-
                         if (this.stateMonsters.Length > 0)
                         {
                             G.Instance.DebugWriter(string.Format("找到{0}个怪", this.stateMonsters.Length));
@@ -228,13 +241,16 @@
                         }
                         else
                         {
+                            if (this.role.IsMoveIntent(MoveIntent.AttackMove))
+                            {
+                                this.role.StopMove("find monster to pickup thing");
+                            }
                             SetState(KillMonsterStates.PickupThing, false);
                         }
                         break;
                     case KillMonsterStates.PickupThing:
                         //拾取物品
-                        //todo: PickupThing();
-                        SetState(KillMonsterStates.FindDoor, false);
+                        PickupThing();
                         break;
                     case KillMonsterStates.FindDoor:
                         //查找门
@@ -249,39 +265,9 @@
                         //向门移动, 进门
                         EntryDoor();
                         break;
-                    case KillMonsterStates.InNextGatePoint:
-                        //是否在进门点
-                        ParametersPoint nextGatePoint = ParametersPoint.Empty;
-                        ZTPoint rmhp=this.house.ScreenToMapCoordinate(this.role.HalfPosition, this.stateScreenLocation);
-                        if (this.house.IsInNextGatePoint(out nextGatePoint,rmhp))
-                        {
-                            SetState(KillMonsterStates.ToLoopPoint, false);
-                        }
-                        else
-                        {
-                            //不在进门点
-                            SetState(KillMonsterStates.ToNextGatePoint, false);
-                        }
-                        break;
-                    case KillMonsterStates.ToNextGatePoint:
-                        //移到进门点
-                        ZTPoint rmp = this.house.ScreenToMapCoordinate(this.role.Position, this.stateScreenLocation);
-                        ZTPoint ngp = DnfRole.HalfToFootPosition(this.house.HousePathInfo.NextGates[nextGate].Point);
-                        this.role.MoveToMapPoint(rmp, ngp);                        
-                        nextGate++;
-                        nextGate = nextGate % this.house.HousePathInfo.NextGates.Count;
-                        SetState(KillMonsterStates.IsLastHouse, true);
-                        break;
-                    case KillMonsterStates.ToLoopPoint:
-                        //移动到循环点
-                        if (!this.house.HousePathInfo.LoopPoint.Equals(ZTPoint.Empty))
-                        {
-                            //开始移动
-                            ZTPoint roleMapPoint = this.house.ScreenToMapCoordinate(this.role.Position, this.stateScreenLocation);
-                            this.role.MoveToMapPoint(roleMapPoint, this.house.HousePathInfo.LoopPoint);
-
-                        }
-                        SetState(KillMonsterStates.IsLastHouse, true);
+                    case KillMonsterStates.ToLoop:
+                        //巡逻
+                        ToLoop();
                         break;
                     case KillMonsterStates.CalcAttackPoint:
                         //判断使用何技能,计算攻击移动距离, 是否需要移动
@@ -292,13 +278,12 @@
                         ReleaseSkill();
                         break;
                     case KillMonsterStates.AttackMove:
-                        //todo:攻击移动
+                        //攻击移动
                         AttackMove();
                         break;
                     case KillMonsterStates.Exit:
                         //结束
-                        G.Instance.DebugWriter("退出!~");
-                        this.role.StopMove();
+                        this.role.StopMove("exit");
                         if (this.isSuccess)
                         {
                             return ZTResult.Success;
@@ -306,7 +291,7 @@
                         return ZTResult.Failed;
                 }
                 
-                G.Instance.DebugWriter("next state:" + currentState.ToString());
+                G.Instance.DebugWriter($"next state:{currentState},capture screen:{needCaptureScreen}");
             }
         }
 
@@ -316,32 +301,69 @@
         /// </summary>
         private void FindRoleMove()
         {
+            if (this.role.IsMoving)
+            {
+                if (this.role.IsMoveIntent(MoveIntent.FindRoleMove))
+                {
+                    //进行中,则返回
+                    SetState(KillMonsterStates.IsLastHouse, true);
+                    return;
+                }
+                else
+                {
+                    //不是则停止
+                    this.role.StopMove("find role other");
+                }
+            }
             this.role.FindRoleMove();
-            SetState(KillMonsterStates.FindRole, true);
+            SetState(KillMonsterStates.IsLastHouse, true);
         }
 
+        
+        DateTime pickupTime = DateTime.MinValue;
         /// <summary>
         /// 拾取物品
         /// </summary>
         private void PickupThing()
         {
-            ////拾取物品,获取最近一个物品位置并步行过去
-            //ZTPoint thingItemPosition = GetNearlyThingItem(image, role.Position);
-            //if (!thingItemPosition .Equals( ZTPoint.Empty))
-            //{
-            //    if (this.role.IsMoving && !this.role.IsMoveIntent(Utility.Dnf.MoveIntent.PickupMove))
-            //    {
-            //        this.role.StopMove();
-            //    }
+            //拾取物品中,返回
+            if (this.role.IsMoveIntent(MoveIntent.PickupMove))
+            {   
+                SetState(KillMonsterStates.IsLastHouse, true);
+                return;
+            }
 
-            //    this.role.PickupMove(this.role.Position, thingItemPosition);
-            //    //return new KillMonsterStateResult(STATE_FindMonster, true);
-            //}
+            ZTPoint screenThingPosition = GetNearlyThingItem(hsvImage, role.Position);
+            //是否有物品
+            if (!screenThingPosition.Equals(ZTPoint.Empty))
+            {
+                //有其它移动,则停止
+                if (this.role.IsMoving&&!this.role.IsMoveIntent(MoveIntent.PickupMove))
+                {
+                    this.role.StopMove("pickup moveing");
+                }
 
-            //if (this.role.IsMoveIntent(Utility.Dnf.MoveIntent.PickupMove))
-            //{
-            //    this.role.StopMove();
-            //}
+                //第一次发现有物品后,等一秒再去拾取,防物品刚出来时的去错误的位置拾取
+                if (pickupTime == DateTime.MinValue)
+                {
+                    pickupTime = DateTime.Now.AddSeconds(1);
+                }
+
+                if (pickupTime > DateTime.Now)
+                {
+                    SetState(KillMonsterStates.IsLastHouse, true);
+                    return;
+                }
+                ////todo:remove
+                //hsvImage.Save(DateTime.Now.ToString("HH_mm_ss_fff")+"_" + Guid.NewGuid().ToString()+".png");
+
+                this.role.PickupMove(screenThingPosition,this.stateScreenLocation);
+                SetState(KillMonsterStates.IsLastHouse, true);
+            }
+            else
+            {
+                SetState(KillMonsterStates.FindDoor, false);
+            }
         }
 
         /// <summary>
@@ -363,20 +385,15 @@
                     //要进入门的允许区域
                     ZTPoint nextGatePoint = this.house.GetNextGatePoint(door.Value);
                     ZTRectangle doorRect = new ZTRectangle(nextGatePoint.X - 70, nextGatePoint.Y - 70, nextGatePoint.X + 70, nextGatePoint.Y + 70);
-
-                    G.Instance.InfoWriter("has door:" + mapDoorPoint.ToString()+",rect:"+doorRect.ToString());
-
+                    
                     if (GeoHelper.IsInRect(mapDoorPoint, doorRect))
                     {
-                        G.Instance.InfoWriter("in door");
                         this.state_DoorDirect = door.Value;
                         this.state_DoorPosition = door.Key;
                         break;
                     }
                 }
             }
-
-            
             
             if (!this.state_DoorPosition.Equals(ZTPoint.Empty))
             {
@@ -385,8 +402,8 @@
             }
             else
             {
-                //未找到门,是否存进门点
-                SetState(KillMonsterStates.InNextGatePoint, false);
+                //未找到门,巡逻
+                SetState(KillMonsterStates.ToLoop, false);
             }
         }
 
@@ -395,12 +412,19 @@
         /// </summary>
         private void EntryDoor()
         {
+            //已经开始进门
+            if (this.role.IsMoving)
+            {
+                this.role.StopMove("entry door other moving");
+            }
+            
             const Int32 offsetX = 200;
             const Int32 offsetY = 100;
             ZTRectangle doorRect = new ZTRectangle(this.state_DoorPosition.X - offsetX, this.state_DoorPosition.Y - offsetY, this.state_DoorPosition.X + offsetX, this.state_DoorPosition.Y + offsetY);
-            if (tryEntryDoor && GeoHelper.IsInRect(this.role.RoleCBPosition, doorRect))
+            if (tryEntryDoor && GeoHelper.IsInRect(this.role.RoleCBPosition.Sub(DnfRole.RoleHalfOffset), doorRect))
             {
                 //离门太近,先向外走,再向门走
+
                 Int32 limitLine = 0;
                 Int32 diff = 0;
                 //传过来人物坐标和门的坐标,根据门的朝向计算人物走向
@@ -460,32 +484,7 @@
             }
             else
             {
-                //先到进门点
-                ZTPoint roleMapPoint = this.house.ScreenToMapCoordinate(this.role.Position, this.stateScreenLocation);
-                ZTPoint nextGatePoint = this.house.GetNextGatePoint(this.state_DoorDirect);
-                List<ZTPoint> paths = this.house.FindPath(roleMapPoint, DnfRole.HalfToFootPosition(nextGatePoint));
-
-                //再到门后50像素
-                ZTPoint dp = this.house.ScreenToMapCoordinate(this.state_DoorPosition, this.stateScreenLocation);
-                ZTPoint doorPoint = DnfRole.HalfToFootPosition(dp);
-                switch (this.state_DoorDirect)
-                {
-                    case Direction.Up:
-                        doorPoint = doorPoint.Add(0, -50);
-                        break;
-                    case Direction.Right:
-                        doorPoint = doorPoint.Add(50, 0);
-                        break;
-                    case Direction.Bottom:
-                        doorPoint = doorPoint.Add(0, 50);
-                        break;
-                    case Direction.Left:
-                        doorPoint = doorPoint.Add(-50, 0);
-                        break;
-                }
-                paths.Add(doorPoint);
-                this.role.MovePaths(roleMapPoint, paths);
-
+                this.role.EntryDoorMove(this.state_DoorPosition, this.stateScreenLocation, this.state_DoorDirect);
                 tryEntryDoor = true;
             }
 
@@ -505,6 +504,10 @@
             skillReleasePoint = AttackRectangle.GetAttackPoint(map.GameRect, role.HalfPosition, stateMonsters, attackSkill, out roleDirection, out needMove);
             if (!needMove)
             {
+                if (this.role.IsMoving)
+                {
+                    this.role.StopMove("calc attack");
+                }
                 G.Instance.DebugWriter(string.Format("不需移动直接发技能,距离:{0}", skillReleasePoint.ToString()));
                 SetState(KillMonsterStates.ReleaseSkill, false);
             }
@@ -519,8 +522,24 @@
         /// </summary>
         private void AttackMove()
         {
+            if (this.role.IsMoving)
+            {
+                if (this.role.IsMoveIntent(MoveIntent.AttackMove))
+                {
+                    //todo:添加如果是攻击移动中,如果怪物偏差太大则重新计算
+                    //进行中,则返回
+                    SetState(KillMonsterStates.IsLastHouse, true);
+                    return;
+                }
+                else
+                {
+                    //不是则停止
+                    this.role.StopMove("attack move other");
+                }
+            }
+
             G.Instance.DebugWriter("attack move :" + skillReleasePoint.ToString() + ",role:" + role.Position.ToString() + ",monster1:" + stateMonsters[0].ToString() + ",skill:" + this.house.Skills.SyncPeek().Key.ToString());
-            this.role.AttackMoveTo(skillReleasePoint,this.stateScreenLocation);
+            this.role.AttackMove(skillReleasePoint, this.stateScreenLocation);
             SetState(KillMonsterStates.FindRole, true);
         }
         
@@ -529,9 +548,8 @@
         /// </summary>
         private void ReleaseSkill()
         {
-            this.role.StopMove();
-
             SkillInfo skill = this.house.Skills.SyncDeQueue();
+            StateProvider.Instance.AttackKey = skill.Key;
             if (roleDirection != HIDCode.NoEvent)
             {
                 G.Instance.InputControl.PressKey(100, roleDirection);
@@ -553,6 +571,31 @@
             G.Instance.DebugWriter(string.Format("发完技能,技能按键:{0},技能名称:{1}", skill.Key, skill.SkillName));
             SetState(KillMonsterStates.IsLastHouse, true);
         }
+                
+        /// <summary>
+        /// 巡逻
+        /// </summary>
+        private void ToLoop()
+        {
+            //巡逻
+            if (this.role.IsMoving)
+            {
+                if (this.role.IsMoveIntent(MoveIntent.ToLoop))
+                {
+                    //进行中,则返回
+                    SetState(KillMonsterStates.IsLastHouse, true);
+                    return;
+                }
+                else
+                {
+                    //不是则停止                    
+                    this.role.StopMove("to loop other");
+                }
+            }
+
+            this.role.LoopMove(this.stateScreenLocation);
+            SetState(KillMonsterStates.IsLastHouse, true);
+        }
         #endregion
 
         /// <summary>
@@ -560,22 +603,22 @@
         /// </summary>
         /// <param name="image"></param>
         /// <returns></returns>
-        public ZTPoint GetNearlyThingItem(Image<Rgb, byte> image, ZTPoint rolePosition)
+        public ZTPoint GetNearlyThingItem(Image<Hsv, byte> image, ZTPoint rolePosition)
         {
-            List<ZTPoint> points = DnfCVHelper.GetThingItemPoints(image, map.GameRect);
-            if (points.Count <= 0)
+            ZTPoint[] points = DnfCVHelper.FindThings(image, map.GameRect);
+            if (points.Length <= 0)
             {
                 return ZTPoint.Empty;
             }
 
-            if (points.Count == 1)
+            if (points.Length == 1)
             {
                 return points[0];
             }
 
             double distance = 0;
             ZTPoint result = ZTPoint.Empty;
-            for (int i = 0; i < points.Count; i++)
+            for (int i = 0; i < points.Length; i++)
             {
                 double temp = ZTImage.Utils.GetDistance(rolePosition.X, rolePosition.Y, points[i].X, points[i].Y);
                 if (i == 0)
@@ -672,9 +715,7 @@
             PickupThing,//拾取物品
             FindDoor,//查找门, 是否找到门
             EntryDoor,//向门移动, 进门
-            InNextGatePoint,//是否在进门点
-            ToNextGatePoint,//移至进门点
-            ToLoopPoint,//移至巡逻点
+            ToLoop,//巡逻
 
 
             

--
Gitblit v1.9.3