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;
}
Exemple #4
0
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;
}