From 9f8b1be682be6c3045b041d3eb0242373e6a2d64 Mon Sep 17 00:00:00 2001 From: Allanis Date: Sun, 15 Sep 2013 22:34:11 +0100 Subject: [PATCH] [Add] Some untested collision detection routines. --- src/collision.c | 127 +++++++++++++++++++++++++++++++++++++++++++++--- src/collision.h | 5 +- 2 files changed, 124 insertions(+), 8 deletions(-) diff --git a/src/collision.c b/src/collision.c index 6c08f0d..0eb65c0 100644 --- a/src/collision.c +++ b/src/collision.c @@ -84,6 +84,44 @@ int CollideSprite(const glTexture* at, const int asx, const int asy, return 0; } +/** + * @fn int CollideLineLine(double s1x, double s1y, double e1x, double e1y, + * double s2x, double s2y, double e2x, double e2y) { + * + * @brief Check to see if two lines collide. + * @param[in] s1 ....... + */ +int CollideLineLine(double s1x, double s1y, double e1x, double e1y, + double s2x, double s2y, double e2x, double e2y, Vec2* crash) { + + double ua_t, ub_t, u_b; + double ua, ub; + + ua_t = (e2x - s2x) * (s1y - s2y) - (e2y - s2y) * (s1x - s2x); + ub_t = (e1x - s1x) * (s1y - s2y) - (e1y - s1y) * (s1x - s2x); + u_b = (e2y - s2y) * (e1x - s1x) - (e2x - s2x) * (e1y - s1y); + + if(u_b != 0.) { + ua = ua_t / u_b; + ub = ub_t / u_b; + + /* Intersection at a point. */ + if((0. <= ua) && (ua <= 1.) && (0. <= ub) && (ub <= 1.)) { + crash->x = s1x + ua * (e1x - s1x); + crash->y = s1y + ua * (e1y - s1y); + return 1; + } else + return 0; + } else { + /* Coincidence. */ + if((ua_t == 0.) || (ub_t == 0.)) + return 3; + /* Parallel. */ + else + return 2; + } +} + /** * @fn int CollideLineSprite(const Vec2* ap, double dir, * const glTexture* bt, const int bsx, const int bsy, @@ -99,16 +137,91 @@ int CollideSprite(const glTexture* at, const int asx, const int asy, * * @sa CollideSprite */ -int CollideLineSprite(const Vec2* ap, double ad, +int CollideLineSprite(const Vec2* ap, double ad, double al, const glTexture* bt, const int bsx, const int bsy, const Vec2* bp, Vec2* crash) { - (void)ap; - (void)ad; - (void)bt; - (void)bsx; - (void)bsy; - (void)bp; + (void) bt; + (void) bsx; + (void) bsy; + double ep[2], tr[2], v[2], mod; + int hits; + Vec2 tmp_crash, border[2]; + + /* Set up end point of line. */ + ep[0] = ap->x + al*cos(ad); + ep[1] = ap->y + al*sin(ad); + + /* Set up top right corner of the rectangle. */ + tr[0] = ap->x + al*cos(ad); + tr[1] = ap->y + al*sin(ad); + + /* Start check for rectangular collision. */ + hits = 0; + + /* Left border. */ + if(CollideLineLine(ap->x, ap->y, ep[0], ep[1], + bp->x, bp->y, bp->x, tr[1], &tmp_crash) != 0) { + border[hits].x = tmp_crash.x; + border[hits].y = tmp_crash.y; + hits++; + } + /* Top border. */ + if(CollideLineLine(ap->x, ap->y, ep[0], ep[1], + bp->x, tr[1], tr[0], tr[1], &tmp_crash) != 0) { + border[hits].x = tmp_crash.x; + border[hits].y = tmp_crash.y; + hits++; + } + /* Now we are going to have to make sure hits isn't 2. */ + /* Right border. */ + if((hits < 2) && CollideLineLine(ap->x, ap->y, ep[0], ep[1], + tr[0], tr[1], tr[0], bp->y, &tmp_crash) != 0) { + border[hits].x = tmp_crash.x; + border[hits].y = tmp_crash.y; + hits++; + } + /* Bottom border. */ + if((hits < 2) && CollideLineLine(ap->x, ap->y, ep[0], ep[1], + tr[0], bp->y, bp->x, bp->y, &tmp_crash) != 0) { + border[hits].x = tmp_crash.x; + border[hits].y = tmp_crash.y; + hits++; + } + + /* No hits - missed. */ + if(hits == 0) + return 0; + + /* Special case only one hit - Shouldn't happen, but just in case. */ + if(hits == 1) { + if(hits == 1) { + /* We just return the same point twise. */ + crash[0].x = crash[1].x = border[0].x; + crash[0].y = crash[1].y = border[0].y; + } + return 1; + } + + crash[0].x = border[0].x; + crash[0].y = border[0].y; + crash[1].x = border[1].x; + crash[1].y = border[1].y; + return 1; + + /* @todo Now we do a pixel perfect approach. */ + + /* directional vector (normalised). */ + v[0] = border[1].x - border[0].x; + v[1] = border[1].y - border[0].y; + /* Normalize. */ + mod = 2*MOD(v[0], v[1]); /* Multiply by two to reduce check amount. */ + v[0] /= mod; + v[1] /= mod; + + /* We start checking first border until we find collision. */ + tmp_crash.x = border[0].x; + tmp_crash.y = border[0].y; } diff --git a/src/collision.h b/src/collision.h index 9aaefbe..66e02cc 100644 --- a/src/collision.h +++ b/src/collision.h @@ -8,7 +8,10 @@ int CollideSprite(const glTexture* at, const int asx, const int asy, const int bsx, const int bsy, const Vec2* bp, Vec2* crash); -int CollideLineSprite(const Vec2* ap, double dir, +int CollideLineLine(double s1x, double s1y, double e1x, double e1y, + double s2x, double s2y, double e2x, double e2y, Vec2* crash); + +int CollideLineSrite(const Vec2* ap, double ad, double al, const glTexture* bt, const int bsx, const int bsy, const Vec2* bp, Vec2* crash);