Files
diggaym/Collision.HC
CrunkLord420 f6a660f692 init
2021-08-11 08:47:58 -07:00

302 lines
7.6 KiB
HolyC

#ifndef COLLISION_HC
#define COLLISION_HC
#include "Vec"
#include "Map"
#define NO_COLLIDE 10000
public Bool CheckCollisionAABB(Vec4 *aabb1, Vec4 *aabb2) {
Bool d0 = aabb2->x2 < aabb1->x1;
Bool d1 = aabb1->x2 < aabb2->x1;
Bool d2 = aabb2->y2 < aabb1->y1;
Bool d3 = aabb1->y2 < aabb2->y1;
return !(d0 | d1 | d2 | d3);
}
public Bool CheckCollisionPoint(Vec4 *aabb, CD2 *p) {
Bool d0 = p->x < aabb->x1;
Bool d1 = p->y < aabb->y1;
Bool d2 = p->x > aabb->x2;
Bool d3 = p->y > aabb->y2;
return !(d0 | d1 | d2 | d3);
}
public Bool CheckICollisionPoint(I64 x1, I64 y1, I64 x2, I64 y2, I64 px, I64 py) {
Bool d0 = px < x1;
Bool d1 = py < y1;
Bool d2 = px > x2;
Bool d3 = py > y2;
return !(d0 | d1 | d2 | d3);
}
public Bool CheckPointAABB(I32 x, I32 y, I32 x1, I32 x2, I32 y1, I32 y2) {
if (x >= x1 && x <= x2 && y >= y1 && y <= y2)
return TRUE;
return FALSE;
}
public U0 CheckCollisionLines(Vec4 *l1, Vec4 *l2, CD2 *res) {
res->x = NO_COLLIDE;
res->y = NO_COLLIDE;
F64 collide = (l2->x2-l2->x1)*(l1->y2-l1->y1) - (l1->x2-l1->x1)*(l2->y2-l2->y1);
if (collide > 0.01) {
F64 lambda = ((l2->y1-l1->y1)*(l1->x2-l1->x1) - (l2->x1-l1->x1)*(l1->y2-l1->y1)) / collide;
F64 gamma = ((l2->y1-l1->y1)*(l2->x2-l2->x1) - (l2->x1-l1->x1)*(l2->y2-l2->y1)) / collide;
if (0.0 < lambda && lambda < 1.0 && 0.0 < gamma && gamma < 1.0) {
res->x = l2->x1 + lambda*(l2->x2 - l2->x1);
res->y = l2->y1 + lambda*(l2->y2 - l2->y1);
}
}
}
// res is array, eg. CD2 res[4]
public U0 CheckCollisionLineRec(Vec4 *l, Vec4* aabb, CD2* res) {
Vec4 l2;
// top-left - top-right
l2.x1 = aabb->x;
l2.y1 = aabb->y;
l2.x2 = aabb->x2;
l2.y2 = aabb->y;
CheckCollisionLines(l, &l2, &res[0]);
// top-left - bottom-left
l2.x1 = aabb->x;
l2.y1 = aabb->y2;
l2.x2 = aabb->x;
l2.y2 = aabb->y;
CheckCollisionLines(l, &l2, &res[1]);
// bottom-right - top-right
l2.x1 = aabb->x2;
l2.y1 = aabb->y;
l2.x2 = aabb->x2;
l2.y2 = aabb->y2;
CheckCollisionLines(l, &l2, &res[2]);
// bottom-right - bottom-left
l2.x1 = aabb->x2;
l2.y1 = aabb->y2;
l2.x2 = aabb->x;
l2.y2 = aabb->y2;
CheckCollisionLines(l, &l2, &res[3]);
}
public U0 ApplyVelCollideTile(Map *lvl, F64 delta, CD2 *pos, CD2 *vel, I32 w, I32 h) {
I32 tmpY, tmpX, i, tw, th;
// Collide X Axis
pos->x += vel->x * delta;
I32 x = Round(pos->x);
I32 y = Round(pos->y);
if (vel->x > 0.0) {
tmpX = (x+w)/16;
if (tmpX >= 0 && tmpX < lvl->width) {
tmpY = y/16;
th = Ceil((pos->y+h)/16)-tmpY;
for (i=0; i<th; i++) {
if (tmpY+i >= 0 && tmpY+i < lvl->height &&
lvl->flags[(tmpY+i)*lvl->width+tmpX] & TFLAG_BLOCK) {
pos->x = tmpX*16-w;
vel->x = 0;
break;
}
}
}
} else if (vel->x < 0.0) {
tmpX = pos->x/16;
if (tmpX >= 0 && tmpX < lvl->width) {
tmpY = y/16;
th = Ceil((pos->y+h)/16)-tmpY;
for (i=0; i<th; i++) {
if (tmpY+i >= 0 && tmpY+i < lvl->height &&
lvl->flags[(tmpY+i)*lvl->width+tmpX] & TFLAG_BLOCK) {
pos->x = tmpX*16+16;
vel->x = 0;
break;
}
}
}
}
// Collide Y Axis
pos->y += vel->y * delta;
x = Round(pos->x);
y = Round(pos->y);
if (vel->y > 0.0) {
tmpY = (y+h)/16;
if (tmpY >= 0 && tmpY < lvl->height) {
tmpX = x/16;
tw = Ceil((pos->x+w)/16)-tmpX;
for (i=0; i<tw; i++) {
if (tmpX+i >= 0 && tmpX+i < lvl->width &&
lvl->flags[tmpY*lvl->width+tmpX+i] & TFLAG_BLOCK) {
pos->y = tmpY*16-h;
vel->y = 0;
break;
}
}
}
} else if (vel->y < 0) {
tmpY = pos->y/16;
if (tmpY >= 0 && tmpY < lvl->height) {
tmpX = x/16;
tw = Ceil((pos->x+w)/16)-tmpX;
for (i=0; i<tw; i++) {
if (tmpX+i >= 0 && tmpX+i < lvl->width &&
lvl->flags[tmpY*lvl->width+tmpX+i] & TFLAG_BLOCK) {
pos->y = tmpY*16+16;
vel->y = 0;
break;
}
}
}
}
}
public U0 ApplyVelCollideTileBounce(Map *lvl, F64 delta, CD2 *pos, CD2 *vel, I32 w, I32 h) {
I64 tmpY, tmpX, i, tw, th;
// Collide X Axis
pos->x += vel->x * delta;
if (vel->x > 0.0) {
tmpX = (ToI64(pos->x) + w)/16;
if (tmpX >= 0 && tmpX < lvl->width) {
tmpY = pos->y/16;
th = Ceil((pos->y+h)/16)-tmpY;
for (i=0; i<th; i++) {
if (tmpY+i >= 0 && tmpY+i < lvl->height &&
lvl->flags[(tmpY+i)*lvl->width+tmpX] & TFLAG_BLOCK) {
pos->x = tmpX*16-w;
vel->x = -(vel->x/2);
break;
}
}
}
} else if (vel->x < 0.0) {
tmpX = ToI64(pos->x)/16;
if (tmpX >= 0 && tmpX < lvl->width) {
tmpY = pos->y/16;
th = Ceil((pos->y+h)/16)-tmpY;
for (i=0; i<th; i++) {
if (tmpY+i >= 0 && tmpY+i < lvl->height &&
lvl->flags[(tmpY+i)*lvl->width+tmpX] & TFLAG_BLOCK) {
pos->x = tmpX*16+16;
vel->x = -(vel->x/2);
break;
}
}
}
}
// Collide Y Axis
pos->y += vel->y * delta;
if (vel->y > 0.0) {
tmpY = (ToI64(pos->y)+h)/16;
if (tmpY >= 0 && tmpY < lvl->height) {
tmpX = ToI64(pos->x)/16;
tw = Ceil((pos->x+w)/16)-tmpX;
for (i=0; i<tw; i++) {
if (tmpX+i >= 0 && tmpX+i < lvl->width &&
lvl->flags[tmpY*lvl->width+tmpX+i] & TFLAG_BLOCK) {
pos->y = tmpY*16-h;
vel->y = -(vel->y/2);
break;
}
}
}
} else if (vel->y < 0) {
tmpY = ToI64(pos->y)/16;
if (tmpY >= 0 && tmpY < lvl->height) {
tmpX = ToI64(pos->x)/16;
tw = Ceil((pos->x+w)/16)-tmpX;
for (i=0; i<tw; i++) {
if (tmpX+i >= 0 && tmpX+i < lvl->width &&
lvl->flags[tmpY*lvl->width+tmpX+i] & TFLAG_BLOCK) {
pos->y = tmpY*16+16;
vel->y = -(vel->y/2);
break;
}
}
}
}
}
public U0 ApplyVelCollidePointTileBounce(Map *lvl, F64 delta, CD2 *pos, CD2 *vel) {
I64 tmpY, tmpX;
// Collide X Axis
pos->x += vel->x * delta;
if (vel->x > 0.0) {
tmpX = ToI64(pos->x+1)/16;
if (tmpX >= 0 && tmpX < lvl->width) {
tmpY = pos->y/16;
if (tmpY >= 0 && tmpY < lvl->height &&
lvl->flags[tmpY*lvl->width+tmpX] & TFLAG_BLOCK) {
pos->x = tmpX*16-1;
vel->x = -(vel->x/2);
}
}
} else if (vel->x < 0.0) {
tmpX = ToI64(pos->x-1)/16;
if (tmpX >= 0 && tmpX < lvl->width) {
tmpY = pos->y/16;
if (tmpY >= 0 && tmpY < lvl->height &&
lvl->flags[tmpY*lvl->width+tmpX] & TFLAG_BLOCK) {
pos->x = tmpX*16+16;
vel->x = -(vel->x/2);
}
}
}
// Collide Y Axis
pos->y += vel->y * delta;
if (vel->y > 0.0) {
tmpY = ToI64(pos->y+1)/16;
if (tmpY >= 0 && tmpY < lvl->height) {
tmpX = ToI64(pos->x)/16;
if (tmpX >= 0 && tmpX < lvl->width &&
lvl->flags[tmpY*lvl->width+tmpX] & TFLAG_BLOCK) {
pos->y = tmpY*16-1;
vel->y = -(vel->y/2);
}
}
} else if (vel->y < 0) {
tmpY = ToI64(pos->y-1)/16;
if (tmpY >= 0 && tmpY < lvl->height) {
tmpX = ToI64(pos->x)/16;
if (tmpX >= 0 && tmpX < lvl->width &&
lvl->flags[tmpY*lvl->width+tmpX] & TFLAG_BLOCK) {
pos->y = tmpY*16+16;
vel->y = -(vel->y/2);
}
}
}
}
public U0 ApplyDrag(F64 *vel, F64 amount, F64 delta) {
if (*vel > 0) {
*vel -= amount * delta;
if (*vel < 0) {
*vel = 0;
}
} else if (*vel < 0) {
*vel += amount * delta;
if (*vel > 0) {
*vel = 0;
}
}
/*
if (vel->y > 0) {
vel->y -= amount * delta;
if (vel->y < 0) {
vel->y = 0;
}
} else if (vel->y < 0) {
vel->y += amount * delta;
if (vel->y > 0) {
vel->y = 0;
}
}
*/
}
#endif