Пример #1
0
        // Based on the Input keys provided and the distance calculated in the update
        // method, the position of the player is changed. The direction to move in is calculated
        // by direction vector = (cos(angle), sin(angle)). Animation is updated accordingly.
        public void PlayerMovement(Keys[] InputKeys, GridLayer grid)
        {
            Vector2 v2NewPos; // Stores the position to which the player is being moved.
            float   rotation = 0;

            Animation.Active = false;
            for (int intKeyIndex = 0; intKeyIndex < 4; intKeyIndex++)
            { // Loops through each key in the key array, checks if it is pressed and moves the player in the direction
                // corresponding to the key. See game screen initialize method for full keys array.
                if (ScreenManager.Instance.KeyState.IsKeyDown(InputKeys[intKeyIndex]))
                {
                    EntityRotation  = rotation;
                    EntityDirection = new Vector2((float)Math.Cos(EntityRotation), (float)Math.Sin(EntityRotation));
                    EntityDirection.Normalize();
                    // Stores the position to which the player is going to be moved.
                    v2NewPos = EntityPosition + (EntityDirection * Distance);
                    if (LegalPosition(v2NewPos, grid))
                    {
                        EntityPosition = v2NewPos;
                    }
                    TmpCurrentFrameY = intKeyIndex;
                    // Sprite sheet order of rows must be the same as the order of the keys for movement.
                    // for this to work.
                    Animation.Active = true;
                }
                rotation += (float)Math.PI / 2;
            }
            TmpCurrentFrameX       = Animation.CurrentFrame.X;
            Animation.Position     = EntityPosition;
            Animation.CurrentFrame = TmpCurrentFrame;
        }
Пример #2
0
        // Finds the position where the line has intersected a non-traversable object (where the line has ended).
        private Vector2 IntersectionPoint(GridLayer grid, Point PointStart, Point PointEnd)
        {
            // Creates a line of points using the Bresenham's line algorithm.
            List <Point> Line = BresenhamLine(PointStart.X, PointStart.Y, PointEnd.X, PointEnd.Y);

            listPoints = new List <Point>();

            Vector2 EndPoint = new Vector2(PointEnd.X, PointEnd.Y); // Contains the position where the line has ended.

            for (int intPointIndex = 0; intPointIndex < Line.Count(); intPointIndex++)
            {
                Node nodeToCheck = grid.GetNode(Line[intPointIndex]); // Retrieve the node which the current point is within.

                if (!nodeToCheck.Traversable)
                { // If the node within which the point is located is not traversable, the intersection point has been found.
                    EndPoint = new Vector2(Line[intPointIndex].X, Line[intPointIndex].Y);

                    Line.RemoveRange(intPointIndex, Line.Count - intPointIndex); // Remove any excess points past the end point.
                    break;
                    // Then exit the loop as a point of intersection has been found (where the line must end).
                }
            }

            // Adds one point for every 40 points in the original list.
            for (int intListIndex = 0; intListIndex < Line.Count(); intListIndex += 40)
            {
                listPoints.Add(Line[intListIndex]);
            }

            return(EndPoint);
        }
Пример #3
0
        // Loops through the nodes on the map and set each node's texture according to the map string array.
        public void SetTextures(string[,] map, GridLayer grid)
        {
            for (int intRow = 0; intRow < map.GetLength(1); intRow++)
            {
                for (int intCol = 0; intCol < map.GetLength(0); intCol++)
                {
                    // Based on the value in the element of the map array, set the node's texture.
                    try
                    {
                        grid.Nodes[intCol, intRow].Texture      = content.Load <Texture2D>("Sprites/" + map[intCol, intRow]);
                        grid.Nodes[intCol, intRow].Texture.Name = map[intCol, intRow];
                    }
                    catch (ContentLoadException) // If the map file's contents were incorrect, use grass as a default texture.
                    {
                        grid.Nodes[intCol, intRow].Texture      = content.Load <Texture2D>("Sprites/grs");
                        grid.Nodes[intCol, intRow].Texture.Name = "grs";
                    }

                    // If the texture was grass, fruit, blade, lamp or light beam, make the node traversable.
                    if (map[intCol, intRow] == "grs" || map[intCol, intRow] == "drk" || map[intCol, intRow] == "bld" ||
                        map[intCol, intRow] == "lbm" || map[intCol, intRow] == "frt" || grid.Nodes[intCol, intRow].Texture.Name == "grs")
                    {
                        grid.Nodes[intCol, intRow].Traversable = true;
                    }
                    else
                    {
                        grid.Nodes[intCol, intRow].Traversable = false;
                    }
                }
            }
        }
