コード例 #1
0
        /// <summary>
        /// Wall Collision Checker
        /// </summary>
        public static bool Wall_Collision(Character character_entity, Shared.Direction direction)
        {
            //-------------------------------------
            // Produce a quick list of terrain entities within a direct radius of the character
            //-------------------------------------
            List <Terrain> quick_terrain_list = new List <Terrain>();

            // Get the side we're checking
            int x_side = 1; // 1 = Right side, -1 = Left side

            if (direction == Shared.Direction.LEFT)
            {
                x_side = -1;
            }

            //-------------------------------------
            // Block Adjacent
            Terrain block1 = Shared.Active_World.Get_Terrain_At(
                (int)character_entity.Grid_Position.X + x_side,
                (int)character_entity.Grid_Position.Y);

            if (block1 != null)
            {
                quick_terrain_list.Add(block1);
            }
            //-------------------------------------
            // Block Below Adjacent
            Terrain block2 = Shared.Active_World.Get_Terrain_At(
                (int)character_entity.Grid_Position.X + x_side,
                (int)character_entity.Grid_Position.Y + 1);

            if (block2 != null)
            {
                quick_terrain_list.Add(block2);
            }
            //-------------------------------------
            // Block Above Adjacent
            Terrain block3 = Shared.Active_World.Get_Terrain_At(
                (int)character_entity.Grid_Position.X + x_side,
                (int)character_entity.Grid_Position.Y - 1);

            if (block3 != null)
            {
                quick_terrain_list.Add(block3);
            }
            //-------------------------------------

            if (quick_terrain_list.Count() == 0)
            {
                return(false); // There are no blocks worth checking on this side, leave collision check
            }
            //-------------------------------------

            // Retrieve the character entities wall collision bound box
            //-------------------------------------
            Rectangle bound_box = new Rectangle
                                  (
                character_entity.Get_Bounds().X - 3,
                character_entity.Get_Bounds().Y,
                character_entity.Get_Bounds().Width + 6,
                character_entity.Get_Bounds().Height
                                  );

            //-------------------------------------

            foreach (Terrain terrain_entity in quick_terrain_list)
            {
                if (bound_box.Intersects(terrain_entity.Get_Bounds()))
                {
                    Rectangle c_bound = bound_box;
                    Rectangle t_bound = terrain_entity.Get_Bounds();
                    //--------------------
                    // We should first make sure this intersected peice of terrain isn't cleanly above or below
                    // the character entity
                    //--------------------
                    if (c_bound.Top > t_bound.Bottom || c_bound.Bottom < t_bound.Top)
                    {
                        return(false);
                    }

                    //  Safety check informs us if this is a floor rather than a wall.
                    // -------------------
                    if ((c_bound.Bottom - t_bound.Top) < 5)
                    {
                        return(false);
                    }
                    //--------------------
                    if (direction == Shared.Direction.LEFT)
                    {
                        // Left Wall Check
                        // -------------------
                        if (c_bound.Left < t_bound.Right && c_bound.Right > t_bound.Right)
                        {
                            // This bit helps ensure players don't exploit spam
                            // jumping against hole walls to breach the wall.
                            if (character_entity.Get_Bounds().Left < t_bound.Right)
                            {
                                character_entity.Shift(new Vector2(-1, 0));
                            }
                            // -------------------
                            return(true);
                        }
                        // -------------------
                    }
                    if (direction == Shared.Direction.RIGHT)
                    {
                        // Right Wall Check
                        // -------------------
                        if (c_bound.Right > t_bound.Left && c_bound.Left < t_bound.Left)
                        {
                            // This bit helps ensure players don't exploit spam
                            // jumping against hole walls to breach the wall.
                            if (character_entity.Get_Bounds().Right > t_bound.Left)
                            {
                                character_entity.Shift(new Vector2(1, 0));
                            }
                            // -------------------
                            return(true);
                        }
                        // -------------------
                    }
                }
            }
            //-------------------------------------
            return(false);
        }
