//=========================================================================================
        /// <summary>
        /// Scores the current behaviour and returns how relevant the AI thinks this action is
        /// </summary>
        /// <returns> A score for this current behaviour. </returns>
        //=========================================================================================
        public override float ScoreBehaviour()
        {
            // Get the AI sight module:

            AI_Sight b_sight = (AI_Sight) BehaviourSet.GetBehaviour("AI_Sight");

            // If not there abort:

            if ( b_sight == null ) return 0;

            // If there is no player then abort:

            if ( b_sight.Player == null ) return 0;

            // Otherwise see if the player is currenly marked as visible to the ai:

            if ( b_sight.PlayerInSight )
            {
                // Store the previous left and right scores here:

                float prev_score_left  = m_score_left;
                float prev_score_right = m_score_right;

                // Player is in sight: see how high above the ai character the player/breacrumb is

                float player_y_relative = b_sight.PlayerBreadcrumb.Y - ControlCharacter.Position.Y;

                // If the player is not above enough then forget this behaviour:

                if ( player_y_relative > PLAYER_MIN_RELATIVE_Y )
                {
                    // Ok.. player is above. Cast two rays to the left and right of the AI to look for walls

                    Core.Level.Collision.Intersect
                    (
                        ControlCharacter.Position                                       ,
                        ControlCharacter.Position - Vector2.UnitX * RAY_CAST_DISTANCE   ,
                        null
                    );

                    IntersectQueryResult intersect_l = Core.Level.Collision.GetClosestIntersect();

                    Core.Level.Collision.Intersect
                    (
                        ControlCharacter.Position                                       ,
                        ControlCharacter.Position + Vector2.UnitX * RAY_CAST_DISTANCE   ,
                        null
                    );

                    IntersectQueryResult intersect_r = Core.Level.Collision.GetClosestIntersect();

                    // See if there is a wall to the left:

                    if ( intersect_l.ValidResult && intersect_l.Normal.Y <= WALL_MAX_NORMAL_Y && intersect_l.Normal.Y >= WALL_MIN_NORMAL_Y )
                    {
                        // Wall to the left.. get our distance to the wall and the player/breacrumb distance

                        float c_dist = Vector2.Dot( ControlCharacter.Position - intersect_l.Point , intersect_l.Normal );
                        float p_dist = Vector2.Dot( b_sight.PlayerBreadcrumb  - intersect_l.Point , intersect_l.Normal );

                        // Make sure we are not behind that wall:

                        if ( c_dist >= 0 )
                        {
                            // Increase score by how close the player/breadcrumb is to that wall and how high up it is:

                            m_score_left += ( RAY_CAST_DISTANCE - p_dist ) * player_y_relative * PLAYER_HEIGHT_IMPORTANCE;

                            // Decrease the score by how far away we are from the wall

                            m_score_left -= c_dist * AI_WALL_DISTANCE_IMPORTANCE;

                            // Save this wall as the last left wall:

                            m_last_left_wall = intersect_l;
                        }
                        else
                        {
                            // Not behind wall: set left score to zero

                            m_score_left = 0;

                            // No last left wall:

                            m_last_left_wall.ValidResult = false;
                        }
                    }
                    else
                    {
                        // No wall to the left: set left score to zero

                        m_score_left = 0;

                        // No last left wall:

                        m_last_left_wall.ValidResult = false;
                    }

                    // See if there is a wall to the right:

                    if ( intersect_r.ValidResult && intersect_r.Normal.Y <= WALL_MAX_NORMAL_Y && intersect_r.Normal.Y >= WALL_MIN_NORMAL_Y )
                    {
                        // Wall to the left.. get our distance to the wall and the player/breadcrumb distance

                        float c_dist = Vector2.Dot( ControlCharacter.Position - intersect_r.Point , intersect_r.Normal );
                        float p_dist = Vector2.Dot( b_sight.PlayerBreadcrumb  - intersect_r.Point , intersect_r.Normal );

                        // Make sure we are behind that wall:

                        if ( c_dist >= 0 )
                        {
                            // Increase score to the right by how close we are to the wall and how high up the player/breadcrumb is

                            m_score_right += ( RAY_CAST_DISTANCE - p_dist ) * player_y_relative * PLAYER_HEIGHT_IMPORTANCE;

                            // Decrease the score by how far away we are from the wall

                            m_score_right -= c_dist * AI_WALL_DISTANCE_IMPORTANCE;

                            // Save this wall as the last right wall:

                            m_last_right_wall = intersect_r;
                        }
                        else
                        {
                            // No wall to the right: set left score to zero

                            m_score_right = 0;

                            // No last right wall:

                            m_last_right_wall.ValidResult = false;
                        }
                    }
                    else
                    {
                        // No wall to the right: set right score to zero

                        m_score_right = 0;

                        // No last right wall:

                        m_last_right_wall.ValidResult = false;
                    }

                }
                else
                {
                    // Player/breadcrumb is not above the ai. forget the behaviour

                    m_score_right = 0;
                    m_score_left  = 0;

                    // No last left and right walls:

                    m_last_left_wall.ValidResult    = false;
                    m_last_right_wall.ValidResult   = false;
                }

                // Interploate the current left and right scores with the previous

                m_score_left  *= ( 1.0f - SCORE_SMOOTHING );
                m_score_right *= ( 1.0f - SCORE_SMOOTHING );

                m_score_left  += prev_score_left  * SCORE_SMOOTHING;
                m_score_right += prev_score_right * SCORE_SMOOTHING;

                // Return the largest wall run score:

                if ( m_score_left > m_score_right ) return m_score_left * Importance; else return m_score_right * Importance;
            }
            else
            {
                // Player is not in sight: this behaviour does not apply

                m_last_left_wall.ValidResult    = false;
                m_last_right_wall.ValidResult   = false;

                return 0;
            }
        }
