void Projectile::Update(float elapsedTime) { // Test si les conditions de fin du projectile sont vraies if (m_timeToLive <= 0 || !m_shot || elapsedTime == 0) return; // Test si atteint la cible if( abs(m_destination.x - m_pos.x) < m_collisionRadius.x && abs(m_destination.y - m_pos.y) < m_collisionRadius.y && abs(m_destination.z - m_pos.z) < m_collisionRadius.z) { Hit(); return; } Vector3f speed = m_rot * m_speed; speed = speed * m_speed.Lenght(); // Met a jour la valeur de la vitesse en // fonction de l'acceleration et du temps m_speed += m_acceleration * elapsedTime; m_timeToLive -= elapsedTime; // distance entre le projectile et sa destination // chemin le plus court Vector3f distance; distance.x = m_pos.x - m_destination.x; distance.y = m_pos.y - m_destination.y; distance.z = m_pos.z - m_destination.z; // calculer l'angle entre les 2 vecteurs // fix imprecision float float n = distance.Dot(speed) / (distance.Lenght() * speed.Lenght()); if (n > 1) n = 1; else if (n < -1) n = -1; float angleA = acos(n); std::cout << angleA << std::endl; Vector3f axis = distance.Cross(speed); axis.Normalize(); // rotation autour de laxe float rotation; if (abs(angleA) >= m_maxRot && abs(angleA) < PII - m_maxRot) { rotation = (angleA > 0) ? -m_maxRot : m_maxRot; rotation *= elapsedTime; } else rotation = angleA - PII; Quaternion q; q.FromAxis(rotation, axis); q.Normalise(); m_rot = q * m_rot; m_rot.Normalise(); // calcul la nouvelle position m_pos += speed * elapsedTime; }
/** * Called when the AI doesn't have a target. In this case, it should just lock * the cursor to the middle of the screen. */ void ShootingAI::aimCursorAtMiddle(double dt) { Vector3D wouldHit; double ang = 0; Point3D aim = lastShotPos; // This target position is just in front of the ship. Point3D targetPos = ship->shotOrigin; /* Move the target position a bit in the forward direction to make sure * that it's in front of the ship, not behind it. */ ship->forward->movePoint(targetPos); Vector3D targetDir = (targetPos - ship->shotOrigin).getNormalized(); // This section of code does angle interpolation. // Find the angle between our vector and where we want to be. ang = acos(aim * targetDir); // Get our axis of rotation. wouldHit = (aim ^ targetDir); wouldHit.normalize(); if (ang > (gunRotSpeed * dt)) { Quaternion q; q.FromAxis(wouldHit, gunRotSpeed * dt); aim = q * aim; // Normalize the vector. aim.normalize(); } else { aim = targetDir; } ship->updateShotDirection(aim); lastShotPos = aim; }
/** Aims at an object. * * This function should be called multiple frames consecutively in order * to actually aim at the object. The gun barrel has a rotation time, * and this function takes care of moving the virtual barrel to where it * needs to be. This will take care of predicting where the target will * be based on its current velocity. * * @param dt time difference since last frame, for gun turning. * @return Whether or not the ship is ready to fire. */ bool ShootingAI::aimAt(double dt, Object3D* target) { Vector3D wouldHit; Vector3D randomVariation; double ang = 0; //------------------------------ // Add a random variation to the aim. // randomVariation is between <-1, -1, -1> and <1, 1, 1> randomVariation.randomMagnitude(); /* maxDifficulty - difficulty ensures that high difficulty means very * little is added onto the randomVariation. Low difficulty means that * a large number is added onto the randomVariation. * The accuracy scales exponentially. Even a max difficulty AI will have * some small randomIAVariationAmount per weapon. */ //randomVariation.scalarMultiplyUpdate(chosenWeapon->randomAIVariationAmount + (maxDifficulty - difficulty)/((float)difficulty / 2)); randomVariation.scalarMultiplyUpdate(chosenWeapon->randomAIVariationAmount + ((maxDifficulty - difficulty)*(maxDifficulty - difficulty)/15)); //aim.addUpdate(randomVariation); //----------------------------- Point3D aim = lastShotPos; Point3D targetPos = chosenWeapon->project(target, randomVariation); Vector3D targetDir = (targetPos - ship->shotOrigin).getNormalized(); // This section of code does angle interpolation. // Find the angle between our vector and where we want to be. ang = acos(aim * targetDir); // Get our axis of rotation. wouldHit = (aim ^ targetDir); wouldHit.normalize(); if (ang > (gunRotSpeed * dt)) { Quaternion q; q.FromAxis(wouldHit, gunRotSpeed * dt); aim = q * aim; // Normalize the vector. aim.normalize(); } else { aim = targetDir; } // The aiming should be clamped within a radius //double forwardDotAim = aim.dot(*ship->forward); double forwardDotAim = targetDir.dot(*ship->forward); /* double upDotAim = aim.dot(*ship->up); double rightDotAim = aim.dot(*ship->right); */ // (Root 2)/2 radians const double minForwardAimAmount = 0.707; ship->updateShotDirection(aim); lastShotPos = aim; bool shouldFire = !chosenWeapon->isOverheated() && chosenWeapon->shouldFire(&targetPos, &aim); /* If the cursor is going outside of the allowable range, choose a new target. * Make sure we don't fire. */ if(forwardDotAim < minForwardAimAmount) { needToChooseTarget = true; shouldFire = false; } return shouldFire; }
void Npc::Move(const Vector3f& destination, float elapsedTime) { if (elapsedTime == 0) return; // Gravité float distanceY = (m_speedGravity * elapsedTime) + (GRAVITY * elapsedTime * elapsedTime / 2.0f); if (!CheckCollision(Vector3f(m_pos.x, m_pos.y - distanceY, m_pos.z))) { m_speedGravity -= GRAVITY * elapsedTime; } else { m_speedGravity = 0; distanceY = 0; } // Test si atteint la destination if( abs(destination.x - m_pos.x) < 1 && abs(destination.y - m_pos.y) < 1 && abs(destination.z - m_pos.z) < 1) { } else { Vector3f deplacement; deplacement = m_rot * m_speed * elapsedTime; // chemin le plus court Vector3f distance; distance.x = m_pos.x - destination.x; distance.y = m_pos.y - destination.y; distance.z = m_pos.z - destination.z; // calculer l'angle entre les 2 vecteurs // fix imprecision float float n = distance.Dot(deplacement) / (distance.Lenght() * deplacement.Lenght()); if (n > 1) n = 1; else if (n < -1) n = -1; float angleA = acos(n); Vector3f axis = distance.Cross(deplacement); axis.Normalize(); // rotation autour de laxe float rotation; if (abs(angleA) >= m_maxRot && abs(angleA) < PII - m_maxRot) rotation = (angleA > 0) ? -m_maxRot : m_maxRot; else rotation = angleA - PII; Quaternion q; q.FromAxis(rotation, axis); q.Normalise(); m_rot = q * m_rot; m_rot.Normalise(); // Check collisions Vector3f curPos = m_pos; Vector3f newPos; newPos.x = curPos.x + deplacement.x; newPos.y = curPos.y; newPos.z = curPos.z; if(!CheckCollision(newPos + Vector3f(0,1,0))) m_pos.x += deplacement.x; newPos.x = curPos.x; newPos.y = curPos.y + deplacement.y; newPos.z = curPos.z; if(!CheckCollision(newPos + Vector3f(0,1,0))) m_pos.y += deplacement.y; newPos.x = curPos.x; newPos.y = curPos.y; newPos.z = curPos.z + deplacement.z; if(!CheckCollision(newPos + Vector3f(0,1,0))) m_pos.z += deplacement.z; } if (!m_flying) m_pos.y += distanceY; }