Пример #4
0
 // Checks if a point is in a traversable node.
 private bool LegalPosition(Vector2 v2NewPos, GridLayer grid)
 {
     if (grid.GetNode(ToPoint(v2NewPos)).Traversable&& grid.GetNode(ToPoint(v2NewPos + new Vector2(RectEntityWidth, 0))).Traversable &&
         grid.GetNode(ToPoint(v2NewPos + new Vector2(0, RectEntityHeight))).Traversable&& grid.GetNode(ToPoint(v2NewPos + new Vector2(RectEntityWidth, RectEntityHeight))).Traversable)
     {
         return(true);
     }
     return(false);
 }
Пример #5
0
 // Visually draws the outline of nodes of the grid layer onto the screen using a texture.
 public void DrawNodes(SpriteBatch spriteBatch, GridLayer Grid)
 {
     for (int intRow = 0; intRow < Grid.Nodes.GetLength(1); intRow++)
     {
         for (int intCol = 0; intCol < Grid.Nodes.GetLength(0); intCol++)
         {
             spriteBatch.Draw(tx2Node, Grid.Nodes[intCol, intRow].Tile, Color.White);
         }
     }
 }
Пример #6
0
        // Loads a map into the grid.
        public void LoadMap(GridLayer grid)
        {
            string[,] strMap = new string[grid.Nodes.GetLength(0), grid.Nodes.GetLength(1)]; // Stores each node's texture value.
            string[] strAllLines = null;                                                     // Stores the lines to load in for the map's texture names.
            // Stores the path to the map file to load in.
            string strFilePath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"\ShadowMaze\" + strMapName + ".csv";

            if (File.Exists(strFilePath))
            {
                for (int intError = 0; intError < 3; intError++)
                {
                    try
                    {
                        strAllLines = File.ReadAllLines(strFilePath); // All the lines of the map file are loaded in to a single string array.
                        break;                                        // If the lines were read successfully, break out of this exception catching loop.
                    }
                    catch (IOException)                               // If the user has the map file open preventing it from being accessed, give the user 3 warnings to close it.
                    {
                        switch (intError)
                        {
                        case 0: // First warning.
                            ScreenManager.MessageBox(new IntPtr(0), "Attempting to load map. Another program is using the map file in Documents/ShadowMaze, please close it and click ok.", "Error", 0);
                            break;

                        case 1: // Second warning.
                            ScreenManager.MessageBox(new IntPtr(0), "If the map file is not closed, the map will not be loaded. Please close it and click ok.", "Error", 0);
                            break;

                        case 2: // Third warning.
                            ScreenManager.MessageBox(new IntPtr(0), "Map could not be loaded as the file is still in use. Close the file and try again if you wish to play.", "Error", 0);
                            ScreenManager.Instance.PopScreen();
                            return; // Exit the method if the lines couldn't be read.
                        }
                    }
                }
            }
            else
            { // If the file does not exist, display an error message.
                ScreenManager.MessageBox(new IntPtr(0), "The map file doesn't exist. Please do not tamper with game files. It is recommended that you delete this map from this menu to avoid future problems.", "Error", 0);
                ScreenManager.Instance.PopScreen();
                return;
            }
            // The two dimensional map array is filled by splitting each individual line in the allLines array.
            // The individual values correspond to the texture to be used for the node at that position.
            for (int intRow = 0; intRow < strAllLines.GetLength(0); intRow++)
            {
                string[] line = strAllLines[intRow].Split(',');
                for (int intCol = 0; intCol < line.GetLength(0) - 1; intCol++)
                {
                    strMap[intCol, intRow] = line[intCol];
                }
            }
            SetTextures(strMap, grid);
        }
