Version:alpha 2.4
Information:
代码摘自我自己的一个项目的一段代码
本文是类似日记形式,可以帮助需要的人,我在未来也会回来看(忘了时)
2022.3.18时我还只是12岁,许多公式不知道,故引用了网上许多博主的代码,原博客地址在注释内有所体现
这是建立在SDL2上的游戏引擎,这很低级,大佬勿喷
class Spirit {
public:
void SetPicture(SDL_Texture* image);
void SetHitBox(const vector<SDL_LFPoint> hit_box);
void SetDirection(double direction);
void SetSize(double sz);
void SetBaseDirection(double _basedir);
double GetSize();
void Move(double speed);
void Update();
void SetPostion(SDL_LFPoint pos);
void SetRotatePoint(SDL_LFPoint pos);
vector<SDL_LFPoint> GetHitBox();
SDL_Texture* GetPicture();
double GetDirection();
SDL_LFPoint GetPos();
bool Spirit::IsHitWith(const vector<SDL_LFPoint>);
SDL_LFPoint GetRotatePoint();
SDL_LFPoint GetPostion();
protected:
vector<SDL_LFPoint> hitBox;
vector<SDL_LFPoint> rotateHitBox;
SDL_LFPoint place, rotatePoint;
SDL_Texture* picture;
double dir, basedir;
double size = 1.0;
};
以下是一些你可能需要的明白的东西
首先,我们使一个精灵的碰撞箱是一个多边形用"vector<SDL_LFPoint>"来存
(注:如果一个多边形是vector<SDL_LFPoint> poly, 则poly[x]与poly[(x + 1) % poly.size()]连边)
那么你就看懂了bool Spirit::IsHitWith(const vector<SDL_LFPoint> box);的定义,两个多边形碰撞箱是否碰撞
Spirit::rotateHitBox是经过旋转处理(SetDirection())后的碰撞箱
那么我们如下处理:
1.如果两个多边形有边重叠,则它们一定相交
2.如果一条直线向任意方向延伸出一条射线,则如果与另一多边形的交点个数为奇数则一个在另一个里边(如果刚好交点在顶点,则要去掉一次,不然就会多一次)
3.否则不相交
注:这适用于任意多边形(包括凹多边形)
这里使用了qq_41726230::is_intersect()来自https://blog.csdn.net/qq_41726230/article/details/105037871
和自己推的HitPoint2Line()
SDL_LFPoint HitPoint2Line(SDL_LFPoint a1, SDL_LFPoint b1, SDL_LFPoint a2, SDL_LFPoint b2) {
double fa1 = (a1.y - b1.y) / (a1.x - b1.x);
double fa2 = a1.y - fa1 * a1.x;
double fb1 = (a2.y - b2.y) / (a2.x - b2.x);
double fb2 = a2.y - fb1 * a2.x;
double x = (fb2 - fa2) / (fa1 - fb1);
double y = fa1 * x + fa2;
return {
x, y };
}
bool Spirit::IsHitWith(const vector<SDL_LFPoint> box) {
if (box.empty() || this->hitBox.empty()) return false;
for (int i = 0; i < this->hitBox.size(); i++) {
qq_41726230::line la(
this->rotateHitBox[i].x * this->size + this->place.x, this->rotateHitBox[i].y * this->size + this->place.y,
this->rotateHitBox[i == this->rotateHitBox.size() - 1 ? 0 : i + 1].x * this->size + this->place.x,
this->rotateHitBox[i == this->rotateHitBox.size() - 1 ? 0 : i + 1].y * this->size + this->place.y
);
for (int j = 0; j < box.size(); j++) {
qq_41726230::line lb(
box[j].x, box[j].y,
box[j == box.size() - 1 ? 0 : j + 1].x,
box[j == box.size() - 1 ? 0 : j + 1].y
);
if (qq_41726230::is_intersect(la, lb)) {
return true;
}
}
}
qq_41726230::line l1(this->rotateHitBox[0].x * this->size + this->place.x, this->rotateHitBox[0].y * this->size + this->place.y, -100, -100);
int cnt[1] = {
};
for (int j = 0; j < box.size(); j++) {
qq_41726230::line lb(
box[j].x, box[j].y,
box[j == box.size() - 1 ? 0 : j + 1].x,
box[j == box.size() - 1 ? 0 : j + 1].y
);
int a = 0, b = 0;
if (qq_41726230::is_intersect(l1, lb)) cnt[0]++;
auto pos = HitPoint2Line({
l1.xa, l1.ya }, {
l1.xb, l1.yb }, {
lb.xa, lb.ya }, {
lb.xb, lb.yb });
if (pos.x == lb.xa && pos.y == lb.ya) {
cnt[0]--;
}
}
if (cnt[0] & 1) {
return true;
}
cnt[0] = 0;
qq_41726230::line l6(box[0].x, box[0].y, -100, -100);
for (int i = 0; i < this->hitBox.size(); i++) {
qq_41726230::line la(
this->rotateHitBox[i].x * this->size + this->place.x, this->rotateHitBox[i].y * this->size + this->place.y,
this->rotateHitBox[i == this-<