上一期做了圆形图片的不规则图形的算法用PolygonCollider2D的实现,但是突然很感兴趣其中具体算法的实现,刚好朋友在做这方面的编辑器功能,和他讨论并参考了一些相关资料,大概试了其中的一种思路。
首先,凸多边形范围判定,接上一节代码,由于已经存好了对应的各个顶点坐标,所以只需要获得点击的local坐标,然后进行对应判定就行。
public override bool IsRaycastLocationValid(Vector2 screenPoint, Camera eventCamera)
{
Vector2 point;
RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, screenPoint, eventCamera, out point);
return ContainsPoint(point);
}
public bool ContainsPoint(Vector2 p)
{
Vector2[] polyPoints = vertexs.ToArray();
var j = polyPoints.Length - 1;
var inside = false;
for (int i = 0; i < polyPoints.Length; j = i++)
{
var pi = polyPoints[i];
var pj = polyPoints[j];
if (((pi.y <= p.y && p.y < pj.y) || (pj.y <= p.y && p.y < pi.y)) && (p.x < (pj.x - pi.x) * (p.y - pi.y) / (pj.y - pi.y) + pi.x))
{
inside = !inside;
}
}
return inside;
}
表现上多各种不同类型的凸变形表现可以,但是当出现凹多边形的时候,就会出现空缺部位点击也会相应的情况,比如
点击缺口的时候依然会判断触发了点击,这里时候就需要用到凹变形分解多个凸变形,然后逐一判断点是否存在其中一个凸变形。下面是伪代码:
//判断是否为凹多边形
bool IsConcavePolygon(List<Vector2> p, out int i){
for (i = 0; i < p.Count; ++i)
{
//顺时针算当前顶点的i+1顶点以及i-1顶点的边的向量方向
va = p[i] - p[i-1];
vb = p[i + 1] - p[i];
//如果vb在va的左侧就可以判断符合凹变形标准 同时记录当前i的下标
if (Vector2.Cross(va ,vb)>0)
return true;
}
return false;
}
//收集分解的所有的多边形的顶点集合
void SplitConcavePolygon(List<Vector2> mList, List<List<Vector2>> list){
int idx;
//判断是否凸变形 如果是直接放入集合
if(!IsConcavePolygon(mList,out idx)){
list.Add(mList);
}else{
//否则收集判断出来的凸变形顶点
List<Vector2> small = new List<Vector2>();
List<Vector2> big = new List<Vector2>();
//判断出凹变形的起始点 为当前收集的终点
int end = idx;
//最少需要三个顶点
int start = end - 2;
//这里注意要加上初始点
big.Add(mList[end]);
for (int i = 0; i < count; i++)
{
if (i <= end)
{
small.Add(mList[i]);
}
else
{
big.Add(mList[i]);
}
}
//这里注意要加上终点
big.Add(mList[start]);
}
//收集好判断出来的凸变形顶点集合
list.Add(small);
//递归继续分离剩下的凹变形
SplitConcavePolygon(big, list);
}
获的顶点集合后画出顶点集合
如同所示 凹变形是成功分离出来了,但是这种思路有一个bug如白圈所示,是无法分辨不连续的点形成的凸变形的,这个有待后续再继续完善。