Пример #7
0
        // Processes whatever power-up/item the player has equipped.
        public void ProcessItem(GridLayer grid, AddShadowCopy[] addShadowCopies, ShadowCopy[] shadowCopies, Texture2D tx2ShadowCopy)
        {
            switch (strItem)
            {
            case "drk":     // If the node contained a dark area, spawn an additional shadow copy.
            {
                if (addShadowCopies.Contains(null))
                {
                    int intNewCopyIndex;
                    intNewCopyIndex = Array.IndexOf(addShadowCopies, null);
                    addShadowCopies[intNewCopyIndex]             = new AddShadowCopy();
                    addShadowCopies[intNewCopyIndex].EntityImage = tx2ShadowCopy;
                    addShadowCopies[intNewCopyIndex].Initialize(EntityNode);
                }
            }
                strItem = null;
                break;

            case "bld":
                EntityNode.Colour = Color.Red;     // Make the colour of the node the player is in red, to show a blade is equipped.
                for (int intCopyIndex = 0; intCopyIndex < shadowCopies.GetLength(0); intCopyIndex++)
                {
                    if (shadowCopies[intCopyIndex] != null && EntityNode.Tile.Intersects(shadowCopies[intCopyIndex].EntityNode.Tile))
                    {                   // If a shadow copy exists and it intersects the player, remove the copy.
                        shadowCopies[intCopyIndex] = null;
                        strItem = null; // Remove the player's item after use.
                    }
                }
                for (int intCopyIndex = 0; intCopyIndex < addShadowCopies.GetLength(0); intCopyIndex++)
                {
                    if (addShadowCopies[intCopyIndex] != null && EntityNode.Tile.Intersects(addShadowCopies[intCopyIndex].EntityNode.Tile))
                    {                   // If a shadow copy exists and it intersects the player, remove the copy.
                        addShadowCopies[intCopyIndex] = null;
                        strItem = null; // Remove the player's item after use.
                    }
                }
                // if a shadow copy is in the same node as a player with a blade. Remove the shadow copy.
                break;

            case "lbm":                                                       // Casts a light ray where the player is facing from the centre of the player.
                LightRay lightBeam = new LightRay(EntityPosition + new Vector2(RectEntityWidth / 2, RectEntityHeight / 2), EntityDirection, 200, grid);
                BeamKillCopy(grid, lightBeam, addShadowCopies, shadowCopies); // If the beam intersects a shadow copy, remove it.
                break;

            case "frt":
                intHealth = 1000;     // If the player has a fruit, reset the player's health to 100.
                strItem   = null;
                break;
            }
        }
Пример #8
0
        // Calls the player movement method, checks if the player has died and calls the process
        // item method if the player is holding an item.
        public void Update(GameTime gameTime, Keys[] InputKeys, GridLayer grid, AddShadowCopy[] addShadowCopies, ShadowCopy[] shadowCopies, Texture2D tx2ShadowCopy)
        {
            Distance = Speed * (float)gameTime.ElapsedGameTime.TotalSeconds;
            PlayerMovement(InputKeys, grid);
            RectEntityX = (int)EntityPositionX;
            RectEntityY = (int)EntityPositionY;

            if (intHealth <= 0)  // If the player's health has reached or dropped below zero.
            {
                boolDead = true; // The player has died.
            }
            if (strItem != null) // If the player is holding an item, process it.
            {
                ProcessItem(grid, addShadowCopies, shadowCopies, tx2ShadowCopy);
            }
            Animation.Update(gameTime);
        }
Пример #9
0
 // Raises the brightness of nodes which are visible and detects if a player is within field of vision.
 public bool InLineOfSight(GridLayer grid, Player player)
 {
     boolFound = false;
     foreach (LightRay line in LRRays)
     {
         foreach (Point point in line.Points)
         {
             // Loop through each point in each line, make the node which the point is within visible.
             grid.GetNode(point).Colour = Color.White;
             // Then check if the node at the point intersects the closest player's rectangle (is within line of sight).
             if (grid.GetNode(point).Tile.Intersects(player.RectEntity))
             {
                 boolFound = true;
             }
         }
     }
     return(boolFound);
 }
