using RichCreator.Utility.InputControl; using RichCreator.Utility.Structs; using RichCreator.Jobs.StateMachines; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using RichCreator.Utility.Skills; using RichCreator.Utility.Maps; namespace RichCreator.Utilitys { /// /// 攻击范围 /// public class AttackRectangle { /// /// 计算目标距离,是否需要移动,和用户应该的朝向 /// /// /// /// /// /// /// /// public static ZTSize GetMoveDistance(ZTRectangle gameRect,ZTPoint rolePosition, ZTPoint[] monsterPositions, SkillInfo skill,out HIDCode direction, out bool needMove) { needMove = false; ZTSize moveDistance = ZTSize.Empty; if (monsterPositions.Length <= 1||skill.MovePriority==MovePriority.Nearly) { moveDistance = GetAttackRectangleByNear(monsterPositions, rolePosition, skill, out direction, out needMove); } else { moveDistance = GetAttackRectangleByQuantity(gameRect,monsterPositions, rolePosition, skill, out direction, out needMove); } return moveDistance; } /// /// 得到最近的攻击目标距离 /// /// private static ZTSize GetAttackRectangleByNear(ZTPoint[] monsterPositions, ZTPoint rolePosition, SkillInfo skill,out HIDCode direction, out bool needMove) { needMove = true; direction = HIDCode.RightArrow; ZTRectangle attackRect = new ZTRectangle(rolePosition.X - skill.Range.Width, rolePosition.Y - skill.Range.Height / 2, rolePosition.X + skill.Range.Width, rolePosition.Y + skill.Range.Height / 2);//攻击范围 //switch (skill.ReleaseAnchor) //{ // case SkillInfo.SkillAnchor.Side: // //两边 // attackRect = new ZTRectangle(rolePosition.X - skill.Range.Width, rolePosition.Y - skill.Range.Height / 2, rolePosition.X + skill.Range.Width, rolePosition.Y + skill.Range.Height / 2);//攻击范围 // break; // case SkillInfo.SkillAnchor.Center: // //TODO:中间 // attackRect = new ZTRectangle(rolePosition.X - skill.Range.Width, rolePosition.Y - skill.Range.Height / 2, rolePosition.X + skill.Range.Width, rolePosition.Y + skill.Range.Height / 2);//攻击范围 // break; //} ZTPoint nearMonsterPosition = ZTPoint.Empty; ZTPoint attackPosition = ZTPoint.Empty; double nearDistance = 0; for (int index = 0; index < monsterPositions.Length; index++) { if (index == 0) { nearDistance = Utils.GetDistance(monsterPositions[index], rolePosition); nearMonsterPosition = monsterPositions[index]; } //天然就在攻击范围内 if (Utils.IsInRect(monsterPositions[index], attackRect)) { needMove = false; break; } if (index == 0) { continue; } //计算远近 double distance = Utils.GetDistance(monsterPositions[index], rolePosition); if (distance < nearDistance) { nearDistance = distance; nearMonsterPosition = monsterPositions[index]; } } ZTSize moveDistance = new ZTSize(nearMonsterPosition.X - rolePosition.X, nearMonsterPosition.Y - rolePosition.Y); //如果不用移动则计算朝向 if (!needMove) { if (moveDistance.Width > 0) { //怪在主角的右边 direction = HIDCode.RightArrow; } else if (moveDistance.Width < 0) { //怪在主角的左边 direction = HIDCode.LeftArrow; } } else { //todo:到目标的左侧或右侧,看哪个轴不用移动 //if (nearMonsterPosition.X > rolePosition.X) //{ // //在怪的左侧 // nearMonsterPosition.X = nearMonsterPosition.X - 13; //} //if (nearMonsterPosition.X < rolePosition.X) //{ // //在怪的右侧 // nearMonsterPosition.X = nearMonsterPosition.X + 13; //} if (rolePosition.X >= (nearMonsterPosition.X - skill.Range.Width) && rolePosition.X <= (nearMonsterPosition.X + skill.Range.Width)) { moveDistance.Width = 0; } if (rolePosition.Y >= (nearMonsterPosition.Y - skill.Range.Height/2) && rolePosition.Y <= (nearMonsterPosition.Y + skill.Range.Height/2)) { moveDistance.Height = 0; } } return moveDistance; } /// /// 得到数量最多的攻击范围 /// /// /// /// /// private static ZTSize GetAttackRectangleByQuantity(ZTRectangle gameRect,ZTPoint[] monsterPositions, ZTPoint rolePosition, SkillInfo skill,out HIDCode direction, out bool needMove) { needMove = true; direction = HIDCode.RightArrow; //所有怪物点的x值和y值 Int32[] xValues = new Int32[monsterPositions.Length]; Int32[] yValues = new Int32[monsterPositions.Length]; for (int i = 0; i < monsterPositions.Length; i++) { xValues[i] = monsterPositions[i].X; yValues[i] = monsterPositions[i].Y; } Sort(xValues); Sort(yValues); //查找密度最高的攻击范围 Int32 maxX = 0, maxY = 0, maxNumber = 0; Int32 monsterNumber = 0; Int32[] counter = new Int32[xValues.Length * yValues.Length]; for (int y = 0; y < yValues.Length; y++) { for (int x = 0; x < xValues.Length; x++) { monsterNumber = InRangeNumber(xValues[x], yValues[y], skill.Range, monsterPositions); if (monsterNumber > maxNumber) { maxX = x; maxY = y; maxNumber = monsterNumber; } } } ZTRectangle monsterRect = new ZTRectangle(xValues[maxX], yValues[maxY], xValues[maxX] + skill.Range.Width, yValues[maxY] + skill.Range.Height); //计算攻击范围 内怪物需要的最小范围 Int32 top = 0, right = 0,bottom = 0,left = 0; for (int i = 0; i < monsterPositions.Length; i++) { if (Utils.IsInRect(monsterPositions[i], monsterRect)) { ZTPoint monsterPoint = monsterPositions[i]; if (i == 0) { top = bottom = monsterPoint.Y; left = right = monsterPoint.X; continue; } if (monsterPoint.Y < top) { top = monsterPoint.Y; } if (monsterPoint.Y > bottom) { bottom = monsterPoint.Y; } if (monsterPoint.X < left) { left = monsterPoint.X; } if (monsterPoint.X > right) { right = monsterPoint.X; } } } //计算最近的攻击点,和可以的攻击范围 ZTPoint releaseSkillPosition = ZTPoint.Empty; ZTRectangle releaseSkillRect = ZTRectangle.Empty; Int32 diffWidth = skill.Range.Width - (right - left); Int32 diffHeight = skill.Range.Height - (bottom - top); diffWidth = Math.Max(diffWidth, 48); diffHeight = Math.Max(diffHeight, 48); if (skill.ReleaseAnchor == SkillInfo.SkillAnchor.Center) { //中间点发技能 releaseSkillPosition = new ZTPoint(left + (right - left) / 2, top + (bottom - top) / 2); direction = HIDCode.NoEvent; releaseSkillRect = new ZTRectangle( releaseSkillPosition.X-diffWidth/2, releaseSkillPosition.Y-diffHeight/2+skill.AnchorOffset.Height, releaseSkillPosition.X + diffWidth/2, releaseSkillPosition.Y + diffHeight/2 + skill.AnchorOffset.Height ); } else { //两边发技能 ZTPoint leftAttackPosition = new ZTPoint(Math.Max(gameRect.Start.X,left+skill.AnchorOffset.Width),Math.Max(top, bottom + skill.AnchorOffset.Height)); ZTPoint rightAttackPosition = new ZTPoint(Math.Min(gameRect.End.X,right+skill.AnchorOffset.Width), Math.Max(top,bottom + skill.AnchorOffset.Height)); double toLeft = Utils.GetDistance(leftAttackPosition, rolePosition); double toRight = Utils.GetDistance(rightAttackPosition, rolePosition); //计算可以发技能的区域 if (toLeft <= toRight) { //距离左边近 releaseSkillPosition = leftAttackPosition; direction = HIDCode.RightArrow; releaseSkillRect = new ZTRectangle( releaseSkillPosition.X-diffWidth, releaseSkillPosition.Y, releaseSkillPosition.X, releaseSkillPosition.Y+diffHeight ); } else { //距离右边近 releaseSkillPosition = rightAttackPosition; direction = HIDCode.LeftArrow; releaseSkillRect = new ZTRectangle( releaseSkillPosition.X, releaseSkillPosition.Y, releaseSkillPosition.X+diffWidth, releaseSkillPosition.Y+diffHeight ); } } if (Utils.IsInRect(rolePosition, releaseSkillRect)) { needMove = false; } //转换为移动距离 return new ZTSize ( releaseSkillPosition.X-rolePosition.X,releaseSkillPosition.Y-rolePosition.Y); } /// /// 得到在范围内的怪的数量 /// /// /// /// 范围的长宽 /// 怪物的点坐标 /// private static Int32 InRangeNumber(Int32 x, Int32 y, ZTSize range, ZTPoint[] monsterPositions) { ZTRectangle rect = new ZTRectangle(x, y, x + range.Width, y + range.Height); int count = 0; for (int i = 0; i < monsterPositions.Length; i++) { if (Utils.IsInRect(monsterPositions[i], rect)) { count++; } } return count; } /// /// 排序 /// /// private static void Sort(Int32[] values) { Int32 temp = 0; for (int i = 0; i < values.Length - 1; i++) { for (int n = i + 1; n < values.Length; n++) { if (values[n] > values[i]) { temp = values[i]; values[i] = values[n]; values[n] = temp; } } } } } }