bool AABBvsTriangle(Manifold& m)
{
AABB_t* a = m.a->asAABB();
Triangle* b = m.b->asTriangle();
bool hypotenuse_case = collide_hyp(*b, m.b_p, m.a_p);
// test for projection overlap along the x-axis
float dist_x = m.a_p.x - m.b_p.x;
float a_proj = scalar_proj(a->xw, X_AXIS); // + scalar_proj(a->yw, X_AXIS);
float b_proj, overlap_x;
// determine the relative position of AABB to Triangle on the x-axis
if ((b->xw.x > 0 && dist_x < 0) || // b faces (+) and a is (-) of b
(b->xw.x < 0 && dist_x > 0)) // b faces (-) and a is (+) of b
{
// hypotenuse opposite from AABB along x-axis
overlap_x = a_proj - std::abs(dist_x);
}
else { // hypotenuse adjacent to AABB along y-axis
// float b_halfwidth_x = b->xw.x / 2; // NOTE: changed b->xw.x to halfwidth
dist_x = m.a_p.x - (m.b_p.x + b->xw.x);
overlap_x = a_proj + std::abs(b->xw.x) - std::abs(dist_x);
}
if (overlap_x > 0)
{
// test for projection overlap along the y-axis
float dist_y = m.a_p.y - m.b_p.y;
a_proj = /* scalar_proj(a->xw, Y_AXIS) + */ scalar_proj(a->yw, Y_AXIS);
float overlap_y;
// determine the relative position of AABB to Triangle on the y-axis
if ((b->yw.y > 0 && dist_y < 0) || // b faces (+) and a is (-) of b
(b->yw.y < 0 && dist_y > 0)) // b faces (-) and a is (+) of b
{
// hypotenuse opposite from AABB along x-axis
overlap_y = a_proj - std::abs(dist_y);
}
else { // hypotenuse adjacent to AABB along y-axis
// float b_halfwidth_y = b->yw.y / 2; // NOTE: changed b->yw.y to halfwidth
dist_y = m.a_p.y - (m.b_p.y + b->yw.y);
overlap_y = a_proj + std::abs(b->yw.y) - std::abs(dist_y);
}
if (overlap_y > 0)
{
if (!hypotenuse_case)
{
// project out of collision along the axis of least overlap
if (overlap_x < overlap_y) {
if (dist_x > 0) {
m.projection = vec2_t(overlap_x, 0); // x-axis is min
}
else {
m.projection = vec2_t(-overlap_x, 0);
}
}
else {
if (dist_y > 0) {
m.projection = vec2_t(0, overlap_y); // y-axis is min
}
else {
m.projection = vec2_t(0, -overlap_y);
}
}
return true;
}
else // special case for when hypotenuse lies between the two centers
{
// test for projection overlap along the 3rd separating axis
float dist_third =
(b->third_axis.x * (m.b_p.x - m.a_p.x))
+ (b->third_axis.y * (m.b_p.y - m.a_p.y));
// 3rd axis may contain negatives, so we need to use magnitude for the AABB
a_proj = std::abs(scalar_proj(a->xw, b->third_axis)) +
std::abs(scalar_proj(a->yw, b->third_axis));
// both legs are used bc they are halfwidths
b_proj = scalar_proj(b->xw, b->third_axis)
+ scalar_proj(b->yw, b->third_axis);
float overlap_third = a_proj + b_proj - std::abs(dist_third);
if (overlap_third > 0)
{
// project out of collision along the axis of least overlap
if (overlap_x < overlap_y) {
if (overlap_x < overlap_third) {
if (dist_x > 0) {
m.projection = vec2_t(overlap_x, 0); // x- axis is min
}
else {
m.projection = vec2_t(-overlap_x, 0);
}
}
else { // third axis is min
m.projection =
vec2_t(b->third_axis.x * overlap_third,
b->third_axis.y * overlap_third);
}
}
else {
if (overlap_y < overlap_third) {
if (dist_y > 0) {
m.projection = vec2_t(0, overlap_y); // y-axis is min
}
else {
m.projection = vec2_t(0, -overlap_y);
}
}
else { // third axis is min
m.projection =
vec2_t(b->third_axis.x * overlap_third,
b->third_axis.y * overlap_third);
}
}
return true;
}
}
}
}
return false;
}
struct Manifold
{
PhysObj* a; // unowned pointer to a
PhysObj* b; // unowned pointer to b
vec3_t a_p; // position of a
vec3_t b_p; // position of b
bool resolve = false;
vec2_t projection;
material_t material;
};
/* For each "armed" piece in play, mark the enemy piece closest to the shooter for
* removal, accounting for both friendly obstacles to line-of-sight and piece's
* with two hit rays (slingers)
*/
void Game_c::shootout()
{
std::vector<PiecePtr> live_pieces;
std::vector<PiecePtr> hit_pieces;
std::vector<PiecePtr>::iterator p1_it;
for (p1_it = mPlayer1Pieces.begin(); p1_it != mPlayer1Pieces.end(); ++p1_it)
{
if ((*p1_it)->getPlayState() == Piece_n::LIVE)
{
live_pieces.push_back(*p1_it);
}
}
std::vector<PiecePtr>::iterator p2_it;
for (p2_it = mPlayer2Pieces.begin(); p2_it != mPlayer2Pieces.end(); ++p2_it)
{
if ((*p2_it)->getPlayState() == Piece_n::LIVE)
{
live_pieces.push_back(*p2_it);
}
}
std::vector<PiecePtr>::iterator it;
for (it = live_pieces.begin(); it != live_pieces.end(); ++it)
{
if ((*it)->getPieceType() != Piece_n::PAWN)
{
Piece_n::Direction_e direction = (*it)->getDirection();
detectHit2(**it, direction, live_pieces);
if ((*it)->getPieceType() == Piece_n::SLINGER)
{
Piece_n::Direction_e secondary_direction;
switch(direction)
{
case Piece_n::UP : { secondary_direction = Piece_n::RIGHT; break; }
case Piece_n::DOWN : { secondary_direction = Piece_n::LEFT; break; }
case Piece_n::LEFT : { secondary_direction = Piece_n::UP; break; }
case Piece_n::RIGHT : { secondary_direction = Piece_n::DOWN; break; }
}
detectHit2(**it, secondary_direction, live_pieces);
}
}
}
}
void Game_c::detectHit(Piece_n::Piece_c& piece,
Piece_n::Direction_e direction,
std::vector<PiecePtr>& pieces)
{
// true once if we have already hit a piece (monodirectional)
bool hit_piece_flag = false;
// stores the hit piece closest to the shooter
PiecePtr hit_piece;
switch (direction)
{
case Piece_n::UP :
{
std::vector<PiecePtr>::iterator it;
for (it = pieces.begin(); it != pieces.end(); ++it)
{
if ((*it)->getPlayState() == Piece_n::LIVE)
{
if ((*it)->getPosition().first == piece.getPosition().first &&
(*it)->getPosition().second < piece.getPosition().second)
{
if (hit_piece_flag)
{
if ((*it)->getPosition().second > hit_piece->getPosition().second)
{
hit_piece = *it;
}
}
else
{
hit_piece = *it;
hit_piece_flag = true;
}
}
}
}
break;
}
// ... case for each other possible piece direction: DOWN, LEFT, RIGHT
}
if (piece.getTeam() != hit_piece->getTeam())
{
hit_piece->nextPlayState();
}
}