Пример #10
0
        // Calls AI methods for the shadow copy to either roam the map or follow players that have entered field of vision.
        // Deals damage to players which are in contact.
        public void Update(GameTime gameTime, Player[] player, GridLayer grid)
        {
            RectEntityX = (int)EntityPositionX;
            RectEntityY = (int)EntityPositionY;
            Distance    = Speed * (float)gameTime.ElapsedGameTime.TotalSeconds; // Sets distance to move according to speed.
            FindClosestPlayer(player);

            CastLightRays(grid);

            // If the player is found or was found previously and it hasn't been 1000 seconds since they were found, follow the player.
            if (boolFound == true || (prevBoolFound == true && intTrackTimer < 500))
            {
                PathToPlayer = new Path(EntityNode, player[TargetPlayer].EntityNode, grid.Nodes);
                FollowPath(PathToPlayer.NodePath, player[TargetPlayer]);
            }

            if (InLineOfSight(grid, player[TargetPlayer])) // If a player is within line of sight.
            {
                prevBoolFound = true;
                intTrackTimer = 0;    // It has been 0 seconds since they were found.
                defaultPath   = null; // Reset the default path as the shadow copy will be moving away from the path whilst following player.
            }
            else if (prevBoolFound == true && intTrackTimer < 500)
            {
                intTrackTimer += gameTime.ElapsedGameTime.Milliseconds; // If player was previously found and it hasn't been 500 milliseconds, increase the tinmer.
            }
            else
            { // If the timer has reached 500 milliseconds, the player is no longer found and the shadow copy should roam.
                prevBoolFound = false;
                FollowPath(grid);
            }

            if (EntityNode == player[TargetPlayer].EntityNode)           // If a shadow copy is in the same node as a player..
            {
                player[TargetPlayer].Health -= 5;                        // decrease the player's health.
                ScreenManager.Instance.SoundManager.PlaySound("Damage"); // and play the sound for damage.
            }

            UpdateAnimation();
            Animation.Update(gameTime);
            // Move the shadow copy in the set direction by the calculated distance.
            EntityPosition += Direction * Distance;
        }
Пример #11
0
        private Texture2D tx2Outline;      // Stores a blank texture with an outline for outlining toolbox items.

        // Instantiates grid, key checker and arrays etc. Sets button text and positions.
        public override void Initialize()
        {
            base.Initialize();
            MapEditGrid = new GridLayer(false);                              // Creates a small grid for editing.
            visGrid     = new VisibleGrid();                                 // Used to display the grid.
            strMap      = new string[MapEditGrid.Columns, MapEditGrid.Rows]; // Stores the map to save to a file.

            keyChecker     = new KeyChecker();
            v2ToolBoxPos   = new Vector2(800, 100);
            v2ToolBoxItems = new Vector2[2, 4];

            // Sets the positions for the toolbox items by looping through each item and adding the spacing value.
            Vector2 v2Spacing = new Vector2(0, 0);

            for (int intColumn = 0; intColumn < v2ToolBoxItems.GetLength(0); intColumn++)
            {
                for (int intItemIndex = 0; intItemIndex < v2ToolBoxItems.GetLength(1); intItemIndex++)
                {
                    v2ToolBoxItems[intColumn, intItemIndex] = v2ToolBoxPos + v2Spacing;
                    v2Spacing.Y += 50;
                }
                v2Spacing.X += 50;
                v2Spacing.Y  = 0;
            }

            buttons = new Button[3];
            for (int intButtonIndex = 0; intButtonIndex < buttons.GetLength(0); intButtonIndex++)
            {
                buttons[intButtonIndex] = new Button();
            }

            buttons[0].Text = "Open Map";
            buttons[1].Text = "Save Map";
            buttons[2].Text = "Back To Menu";

            buttons[0].Position = new Vector2(650, 400);
            buttons[1].Position = new Vector2(650, 500);
            buttons[2].Position = new Vector2(0, 500);

            strMapName = ""; // Sets the initial string as nothing so that it can be added to by the key checker.
        }
