/// <summary>
		/// UpdateTank runs the AI code that will update the tank's orientation and
		/// position. It is very similar to UpdateMouse, but is slightly more
		/// complicated: where mouse only has two states, idle and active, the Tank has
		/// three.
		/// </summary>
		private void UpdateTank ()
		{
			// However, the tank's behavior is more complicated than the mouse's, and so
			// the decision making process is a little different. 

			// First we have to use the current state to decide what the thresholds are
			// for changing state, as described in the doc.

			float tankChaseThreshold = TankChaseDistance;
			float tankCaughtThreshold = TankCaughtDistance;
			// if the tank is idle, he prefers to stay idle. we do this by making the
			// chase distance smaller, so the tank will be less likely to begin chasing
			// the cat.
			if (tankState == TankAiState.Wander) {
				tankChaseThreshold -= TankHysteresis / 2;
			}
			// similarly, if the tank is active, he prefers to stay active. we
			// accomplish this by increasing the range of values that will cause the
			// tank to go into the active state. 
			else if (tankState == TankAiState.Chasing) {
				tankChaseThreshold += TankHysteresis / 2;
				tankCaughtThreshold -= TankHysteresis / 2;
			}
			// the same logic is applied to the finished state. 
			else if (tankState == TankAiState.Caught) {
				tankCaughtThreshold += TankHysteresis / 2;
			}

			// Second, now that we know what the thresholds are, we compare the tank's 
			// distance from the cat against the thresholds to decide what the tank's
			// current state is.
			float distanceFromCat = Vector2.Distance (tankPosition, catPosition);
			if (distanceFromCat > tankChaseThreshold) {
				// just like the mouse, if the tank is far away from the cat, it should
				// idle.
				tankState = TankAiState.Wander;
			} else if (distanceFromCat > tankCaughtThreshold) {
				tankState = TankAiState.Chasing;
			} else {
				tankState = TankAiState.Caught;
			}

			// Third, once we know what state we're in, act on that state.
			float currentTankSpeed;
			if (tankState == TankAiState.Chasing) {
				// the tank wants to chase the cat, so it will just use the TurnToFace
				// function to turn towards the cat's position. Then, when the tank
				// moves forward, he will chase the cat.
				tankOrientation = TurnToFace (tankPosition, catPosition, tankOrientation, 
					TankTurnSpeed);
				currentTankSpeed = MaxTankSpeed;
			} else if (tankState == TankAiState.Wander) {
				// wander works just like the mouse's.
				Wander (tankPosition, ref tankWanderDirection, ref tankOrientation, 
					TankTurnSpeed);
				currentTankSpeed = .25f * MaxTankSpeed;
			} else {
				// this part is different from the mouse. if the tank catches the cat, 
				// it should stop. otherwise it will run right by, then spin around and
				// try to catch it all over again. The end result is that it will kind
				// of "run laps" around the cat, which looks funny, but is not what
				// we're after.
				currentTankSpeed = 0.0f;
			}

			// this calculation is also just like the mouse's: we construct a heading
			// vector based on the tank's orientation, and then make the tank move along
			// that heading.
			Vector2 heading = new Vector2 (
				(float)Math.Cos (tankOrientation), (float)Math.Sin (tankOrientation));
			tankPosition += heading * currentTankSpeed;
		}
Beispiel #2
0
        /// <summary>
        /// UpdateTank runs the AI code that will update the tank's orientation and
        /// position. It is very similar to UpdateMouse, but is slightly more
        /// complicated: where mouse only has two states, idle and active, the Tank has
        /// three.
        /// </summary>
        private void UpdateTank()
        {
            // However, the tank's behavior is more complicated than the mouse's, and so
            // the decision making process is a little different.

            // First we have to use the current state to decide what the thresholds are
            // for changing state, as described in the doc.

            float tankChaseThreshold  = TankChaseDistance;
            float tankCaughtThreshold = TankCaughtDistance;

            // if the tank is idle, he prefers to stay idle. we do this by making the
            // chase distance smaller, so the tank will be less likely to begin chasing
            // the cat.
            if (tankState == TankAiState.Wander)
            {
                tankChaseThreshold -= TankHysteresis / 2;
            }
            // similarly, if the tank is active, he prefers to stay active. we
            // accomplish this by increasing the range of values that will cause the
            // tank to go into the active state.
            else if (tankState == TankAiState.Chasing)
            {
                tankChaseThreshold  += TankHysteresis / 2;
                tankCaughtThreshold -= TankHysteresis / 2;
            }
            // the same logic is applied to the finished state.
            else if (tankState == TankAiState.Caught)
            {
                tankCaughtThreshold += TankHysteresis / 2;
            }

            // Second, now that we know what the thresholds are, we compare the tank's
            // distance from the cat against the thresholds to decide what the tank's
            // current state is.
            float distanceFromCat = Vector2.Distance(tankPosition, catPosition);

            if (distanceFromCat > tankChaseThreshold)
            {
                // just like the mouse, if the tank is far away from the cat, it should
                // idle.
                tankState = TankAiState.Wander;
            }
            else if (distanceFromCat > tankCaughtThreshold)
            {
                tankState = TankAiState.Chasing;
            }
            else
            {
                tankState = TankAiState.Caught;
            }

            // Third, once we know what state we're in, act on that state.
            float currentTankSpeed;

            if (tankState == TankAiState.Chasing)
            {
                // the tank wants to chase the cat, so it will just use the TurnToFace
                // function to turn towards the cat's position. Then, when the tank
                // moves forward, he will chase the cat.
                tankOrientation = TurnToFace(tankPosition, catPosition, tankOrientation,
                                             TankTurnSpeed);
                currentTankSpeed = MaxTankSpeed;
            }
            else if (tankState == TankAiState.Wander)
            {
                // wander works just like the mouse's.
                Wander(tankPosition, ref tankWanderDirection, ref tankOrientation,
                       TankTurnSpeed);
                currentTankSpeed = .25f * MaxTankSpeed;
            }
            else
            {
                // this part is different from the mouse. if the tank catches the cat,
                // it should stop. otherwise it will run right by, then spin around and
                // try to catch it all over again. The end result is that it will kind
                // of "run laps" around the cat, which looks funny, but is not what
                // we're after.
                currentTankSpeed = 0.0f;
            }

            // this calculation is also just like the mouse's: we construct a heading
            // vector based on the tank's orientation, and then make the tank move along
            // that heading.
            Vector2 heading = new Vector2(
                (float)Math.Cos(tankOrientation), (float)Math.Sin(tankOrientation));

            tankPosition += heading * currentTankSpeed;
        }