|
|
发表于 2009-5-21 19:08:00
|
显示全部楼层
Re:关于碰撞检测!
给一个 三角形- 点 的碰撞检测代码:
#ifndef _Hit_h_
#define _Hit_h_
#include <math.h>
#include <vector>
#define MIN_FLOAT 0.00001f
#define FLOAT_EQUAL(_a, _b) (fabs((_a) - (_b)) < MIN_FLOAT)
#define HTP_LEFT 0x1
#define HTP_RIGHT 0x2
#define HTP_UP 0x4
#define HTP_DOWN 0x8
// 直线
typedef struct _Line
{
float x, y, dx, dy; // 经过的一个点坐标
float k; // 斜率
bool v; // 是否垂直(忽略斜率)
char side; // 正确的面
_Line() : x(0), y(0), dx(0), dy(0), k(0), v(false), side(0) {}
_Line(float x1, float y1, float x2, float y2, char s)
{
FillLine(x1, y1, x2, y2, s);
}
void FillLine(float x1, float y1, float x2, float y2, char s)
{
// 分母为0
if(FLOAT_EQUAL(x2, x1))
{
x = x1;
y = y1;
k = 0;
v = true;
}
else
{
x = x1;
y = y1;
k = (y2 - y1) / (x2 - x1);
v = false;
}
dx = x2;
dy = y2;
side = s;
}
// 返回的是点相对于线的位置
char TestPoint(float px, float py) const
{
char flag = 0;
float t;
// 垂直
if(v)
{
t = px - x;
if(t >= 0) flag |= HTP_RIGHT;
if(t <= 0) flag |= HTP_LEFT;
}
// 水平
else if(fabs(k) < MIN_FLOAT)
{
t = py - y;
if(t >= 0) flag |= HTP_DOWN;
if(t <= 0) flag |= HTP_UP;
}
else
{
float ox = (py - y) / k;
float tmpx = x + ox;
t = px - tmpx;
if(t >= 0) flag |= HTP_RIGHT;
if(t <= 0) flag |= HTP_LEFT;
float oy = t * k;
if(oy >= 0) flag |= HTP_UP;
if(oy <= 0) flag |= HTP_DOWN;
}
return flag;
}
bool HitPoint(float px, float py) const
{
char flag = TestPoint(px, py);
bool bLR = false, bUD = false;
if(side & HTP_LEFT)
{
if(flag & HTP_LEFT) bLR = true;
}
else if(side & HTP_RIGHT)
{
if(flag & HTP_RIGHT) bLR = true;
}
else bLR = true;
if(side & HTP_UP)
{
if(flag & HTP_UP) bUD = true;
}
else if(side & HTP_DOWN)
{
if(flag & HTP_DOWN) bUD = true;
}
else bUD = true;
return bLR && bUD;
}
void SetSide(float px, float py)
{
char flag = TestPoint(px, py);
side = flag;
}
bool operator == (const _Line& ln) const
{
return (v == ln.v) && FLOAT_EQUAL(x, ln.x) && FLOAT_EQUAL(y, ln.y) && FLOAT_EQUAL(k, ln.k);
}
bool operator != (const _Line& ln) const
{
return !(*this == ln);
}
} Line;
// 检测三角形是否与点成功碰撞
#define IS_HITTING(_val) ((_val) == 0xF)
// 三角形
class Triangle
{
public:
Triangle() {}
Triangle(float x1, float y1, float x2, float y2, float x3, float y3, char s1, char s2, char s3)
{
FillTriangle(x1, y1, x2, y2, x3, y3, s1, s2, s3);
}
void FillTriangle(float x1, float y1, float x2, float y2, float x3, float y3, char s1, char s2, char s3)
{
m_Edges[0].FillLine(x1, y1, x2, y2, s1);
m_Edges[1].FillLine(x2, y2, x3, y3, s2);
m_Edges[2].FillLine(x3, y3, x1, y1, s3);
}
bool HitPoint(float px, float py) const
{
bool bOK = true;
bOK = bOK && m_Edges[0].HitPoint(px, py);
bOK = bOK && m_Edges[1].HitPoint(px, py);
bOK = bOK && m_Edges[2].HitPoint(px, py);
return bOK;
}
void GetEdges(Line edges[3]) const
{
edges[0] = m_Edges[0];
edges[1] = m_Edges[1];
edges[2] = m_Edges[2];
}
void SetSide(float px, float py)
{
m_Edges[0].SetSide(px, py);
m_Edges[1].SetSide(px, py);
m_Edges[2].SetSide(px, py);
}
bool operator == (const Triangle& tri) const
{
return (m_Edges[0] == tri.m_Edges[0]) && (m_Edges[1] == tri.m_Edges[1]) && (m_Edges[2] == tri.m_Edges[2]);
}
bool operator != (const Triangle& tri) const
{
return !(*this == tri);
}
private:
// 三边
Line m_Edges[3];
};
// 多边形
class Shape
{
public:
virtual ~Shape() {}
void AddTriangle(const Triangle& tri)
{
m_Polygon.push_back(tri);
}
void Clear()
{
m_Polygon.clear();
}
bool HitPoint(float px, float py) const
{
for(TriangleList::const_iterator i = m_Polygon.begin(); i != m_Polygon.end(); i++)
{
if(i->HitPoint(px, py)) return true;
}
return false;
}
protected:
typedef std::vector<Triangle> TriangleList;
TriangleList m_Polygon;
};
#endif
|
|