Пример #12
0
        // Casts light rays in the direction that the shadow copy is facing.
        public void CastLightRays(GridLayer grid)
        {
            // Stores the directions in which light rays should be casted.
            Vector2[] v2Directions = new Vector2[3];
            // Directions to cast lines in are calculated: direction vector = cos(angle) - sin(angle)
            v2Directions[0] = new Vector2((float)Math.Sin(EntityRotation), -(float)Math.Cos(EntityRotation));
            v2Directions[0].Normalize(); // Cast a light ray in the direction that the copy is facing.
            v2Directions[1] = new Vector2((float)Math.Sin(EntityRotation - 0.5), -(float)Math.Cos(EntityRotation - 0.5));
            v2Directions[1].Normalize(); // Cast a light ray to the left of the first one.
            v2Directions[2] = new Vector2((float)Math.Sin(EntityRotation + 0.5), -(float)Math.Cos(EntityRotation + 0.5));
            v2Directions[2].Normalize(); // Cast a light ray which is to the right of the first one.

            // Stores the centre of the shadow copy so that rays can be casted from there.
            Vector2 v2CentreOfCopy = EntityPosition + new Vector2(RectEntityWidth / 2, RectEntityHeight / 2);

            LRRays = new LightRay[3];
            // Create the light rays in the three directions using the constructor of the light ray class.
            for (int intRayIndex = 0; intRayIndex < 3; intRayIndex++)
            {
                LRRays[intRayIndex] = new LightRay(v2CentreOfCopy, v2Directions[intRayIndex], intSight, grid);
            }
        }
Пример #13
0
        // Causes the shadow copy to follow a random path (to roam the map).
        private void FollowPath(GridLayer grid)
        {
            // If the path isn't null, follow the path.
            if (defaultPath != null)
            {
                // Calculate the direction from the shadow copy to the next node it has to follow.
                Direction = new Vector2(defaultPath.NodePath[intNodeIndex].TileX, defaultPath.NodePath[intNodeIndex].TileY) - EntityPosition;
                // Calculate the angle the shadow copy is moving so that light rays can be cast in the same direction.
                EntityRotation = (float)Math.Atan2(Direction.X, -Direction.Y);
                Direction      = Vector2.Normalize(Direction);
                if (EntityNode == defaultPath.NodePath[intNodeIndex])
                {
                    intNodeIndex--;     // If the shadow copy has moved into the next node in the path. Move to the next one.
                }
                if (intNodeIndex == -1) // If the last node in the path has been reached. Set the path to null.
                {
                    defaultPath = null;
                }
            }
            else // Otherwise create a new random path.
            {
                Random rnd          = new Random(); // Creates a pseudo-random number generator.
                int    intRndColumn = rnd.Next(0, 21);
                int    intRndRow    = rnd.Next(0, 12);
                // Creates a path to a random node on the map.
                defaultPath = new Path(EntityNode, grid.Nodes[intRndColumn, intRndRow], grid.Nodes);

                // If the generated path was to a non-traversable node or was empty, the path is set to null
                // so that it can be recalculated in the next update.
                if (defaultPath.NodePath.Count > 1 && grid.Nodes[intRndColumn, intRndRow].Traversable)
                {
                    intNodeIndex = defaultPath.NodePath.Count - 1;
                }
                else
                {
                    defaultPath = null;
                }
            }
        }
Пример #14
0
 // Checks if a shadow copy is within the range of a light beam and removes it if it is.
 public void BeamKillCopy(GridLayer grid, LightRay lightBeam, AddShadowCopy[] addShadowCopies, ShadowCopy[] shadowCopies)
 { // Check each point in the beam, if the point is in the same node as a copy, remove the shadow copy.
     foreach (Point point in lightBeam.Points)
     {
         for (int intCopyIndex = 0; intCopyIndex < shadowCopies.GetLength(0); intCopyIndex++)
         {
             if (shadowCopies[intCopyIndex] != null && shadowCopies[intCopyIndex].RectEntity.Intersects(grid.GetNode(point).Tile))
             {                   // Only check and remove the copy if it actually exists.
                 shadowCopies[intCopyIndex] = null;
                 strItem = null; // Removes the player's item after use.
             }
         }
         for (int intCopyIndex = 0; intCopyIndex < addShadowCopies.GetLength(0); intCopyIndex++)
         {
             if (addShadowCopies[intCopyIndex] != null && addShadowCopies[intCopyIndex].RectEntity.Intersects(grid.GetNode(point).Tile))
             {                   // Only check and remove the copy if it actually exists.
                 addShadowCopies[intCopyIndex] = null;
                 strItem = null; // Removes the player's item after use.
             }
         }
         grid.GetNode(point).Colour = Color.White; // Makes any nodes in the beam brighter.
     }
 }
