ICT290 / src / scene / AIController / Attacks / Projectile.cpp
Projectile.cpp
Raw
//
// Created by Micha on 19/09/2021.
//

#include "Projectile.h"

Projectile::Projectile(
    glm::vec2 target,   // the target's position
    GameWorld* world,   // a pointer to the world data
    int ShooterID,      // the ID of the bot that fired this shot
    glm::vec2 origin,   // the start position of the projectile
    glm::vec2 heading,  // the heading of the projectile
    int damage,         // how much damage it inflicts
    float scale,
    float MaxSpeed,
    float mass,
    float MaxForce,
    float turnRate)
    : MovingEntity(origin,
                   glm::vec2(scale, scale),
                   scale,
                   heading,
                   glm::vec2(0.0f, 0.0f),
                   mass,
                   MaxSpeed,
                   MaxForce,
                   turnRate),
      m_Target(target),
      m_Dead(false),
      m_World(world),
      m_DamageInflicted(damage),
      m_Origin(origin),
      m_ShooterID(ShooterID),
      m_TimeOfCreation(SDL_GetTicks()) {
    // m_LifeTime = 10000;
    // use sdl timer and set an alarm
    m_Impacted = false;
    m_OriginToTargetNormal = glm::normalize(m_Target - m_Origin);
    m_BoundingRadius = scale;
    // m_ImpactPoint = glm::vec2(.0f);

    m_ImpactPoint = m_World->getClosestWallIntersection(m_Position,
                                                        glm::normalize(
                                                            m_Target
                                                            - m_Position),
                                                        m_DistToClosestImpact);
    if (glm::length(m_Target - m_Position) > m_DistToClosestImpact)
        m_Target = m_ImpactPoint;
}

Vehicle* Projectile::getClosestIntersectingBot(glm::vec2 From,
                                               glm::vec2 To) const {
    Vehicle* ClosestIntersectingBot = nullptr;
    float ClosestSoFar = (std::numeric_limits<float>::max)();

    glm::vec2 rayNormal = glm::normalize(From - To);
    glm::vec2 fromLeft{From};
    glm::vec2 fromRight{From};

    if (rayNormal.x > rayNormal.y) {
        fromLeft.x -= m_Scale.x;
        fromRight.x += m_Scale.x;
    } else {
        fromLeft.y -= m_Scale.y;
        fromRight.y += m_Scale.y;
    }

    // iterate through all entities checking against the line segment FromTo
    for (auto curBot : m_World->m_Vehicles) {
        // make sure we don't check against the shooter of the projectile
        if (curBot->getID() != m_ShooterID) {
            float distance = 0;
            // if the distance to FromTo is less than the entity's bounding
            // radius then there is an intersection
            if (glm::intersectRaySphere(From,
                                        rayNormal,
                                        curBot->getPosition(),
                                        curBot->getBoundingRadius()
                                            * curBot->getBoundingRadius(),
                                        distance)
                || glm::intersectRaySphere(fromLeft,
                                           rayNormal,
                                           curBot->getPosition(),
                                           curBot->getBoundingRadius()
                                               * curBot->getBoundingRadius(),
                                           distance)
                || glm::intersectRaySphere(fromRight,
                                           rayNormal,
                                           curBot->getPosition(),
                                           curBot->getBoundingRadius()
                                               * curBot->getBoundingRadius(),
                                           distance)) {
                // test to see if this is the closest so far
                // float Dist = Vec2DDistanceSq((*curBot)->Pos(), m_Origin);

                if (distance < ClosestSoFar) {
                    ClosestSoFar = distance;
                    ClosestIntersectingBot = curBot;
                }
            }
        }
    }
    return ClosestIntersectingBot;
}

Vehicle* Projectile::getHitBot() const {
    for (auto curBot : m_World->m_Vehicles) {
        if (curBot->getID() != m_ShooterID) {
            float distance = glm::abs(
                glm::distance(m_Position, curBot->getPosition()));
            if (distance < curBot->getBoundingRadius() + m_BoundingRadius) {
                return curBot;
            }
        }
    }
    // No Bot
    return nullptr;
}