コード例 #2
0
        /// <summary>
        /// Determines whether or not an NPC has Line of sight of an input target
        /// </summary>
        /// <param name="source">The source NPC</param>
        /// <param name="target">The target to look for</param>
        /// <param name="range">The LoS range in blocks</param>
        /// <returns>Returns true if the target character is within LoS</returns>
        public static bool Line_Of_Sight(NPC source, Entity target, int range)
        {
            // Establish essential calculation data
            //-------------------------------------

            //-------------------------------------
            // The NPC's source of sight. Grid position, plus the eye offset tells us where there 'eyes' are

            Vector2 NPC_sight_source = new Vector2
                                       (
                source.Grid_Position.X + source.Eye_Offset.X,
                source.Grid_Position.Y + source.Eye_Offset.Y
                                       );
            //-------------------------------------
            // The line slope from our target position and the NPC's sight source

            Vector2 sight_slope = new Vector2
                                  (
                target.Grid_Position.X - NPC_sight_source.X,
                (target.Grid_Position.Y - NPC_sight_source.Y -
                 (int)Math.Floor((target.Get_Bounds().Height / Shared.Block_Dimension / Shared.Pixel_Scale)))
                                  );
            //-------------------------------------
            // The absolute of the slope. We need to quantify values later.

            Vector2 absolute_slope = new Vector2
                                     (
                Math.Abs(sight_slope.X),
                Math.Abs(sight_slope.Y)
                                     );
            //-------------------------------------
            // Calculates the amount of blocks we'll need to check based on the
            // highest vertical or horizontal distance

            int block_count = (int)Math.Max
                              (
                absolute_slope.X,
                absolute_slope.Y
                              );

            //-------------------------------------
            // In order to prevent falling a block short through odd division,
            // add an extra block when using odd numbers

            if (block_count % 2 != 0)
            {
                block_count++;
            }
            //-------------------------------------

            //-------------------------------------
            // Set up some crucial variables

            int  block_X = 0;      // The current X position we're checking
            int  block_Y = 0;      // The current Y position we're checking
            bool x_split = false;  // Whether we're splitting the horizontal distance
            bool y_split = false;  // or the vertical distance. Distance splitting means we'll
                                   // get more natural lines, instead of L shapes

            int SPLIT_COUNT   = 0; // Initialize
            int split_counter = 0; // Initialize

            //-------------------------------------


            //-------------------------------------
            // Prepare split counting if necessary

            if (absolute_slope.X > absolute_slope.Y)
            {
                // Since the horizontal distance is greater, we'll dispere the vertical increment
                // evenly throughout the horizontal line to assure we don't get any L shaped LoS lines
                y_split       = true;
                SPLIT_COUNT   = (int)Math.Ceiling(absolute_slope.X / absolute_slope.Y);
                split_counter = SPLIT_COUNT;
            }
            else if (absolute_slope.Y > absolute_slope.X)
            {
                // Since the vertical distance is greater, we'll dispere the horizontal increment
                // evenly throughout the horizontal line to assure we don't get any L shaped LoS lines
                x_split       = true;
                SPLIT_COUNT   = (int)Math.Ceiling(absolute_slope.Y / absolute_slope.X);
                split_counter = SPLIT_COUNT;
            }
            //-------------------------------------

            //-------------------------------------
            // Now let's run through all the blocks we need to check!
            for (int block = 0; block < block_count + 1; block++)
            {
                //-------------------------------------
                // Increment or decrement depending on split & slope
                split_counter++;
                if (block_X > sight_slope.X && (!x_split || split_counter == SPLIT_COUNT))
                {
                    block_X--;
                }
                else if (block_X < sight_slope.X && (!x_split || split_counter == SPLIT_COUNT))
                {
                    block_X++;
                }

                if (block_Y > sight_slope.Y && (!y_split || split_counter == SPLIT_COUNT))
                {
                    block_Y--;
                }
                else if (block_Y < sight_slope.Y && (!y_split || split_counter == SPLIT_COUNT))
                {
                    block_Y++;
                }
                //-------------------------------------


                //-------------------------------------
                // Reset split counter
                if (split_counter > SPLIT_COUNT)
                {
                    split_counter = 1;
                }
                //-------------------------------------

                //-------------------------------------
                // Check current block location for solid blocks

                int     check_X = (int)(NPC_sight_source.X + block_X);
                int     check_Y = (int)(NPC_sight_source.Y + block_Y);
                Terrain terrain = Shared.Active_World.Get_Terrain_At(check_X, check_Y);
                //-------------------------------------
                if (terrain is Terrain)
                {
                    return(false); // A solid block lays in the way of our LoS
                }
                //-------------------------------------
            }

            return(true); // With all blocks between us and our target clear, we have LoS
            //-------------------------------------
        }
コード例 #3
0
        /// <summary>
        /// Ceiling Collision Checker
        /// </summary>
        public static bool Ceiling_Collision(Character character_entity)
        {
            //-------------------------------------
            // Check block above character for collision
            //-------------------------------------
            List <Terrain> quick_terrain_list = new List <Terrain>();

            //-------------------------------------
            // Block Atop
            Terrain block1 = Shared.Active_World.Get_Terrain_At(
                (int)character_entity.Grid_Position.X,
                (int)character_entity.Grid_Position.Y);

            if (block1 != null)
            {
                quick_terrain_list.Add(block1);
            }
            //-------------------------------------
            // Block Above
            Terrain block2 = Shared.Active_World.Get_Terrain_At(
                (int)character_entity.Grid_Position.X,
                (int)character_entity.Grid_Position.Y - 1);

            if (block2 != null)
            {
                quick_terrain_list.Add(block2);
            }
            //-------------------------------------

            if (quick_terrain_list.Count() == 0)
            {
                return(false); // There are no blocks worth checking on this side, leave collision check
            }
            // Retrieve the character entities wall collision bound box
            //-------------------------------------
            Rectangle bound_box = new Rectangle
                                  (
                character_entity.Get_Bounds().X + 5,
                character_entity.Get_Bounds().Y,
                character_entity.Get_Bounds().Width - 10,
                character_entity.Get_Bounds().Height
                                  );

            //-------------------------------------

            foreach (Terrain block in quick_terrain_list)
            {
                if (bound_box.Intersects(block.Get_Bounds()))
                {
                    // We've found a collision. Let's check if it's a ground collision!
                    //-------------------------------------
                    // Bound Boxes
                    //--------------------
                    Rectangle c_bound = bound_box;
                    Rectangle t_bound = block.Get_Bounds();
                    //--------------------
                    if (c_bound.Top < t_bound.Bottom)
                    {
                        if (c_bound.Bottom > t_bound.Bottom)
                        {
                            return(true);
                        }
                    }
                }
            }
            return(false);
            //-------------------------------------
        }