You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

217 lines
6.2 KiB

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
namespace CharacterEngine.Primitives
{
public class CEProjection
{
public Vector2 axis;
public float max;
public float min;
public CEProjection() { }
public CEProjection (CECollider coll, Vector2 axis)
{
Project(coll, axis);
}
public void Project(CECollider coll, Vector2 axis)
{
for (int i = 0; i < 4; i++)
{
Vector2 p = Vector3.Project(coll.GetPoint(i), axis);
float distance = p.magnitude * Mathf.Sign(Vector2.Dot(p, axis));
if (i == 0)
{
max = min = distance;
}
else
{
if (distance > max) max = distance;
else if (distance < min) min = distance;
}
}
}
}
public class CECollider
{
public static int[,] edges = new int[,]
{
{0, 2}, {0, 3}, {1, 2},{1, 3}
};
public static int[,] pointsNeighbours = new int[,]
{
{2, 3}, {3, 2}, {0, 1},{1, 0}
};
private BoxCollider2D collider;
public BoxCollider2D Coll
{
get { return collider; }
}
public virtual Vector2 position
{
get { return collider.bounds.center; }
}
public float Height
{
get { return (GetPoint(0) - GetPoint(3)).magnitude; }
}
public float Width
{
get { return (GetPoint(0) - GetPoint(2)).magnitude; }
}
public Vector2 Max
{
get { return GetPoint(0); }
}
public Vector2 Min
{
get { return GetPoint(1); }
}
public Vector2 AABBMax
{
get { return GetAABBPoint(0); }
}
public Vector2 AABBMin
{
get { return GetAABBPoint(1); }
}
public readonly Vector2[] localPoints;
public CECollider (BoxCollider2D coll)
{
collider = coll;
///COLLIDER CONSTANT RELATIVE POINTS
localPoints = new Vector2[]
{
coll.size * 0.5f, //max
-coll.size * 0.5f, //min
new Vector2(-coll.size.x * 0.5f, coll.size.y * 0.5f),
new Vector2(coll.size.x * 0.5f, -coll.size.y * 0.5f)
};
}
/// <summary>
/// GET REAL WORLD POINT OF COLLIDER
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
public Vector2 GetPoint (int index)
{
return position + (Vector2)(collider.transform.rotation * Vector2.Scale(localPoints[index], collider.transform.lossyScale));
}
public Vector2 GetPoint(int index, Vector2 position)
{
return position + (Vector2)(collider.transform.rotation * Vector2.Scale(localPoints[index], collider.transform.lossyScale));
}
public Vector2 GetAABBPoint(int index)
{
return position + (Vector2)(Vector2.Scale(localPoints[index], collider.transform.lossyScale));
}
public Vector2 GetAABBPoint(int index, Vector2 position)
{
return position + (Vector2)(Vector2.Scale(localPoints[index], collider.transform.lossyScale));
}
public Vector2 GetNormal(int index)
{
return Vector3.Cross(GetPoint(edges[index, 0]) - GetPoint(edges[index, 1]), Vector3.forward).normalized;
}
public Vector2 GetNormal(int index, Vector2 position)
{
return Vector3.Cross(GetPoint(edges[index, 0], position) - GetPoint(edges[index, 1], position), Vector3.forward).normalized;
}
public bool ContainsPoint (Vector2 p)
{
p = position + (Vector2)(Quaternion.Inverse(collider.transform.rotation) * (p - position));
bool insideX = p.x > AABBMin.x && p.x < AABBMax.x;
bool insideY = p.y > AABBMin.y && p.y < AABBMax.y;
return insideX && insideY;
}
public void Project(Vector2 normal, Vector2 p)
{
}
/// <summary>
/// Collision test along a path
/// </summary>
public CECollision SweepTest(Vector2 dir, float distance)
{
CECollision hit = new CECollision();
for (int i = 0; i <= CEPrimitives.sweepResolution; i++)
{
Vector2 currentDistance = dir.normalized * (distance * (i / CEPrimitives.sweepResolution));
hit = BoxCast(position + currentDistance);
if (hit.impulse.magnitude != 0.0f) break;
}
return hit;
}
/// <summary>
/// Collision test in an specific point
/// </summary>
public CECollision BoxCast(Vector2 position)
{
int mask = LayerMask.GetMask("Default");
CECollision collision = new CECollision();
RaycastHit2D outHit = new RaycastHit2D();
for (int i = 0; i < edges.GetLength(0); i++)
{
outHit = Physics2D.Linecast(GetPoint(edges[i, 0], position), GetPoint(edges[i, 1], position), mask);
if (!outHit)
{
outHit = Physics2D.Linecast(GetPoint(edges[i, 1], position), GetPoint(edges[i, 0], position), mask);
}
if (outHit) break;
}
if (outHit)
{
CECollider agent = new CECollider((BoxCollider2D)outHit.collider);
CECollider myAgent = new CEVirtualCollider(position, collider);
collision = CECollision.ResolveCollision(myAgent, agent);
}
return collision;
}
}
public class CEVirtualCollider : CECollider
{
protected Vector2 virtualPosition;
public override Vector2 position
{
get
{
return virtualPosition;
}
}
public CEVirtualCollider (Vector2 pos, BoxCollider2D coll) : base(coll)
{
virtualPosition = pos;
}
}
}