/*void Projectile::update(void) {
    if (!hasImpacted()) {
        // calculate the steering force
        glm::vec2 DesiredVelocity = glm::normalize(m_Target - m_Position)
                                    * getMaxSpeed();

        glm::vec2 sf = DesiredVelocity - m_VelocityVec;

        // update the position
        glm::vec2 accel = sf / m_mass;

        m_VelocityVec += accel;

        // make sure the slug does not exceed maximum velocity
        // get length difference and scale accordingly
        // float length = glm::length(m_VelocityVec);
        if (glm::length(m_VelocityVec) > m_MaxSpeed) {
            float speedScalar = m_MaxSpeed / glm::length(m_VelocityVec);
            m_VelocityVec = m_VelocityVec * speedScalar;
        }

        // update the position
        m_Position += m_VelocityVec;

        testForImpact();
    } else if (!isVisibleToPlayer()) {
        m_Dead = true;
    }
}*/

//---------------------- GetListOfIntersectingBots
//----------------------------
std::list<Vehicle*> Projectile::getListOfIntersectingBots(glm::vec2 From,
                                                          glm::vec2 To) const {
    // this will hold any bots that are intersecting with the line segment
    std::list<Vehicle*> hits;

    for (auto curBot : m_World->m_Vehicles) {
        // make sure we don't check against the shooter of the projectile
        if (curBot->getID() != m_ShooterID) {
            float distance = 0;
            glm::vec2 rayNormal = glm::normalize(From - To);
            // if the distance to FromTo is less than the entities bounding
            // radius then there is an intersection so add it to hits
            if (glm::intersectRaySphere(From,
                                        rayNormal,
                                        curBot->getPosition(),
                                        curBot->getBoundingRadius()
                                            * curBot->getBoundingRadius(),
                                        distance)) {
                hits.push_back(curBot);
            }
        }
    }

    return hits;
}

//----------------------------------- TestForImpact
//---------------------------
// void Projectile::testForImpact() {
//    // first find the closest wall that this ray intersects with. Then we
//    // can test against all entities within this range.
//    /*
//        if(glm::length(m_Target - m_Position) < 0.01){
//            m_Impacted = true;
//            m_Dead = true;
//
//        }
//        // test impact calculated, then get normalized vector from wall to
//        // projectile, and check if facing forward if(!m_ImpactPointCalcd)
//            m_ImpactPoint =
//            m_World->getClosestWallIntersection(m_Position,
//                                                             glm::normalize(
//                                                                 m_VelocityVec),
//                                                                 m_DistToClosestImpact);
//           //m_ImpactPointNormal = glm::normalize(m_ImpactPoint -
//           m_Position);
//       //just create a feeler like the wall avoidance.
//       //dont check
//*/
// float distToThisIP = 0.0;
// glm::vec2 intersectPoint(0.0f);
// for (const WallType& wall : m_World->currentLevel.getWalls()) {
//    if (LineSegmentIntersections(m_Position,             // line origin
//                                 m_Position + 0.1f,      // line end
//                                 wall.getOriginPoint(),  // wall origin
//                                 wall.getEndPoint(),
//                                 intersectPoint,
//                                 distToThisIP)) {
//        if (wall.getOriginPoint().x == wall.getEndPoint().x) {
//            if (intersectPoint.y <= wall.getEndPoint().y
//                && intersectPoint.y >= wall.getOriginPoint().y) {
//                m_Impacted = true;
//                m_Dead = true;
//                return;
//            }
//        } else {
//            if (intersectPoint.x <= wall.getEndPoint().x
//                && intersectPoint.x >= wall.getOriginPoint().x) {
//                m_Impacted = true;
//                m_Dead = true;
//                return;
//            }
//        }
//    }
//}
//
// glm::vec2 positionToTarget = m_Target - m_Position;
// float facing = dot(glm::normalize(positionToTarget),
// m_OriginToTargetNormal);
//
// if (glm::length((positionToTarget)) < glm::length(m_VelocityVec)
//    || facing < 0) {
//    m_Impacted = true;
//    m_Dead = true;
//}
//
//// test to see if the ray between the current position of the slug and
//// the start position intersects with any bots.
// std::list<Vehicle*> hits = getListOfIntersectingBots(m_Origin,
// m_Position);
//
///*
//    //if no bots hit just return;
//    if (hits.empty()) return;
//
//    //give some damage to the hit bots
//    std::list<Bot*>::iterator it;
//    for (it=hits.begin(); it != hits.end(); ++it)
//    {
//        //send a message to the bot to let it know it's been hit, and who
//   the
//        //shot came from
//        Dispatcher->DispatchMsg(SEND_MSG_IMMEDIATELY,
//                                m_iShooterID,
//                                (*it)->ID(),
//                                Msg_TakeThatMF,
//                                (void*)&m_iDamageInflicted);
//
//    }
//    */
//}
//