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
|
{
|
/// <summary>
|
/// 攻击范围
|
/// </summary>
|
public class AttackRectangle
|
{
|
/// <summary>
|
/// 计算目标距离,是否需要移动,和用户应该的朝向
|
/// </summary>
|
/// <param name="rolePosition"></param>
|
/// <param name="monsterPositions"></param>
|
/// <param name="movePriority"></param>
|
/// <param name="skill"></param>
|
/// <param name="direction"></param>
|
/// <param name="needMove"></param>
|
/// <returns></returns>
|
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;
|
}
|
|
|
|
|
/// <summary>
|
/// 得到最近的攻击目标距离
|
/// </summary>
|
/// <returns></returns>
|
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;
|
}
|
|
|
|
/// <summary>
|
/// 得到数量最多的攻击范围
|
/// </summary>
|
/// <param name="monsterRect"></param>
|
/// <param name="monsterPositions"></param>
|
/// <param name="yRange"></param>
|
/// <returns></returns>
|
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);
|
}
|
|
|
/// <summary>
|
/// 得到在范围内的怪的数量
|
/// </summary>
|
/// <param name="x"></param>
|
/// <param name="y"></param>
|
/// <param name="range">范围的长宽</param>
|
/// <param name="monsterPositions">怪物的点坐标</param>
|
/// <returns></returns>
|
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;
|
}
|
|
|
/// <summary>
|
/// 排序
|
/// </summary>
|
/// <param name="values"></param>
|
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;
|
}
|
}
|
}
|
}
|
|
|
|
|
|
}
|
}
|