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;
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;
}
}
}
}
///
/// 移动优化级
///
public enum MovePriority
{
Quantity,//数量集中为高优先级
Nearly//近为高优先级
}
}
}