Пример #15
0
        private Texture2D tx2ShadowCopy;       // Stores the texture of shadow copies to spawn them.
        #endregion

        // Instantiates objects and initializes the game grid (creates the grid of nodes).
        // Provides the input keys for each player and sets every entity's
        // starting position.
        public override void Initialize()
        {
            base.Initialize();
            layerGameGrid = new GridLayer(true);
            player        = new Player[4];
            shadowCopy    = new ShadowCopy[4];
            switch (ScreenManager.Instance.Difficulty)
            {
            case "easy":
                addShadowCopy = new AddShadowCopy[0];
                break;

            case "intermediate":
                addShadowCopy = new AddShadowCopy[2];
                break;

            case "hard":
                addShadowCopy = new AddShadowCopy[4];
                break;

            case "impossible":
                addShadowCopy = new AddShadowCopy[6];
                break;
            }
            InputKeys = new Keys[4, 4];

            // four players are instantiated and each has their starting node set by the InitPos function.
            for (int intPlayerIndex = 0; intPlayerIndex <= 3; intPlayerIndex++)
            {
                player[intPlayerIndex] = new Player();
                player[intPlayerIndex].Initialize(InitPos(intPlayerIndex, layerGameGrid.Nodes));
            }
            // Sets the colour of players.
            player[0].Colour = Color.Blue;
            player[1].Colour = Color.ForestGreen;
            player[2].Colour = Color.Gold;
            player[3].Colour = Color.Red;

            // four shadow copies are instantiated and each has their starting node set by the InitPos function.
            for (int intCopyIndex = 0; intCopyIndex <= 3; intCopyIndex++)
            {
                shadowCopy[intCopyIndex] = new ShadowCopy();
                shadowCopy[intCopyIndex].Initialize(InitCopyPos(intCopyIndex, layerGameGrid.Nodes));
            }

            #region setKeys
            InputKeys[0, 0] = Keys.D;
            InputKeys[0, 1] = Keys.S;
            InputKeys[0, 2] = Keys.A;
            InputKeys[0, 3] = Keys.W;

            InputKeys[1, 0] = Keys.H;
            InputKeys[1, 1] = Keys.G;
            InputKeys[1, 2] = Keys.F;
            InputKeys[1, 3] = Keys.T;

            InputKeys[2, 0] = Keys.L;
            InputKeys[2, 1] = Keys.K;
            InputKeys[2, 2] = Keys.J;
            InputKeys[2, 3] = Keys.I;

            InputKeys[3, 0] = Keys.Right;
            InputKeys[3, 1] = Keys.Down;
            InputKeys[3, 2] = Keys.Left;
            InputKeys[3, 3] = Keys.Up;
            #endregion
        }
Пример #16
0
        // Constructor to set the starting and ending positions of the line upon creation of the light ray.
        public LightRay(Vector2 v2CastPoint, Vector2 v2Direction, int intDistanceToCast, GridLayer grid)
        {
            Point   PointStart = new Point((int)v2CastPoint.X, (int)v2CastPoint.Y); // Stores the start of the line.
            Vector2 v2EndPoint = v2CastPoint + v2Direction * intDistanceToCast;     // Sets the end vector2 according to direction.

            Point PointEnd = new Point((int)v2EndPoint.X, (int)v2EndPoint.Y);       // Stores the end point according to direction of the line.

            v2End = IntersectionPoint(grid, PointStart, PointEnd);                  // Calculate the line points using the start and end points.
        }
Пример #17
0
 // Draws the outline of the grid onto the screen.
 public void Draw(SpriteBatch spriteBatch, GridLayer Grid)
 {
     DrawNodes(spriteBatch, Grid);
 }