Exemple #2
0
        //=====================================================================================
        /// <summary>
        /// Intersect query function. If an object is collideable it should also implement code to 
        /// do a line / line intersection test here. It should return all of the intersections 
        /// found.
        /// </summary>
        /// <param name="lineStart">        Start point of the line involved.               </param>
        /// <param name="lineEnd">          End point of the line involved.                 </param>
        /// <param name="otherObject">      Object making the collision query, may be null. </param>
        /// <param name="results">          Array to save the results to.                   </param>
        /// <param name="results_index">    Index in the array to save the results to.      </param>
        /// <returns>                       Number of results from the intersection test.   </returns>
        //=====================================================================================
        public override int OnIntersectQuery( 
            Vector2                 lineStart           ,
            Vector2                 lineEnd             ,
            GameObject              otherObject         ,      
            IntersectQueryResult[]  results             ,
            int                     results_index
        )
        {
            // Abort if no room to save new result:

            if ( results_index >= results.Length ) return 0;

            // Store the result here:

            Vector2 intersect_point = Vector2.Zero;

            // Do it:

            bool intersection = m_line.IntersectInfinite( new Line(lineStart,lineEnd) , ref intersect_point );

            // See if there was an intersection:

            if ( intersection )
            {
                // Make up the result:

                IntersectQueryResult result;

                result.ValidResult      = true;
                result.QueryObject      = this;
                result.Point            = intersect_point;
                result.Normal           = Vector2.UnitY;
                result.PointDistance    = Vector2.Distance(lineStart,intersect_point);

                // Save the result:

                results[results_index] = result;

                // Got a result: return 1

                return 1;
            }
            else
            {
                // No result:

                return 0;
            }
        }
Exemple #3
0
        //=====================================================================================
        /// <summary>
        /// Intersect query function. If an object is collideable it should also implement code to 
        /// do a line / line intersection test here. It should return all of the intersections 
        /// found.
        /// </summary>
        /// <param name="lineStart">        Start point of the line involved.               </param>
        /// <param name="lineEnd">          End point of the line involved.                 </param>
        /// <param name="otherObject">      Object making the collision query, may be null. </param>
        /// <param name="results">          Array to save the results to.                   </param>
        /// <param name="results_index">    Index in the array to save the results to.      </param>
        /// <returns>                       Number of results from the intersection test.   </returns>
        //=====================================================================================
        public override int OnIntersectQuery( 
            Vector2                 lineStart           ,
            Vector2                 lineEnd             ,
            GameObject              otherObject         ,      
            IntersectQueryResult[]  results             ,
            int                     results_index
        )
        {
            // Abort if there is no more room for results:

            if ( results_index >= results.Length ) return 0;

            // Check out the collision cache and see if the ellipse is within bounds of our lines:

            if ( LevelCollisionQuery.IntersectionCache.RayBoxTopLeft.X      > m_lines_bb_bottom_right.X     ) return 0;
            if ( LevelCollisionQuery.IntersectionCache.RayBoxBottomRight.X  < m_lines_bb_top_left.X         ) return 0;
            if ( LevelCollisionQuery.IntersectionCache.RayBoxTopLeft.Y      < m_lines_bb_bottom_right.Y     ) return 0;
            if ( LevelCollisionQuery.IntersectionCache.RayBoxBottomRight.Y  > m_lines_bb_top_left.Y         ) return 0;

            // Store the number of results here:

            int num_results = 0;

            // Make a new line to test with:

            Line line = new Line( lineStart , lineEnd );

            // Collide the line with each of this object's lines:

            for ( int i = 0 ; i < m_collision_lines.Length ; i++ )
            {
                // Store the collision point here:

                Vector2 intersection_point = Vector2.Zero;

                // Do the intersection:

                bool lines_intersect = m_collision_lines[i].Intersect( line , ref intersection_point );

                // See if we got an intersection

                if ( lines_intersect )
                {
                    // Increment number of results:

                    num_results++;

                    // Get vector from line start to point of intersection

                    Vector2 r = intersection_point - lineStart;

                    // Get the distance to the point

                    float intersection_distance = Vector2.Dot( r , line.Direction );

                    // Make up the result:

                    IntersectQueryResult result;

                    result.ValidResult      = true;
                    result.QueryObject      = this;
                    result.Point            = intersection_point;
                    result.Normal           = m_collision_lines[i].Normal;
                    result.PointDistance    = intersection_distance;

                    // Save the result:

                    results[results_index] = result;

                    // Increment results index:

                    results_index++;

                    // If past the end then return number of results:

                    if ( results_index >= results.Length ) return num_results;
                }
            }

            // Return the number of collision results

            return num_results;
        }