diff --git a/src/collision.c b/src/collision.c index e5097a1..90fd4b0 100644 --- a/src/collision.c +++ b/src/collision.c @@ -3,22 +3,32 @@ #include "collision.h" /** - * @brief Collide sprite at (asx, asy) in 'at' at pos 'ap' with sprite at (bsx,bsy) - * in 'bt' at 'bp' * - * @param[in] at - Texture a. - * @param[in] asx - Position of x of sprite a. - * @param[in] asy - Position of y of sprite a. - * @param[in] ap - Position in space of sprite a. - * @param[in] bt - Texture b. - * @param[in] bsx - Position of x of sprite b. - * @param[in] bsy - Position of y of sprite b. - * @param[in] bp - Position in space of sprite b. + * @fn CollideSprite(const glTexture* at, const int asx, const int asy, + * const Vec2* ap, const glTexture* bt, + * const int bsx, const int bsy, const Vec2* bp, + * Vec2* crash) + * + * @brief Check whether or not sprites collide. + * + * This function does pixel perfect checks. If the collision actually accurs, + * crash is set to store the real position of the collision. + * + * @param[in] at - Texture a. + * @param[in] asx - Position of x of sprite a. + * @param[in] asy - Position of y of sprite a. + * @param[in] ap - Position in space of sprite a. + * @param[in] bt - Texture b. + * @param[in] bsx - Position of x of sprite b. + * @param[in] bsy - Position of y of sprite b. + * @param[in] bp - Position in space of sprite b. + * @param[out] crash - Actual position of the collision (only on collision). * @return 1 on collision, 0 else. */ int CollideSprite(const glTexture* at, const int asx, const int asy, const Vec2* ap, const glTexture* bt, - const int bsx, const int bsy, const Vec2* bp) { + const int bsx, const int bsy, const Vec2* bp, + Vec2* crash) { int x,y; int ax1, ax2, ay1, ay2; @@ -63,92 +73,43 @@ int CollideSprite(const glTexture* at, const int asx, const int asy, for(x = inter_x0; x <= inter_x1; x++) /* Compute offsets for surface before passing to TransparentPixel test. */ if((!gl_isTrans(at, abx + x, aby + y)) && - (!gl_isTrans(bt, bbx + x, bby + y))) + (!gl_isTrans(bt, bbx + x, bby + y))) { + + /* Set the crash position. */ + crash->x = x; + crash->y = y; return 1; + } return 0; } /** - * @brief Calculate collision path corrections. + * @fn int CollideLineSprite(const Vec2* ap, double dir, + * const glTexture* bt, const int bsx, const int bsy, + * const Vec2& bp, Vec2* crash) * - * @param[in] p - Position of object that's trying to collide. - * @param[in] v - Velocity of object that's trying to collide. - * @param[in] tp - Position of the target to collide into. - * @param[in] tv - Velocity of the target to collide into. - * @param[in] limit - Accuracy limit. - * @return Direction object will need to adjust velocity to for collision. + * @param[in] ap Origin of the line. + * @param[in] ad Direction of the line. + * @param[in] bt Texture b. + * @param[in] bsx Position of x of sprite b. + * @param[in] bsy Position of y of sprite b + * @param[in] bp Position in space of sprite b. + * @return 1 on Collision, else 0. + * + * @sa CollideSprite */ -/* - * Doesn't work as expected, needs to be fixed to allow missiles to use - * the physics engine instead of hacking their velocities. - */ -#if 0 -double CollidePath(const Vec2* p, Vec2* v, - const Vec2* tp, Vec2* tv, double limit) { +int CollideLineSprite(const Vec2* ap, double ad, + const glTexture* bt, const int bsx, const int bsy, const Vec2* bp, + Vec2* crash) { - double mx, my; /* Position modifiers. */ - double t, tt; /* Time to target. */ - Vec2 test, ttest; /* Test vector and target test vector. */ - double offset; /* Direction to face and error it produces. */ - double mod, moddir; /* Modifier for iteration. */ - int i; + (void)ap; + (void)ad; + (void)bt; + (void)bsx; + (void)bsy; + (void)bp; + (void)crash; - /* Test vector. */ - vect_cset(&test, tp->x - p->x, tp->y - p->y); /* Start byt straight line. */ - t = VMOD(test) / VMOD(*v); /* d=v*t ==> t=d/v. */ - - /* Target test vector. */ - vectnull(&ttest); /* Starting from itself. */ - tt = VMOD(ttest) / VMOD(*tv); - - /* Special case object isn't moving. */ - if(VMOD(*v) < 1e-6) - return VANGLE(test); - - /* Target faster than object. */ - if(VMOD(*v) < VMOD(*tv)) { - vect_reflect(&test, v, tv); - return VANGLE(test); - } - - /* Loop until error is minimal. */ - offset = tt - t; - moddir = 1.; /* Start off by position increments. */ - mod = 10.; /* Start off by a 10 second jump. */ - i = 0; - while(FABS(offset) > limit) { - if(i > 100) break; - - /* Calculate position modifiers. */ - if(offset < -mod/2.) /* tt>t ==> major overshot. */ - moddir = -1.; - else if(offset < 0.) { /* tt>t ==> overshot. */ - /* Invert direction and half. */ - moddir = -1.; - mod = mod/2.; - } - else if(offset > mod) /* tt undershot. */ - moddir = 1.; /* Make sure it's positive. */ - else if(offset > 0.) { /* tt minor undershot. */ - /* Positive and shrink step. */ - moddir = 1.; - mod = FABS(mod)/2.; - } - mx = tv->x * mod * moddir; - my = tv->y * mod * moddir; - - /* Increment test vectors. */ - vect_cadd(&test, mx, my); - vect_cadd(&ttest, mx, my); - - /* Compare results. */ - t = VMOD(test) / VMOD(*v); - tt = VMOD(ttest) / VMOD(*tv); - offset = tt - t; - - i++; - } - return VANGLE(test); } -#endif + diff --git a/src/collision.h b/src/collision.h index 02a5388..9aaefbe 100644 --- a/src/collision.h +++ b/src/collision.h @@ -5,9 +5,10 @@ /* Return 1 if collision is detected. */ int CollideSprite(const glTexture* at, const int asx, const int asy, const Vec2* ap, const glTexture* bt, - const int bsx, const int bsy, const Vec2* bp); + const int bsx, const int bsy, const Vec2* bp, + Vec2* crash); -/* Get direction to face the target. */ -/*double CollidePath(const Vec2* p, Vec2* v, - const Vec2* tp, Vec2* tv, const double limit);*/ +int CollideLineSprite(const Vec2* ap, double dir, + const glTexture* bt, const int bsx, const int bsy, const Vec2* bp, + Vec2* crash); diff --git a/src/menu.c b/src/menu.c index f3831bd..fc4e85a 100644 --- a/src/menu.c +++ b/src/menu.c @@ -150,7 +150,7 @@ static void menu_main_exit(char* str) { /* Ze ingame menu. */ /* Small ingame menu. */ void menu_small(void) { - if((player == NULL) player_isFlag(PLAYER_DESTROYED) + if((player == NULL) || player_isFlag(PLAYER_DESTROYED) || pilot_isFlag(player, PILOT_DEAD) || (menu_isOpen(MENU_MAIN) || menu_isOpen(MENU_SMALL) || diff --git a/src/weapon.c b/src/weapon.c index e8e9c79..782aab3 100644 --- a/src/weapon.c +++ b/src/weapon.c @@ -68,7 +68,7 @@ static Weapon* weapon_create(const Outfit* outfit, const double dir, static void weapon_render(const Weapon* w); static void weapons_updateLayer(const double dt, const WeaponLayer layer); static void weapon_update(Weapon* w, const double dt, WeaponLayer layer); -static void weapon_hit(Weapon* w, Pilot* p, WeaponLayer layer); +static void weapon_hit(Weapon* w, Pilot* p, WeaponLayer layer, Vec2* pos); static void weapon_destroy(Weapon* w, WeaponLayer layer); static void weapon_free(Weapon* w); /* Think. */ @@ -313,6 +313,7 @@ static void weapon_render(const Weapon* w) { static void weapon_update(Weapon* w, const double dt, WeaponLayer layer) { int i, wsx, wsy, psx, psy; glTexture* gfx; + Vec2 crash; gfx = outfit_gfx(w->outfit); @@ -329,16 +330,19 @@ static void weapon_update(Weapon* w, const double dt, WeaponLayer layer) { /* Smart weapons only collide with their target. */ if((weapon_isSmart(w)) && (pilot_stack[i]->id == w->target) && CollideSprite(gfx, wsx, wsy, &w->solid->pos, - pilot_stack[i]->ship->gfx_space, psx, psy, &pilot_stack[i]->solid->pos)) { - weapon_hit(w, pilot_stack[i], layer); + pilot_stack[i]->ship->gfx_space, psx, psy, &pilot_stack[i]->solid->pos, + &crash)) { + + weapon_hit(w, pilot_stack[i], layer, &crash); return; } /* Dumb weapons hit anything not of the same faction. */ if(!weapon_isSmart(w) && !areAllies(w->faction, pilot_stack[i]->faction) && CollideSprite(gfx, wsx, wsy, &w->solid->pos, - pilot_stack[i]->ship->gfx_space, psx, psy, &pilot_stack[i]->solid->pos)) { - weapon_hit(w, pilot_stack[i], layer); + pilot_stack[i]->ship->gfx_space, psx, psy, &pilot_stack[i]->solid->pos, + &crash)) { + weapon_hit(w, pilot_stack[i], layer, &crash); return; } } @@ -349,8 +353,16 @@ static void weapon_update(Weapon* w, const double dt, WeaponLayer layer) { (*w->solid->update)(w->solid, dt); } -/* Good shot. */ -static void weapon_hit(Weapon* w, Pilot* p, WeaponLayer layer) { +/** + * fn static void weapon_hit(Weapon* w, Pilot* p, WeaponLayer layer, vec2* pos) + * + * @breif Weapon hit the pilot. + * @param w Weapon Involved in the collision. + * @param p Pilot that got it. + * @param layer Layer to which the weapon belongs. + * @param pos Position of the hit. + */ +static void weapon_hit(Weapon* w, Pilot* p, WeaponLayer layer, Vec2* pos) { /* Someone should let the ai know it's been attacked. */ if(!pilot_isPlayer(p)) { if((player_target == p->id) || (RNG(0,2) == 0)) { /* 33% chance. */ @@ -361,12 +373,10 @@ static void weapon_hit(Weapon* w, Pilot* p, WeaponLayer layer) { } ai_attacked(p, w->parent); } - spfx_add(outfit_spfx(w->outfit), - VX(w->solid->pos), VY(w->solid->pos), + spfx_add(outfit_spfx(w->outfit), pos->x, pos->y, VX(p->solid->vel), VY(p->solid->vel), SPFX_LAYER_BACK); } else - spfx_add(outfit_spfx(w->outfit), - VX(w->solid->pos), VY(w->solid->pos), + spfx_add(outfit_spfx(w->outfit), pos->x, pos->y, VX(p->solid->vel), VY(p->solid->vel), SPFX_LAYER_FRONT); /* Let the ship know that is should take some kind of damage. */