// // 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::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 Projectile::getListOfIntersectingBots(glm::vec2 From, glm::vec2 To) const { // this will hold any bots that are intersecting with the line segment std::list 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 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::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); // // } // */ //} //