Пример #1
0
        void UpdateGameplay(float fDeltaTime)
        {
            if (!IsPaused)
            {
                m_Camera.Update(fDeltaTime);

                if (GameState.Get().Speed != eGameSpeed.Stop)
                {
                    float fAlteredTime = fDeltaTime * TimeFactor;

                    // We have to make a temp copy in case the objects list changes
                    LinkedList <GameObject> temp = new LinkedList <GameObject>(m_GameObjects);
                    foreach (GameObject o in temp)
                    {
                        if (o.Enabled)
                        {
                            o.Update(fAlteredTime);
                        }
                    }

                    m_Timer.Update(fAlteredTime);
                }

                // Use mouse picking to select the appropriate tile.
                Ray ray = InputManager.Get().CalculateMouseRay();
                m_CurrentTile = m_Level.Intersects(ray);
            }
        }
Пример #2
0
        // This selects a particular tile given a ray from the camera
        public Objects.Tile Intersects(Ray ray)
        {
            // It's possible that multiple tiles intersect, so we need to create a list
            // of potential tiles to select.
            LinkedList <Objects.Tile> possibles = new LinkedList <Objects.Tile>();

            foreach (Objects.Tile t in m_Tiles)
            {
                if (t.AABB.Intersects(ray) != null)
                {
                    possibles.AddLast(t);
                }
            }

            // Now select the tile that is the closest to the start position of the ray
            Objects.Tile retval    = null;
            float        fBestDist = 999999999.0f;

            foreach (Objects.Tile t in possibles)
            {
                float fDist = Vector3.DistanceSquared(t.Position, ray.Position);
                if (fDist < fBestDist)
                {
                    retval    = t;
                    fBestDist = fDist;
                }
            }

            return(retval);
        }
Пример #3
0
        public void SetupGameplay()
        {
            ClearGameObjects();
            m_UIStack.Clear();
            m_UIGameplay = new UI.UIGameplay(m_Game.Content);
            m_UIStack.Push(m_UIGameplay);

            m_bPaused = false;
            m_Speed   = eGameSpeed.Normal;
            m_Camera.ResetCamera();
            GraphicsManager.Get().ResetProjection();
            m_SelectedTile = null;
            m_CurrentTile  = null;

            m_Timer.RemoveAll();

            Money         = Balance.StartingMoney;
            Life          = Balance.StartingLife;
            m_WaveNumber  = 0;
            m_bWaveActive = false;
            SpawnWorld();

            // Start the timer for the first wave
            m_Timer.AddTimer("StartWave", Balance.FirstWaveTime, StartWave, false);
            m_bCanPlayAlarm = true;
        }
Пример #4
0
        // Helper function that creates the correct type of tile
        Objects.Tile CreateTile(Vector3 vPos, eTileType type = eTileType.Default)
        {
            Objects.Tile Tile = null;
            switch (type)
            {
            case (eTileType.Default):
                Tile = new Objects.Tile(m_Game);
                break;

            case (eTileType.Green):
                Tile = new Objects.TileGreen(m_Game);
                break;

            case (eTileType.Base):
                Tile = new Objects.TileGreen(m_Game);
                break;

            case (eTileType.Red):
                Tile = new Objects.TileRed(m_Game);
                break;

            case (eTileType.EnemySpawn):
                Tile = new Objects.TileRed(m_Game);
                break;
            }

            if (Tile != null)
            {
                Tile.Position = vPos;
                GameState.Get().SpawnGameObject(Tile);
                m_Tiles.AddLast(Tile);
            }

            return(Tile);
        }
Пример #5
0
        // This function is called when a new tile is clicked on and selected
        public void SetSelected(Objects.Tile t)
        {
            if (m_SelectedTile != null)
            {
                m_SelectedTile.IsSelected = false;
            }

            m_SelectedTile = t;

            // Notify the UI that a new tile has been selected
            m_UIGameplay.NewSelectedTile(t);

            if (m_SelectedTile != null)
            {
                m_SelectedTile.IsSelected = true;
            }
        }
Пример #6
0
        public override void Update(float fDeltaTime)
        {
            // Update the position between the two nodes
            if (m_LerpTo != null)
            {
                float fTotalDistance = Vector3.Distance(m_StartPos, m_EndPos);
                float fTotalTime = fTotalDistance / Balance.Enemies[m_Level - 1].Speed;
                float fSnareAmount = SnareFactor / 100.0f;
                m_fMoveTime += fDeltaTime * fSnareAmount;

                Position = Vector3.Lerp(m_StartPos, m_EndPos, m_fMoveTime / fTotalTime);

                // If we're at the target node, time to move on to the next one
                if (Vector3.Distance(Position, m_EndPos) < 0.05f)
                {
                    m_LerpFrom = m_LerpTo;
                    m_LerpTo = m_LerpFrom.parent;
                    m_StartPos = m_LerpFrom.tile.Position;
                    m_EndPos = m_LerpTo.tile.Position;

                    // Update the current tile
                    m_CurrentTile = m_LerpFrom.tile;

                    if (m_LerpTo != null)
                    {
                        m_fMoveTime = 0.0f;
                        SetDirection();
                    }
                }
            }

            // If we're at the goal node, deal damage and remove from the world
            if (Vector3.Distance(Position, Pathfinder.Get().GlobalGoalTile.Position) < 0.5f)
            {
                GameState.Get().DamageBase(Balance.Enemies[m_Level - 1].Damage);
                GameState.Get().RemoveEnemy(this);
            }

            base.Update(fDeltaTime);
        }
Пример #7
0
        public void ResetPath(bool bRecalculated = false)
        {
            if (m_Path != null)
            {
                m_LerpFrom = m_Path;
                m_CurrentTile = m_LerpFrom.tile;
                m_LerpTo = m_LerpFrom.parent;

                // If this was recalculated (because something was built),
                // set the start pos to the current one, so it smoothly transitions to the new path.
                if (bRecalculated)
                {
                    m_StartPos = Position;
                }
                else
                {
                    m_StartPos = m_LerpFrom.tile.Position;
                }

                m_EndPos = m_LerpTo.tile.Position;
                SetDirection();
            }
            else
            {
                // We have no path, so we're just stuck
                m_LerpFrom = null;
                m_LerpTo = null;
            }

            m_fMoveTime = 0.0f;
        }
Пример #8
0
 public void AddNeighbor(Tile t)
 {
     m_Neighbors.AddLast(t);
 }
Пример #9
0
        public virtual void LoadLevel(string sLevelName)
        {
            m_Tiles.Clear();
            int iWidth = 10;
            int iHeight = 5;

            int[,] TileData =
            {
                  {2,  0,  0,  0,  0,  0,  0,  0,  0,  0},
                {2,  2,  0,  0,  0,  0,  0,  0,  0,  0},
                  {4,  0,  0,  0,  0,  0,  0,  0,  0,  3},
                {2,  2,  0,  0,  0,  0,  0,  0,  0,  0},
                  {2,  0,  0,  0,  0,  0,  0,  0,  0,  0},
            };

            // Generate tile array based on width/height
            // (used to setup neighbors)
            Objects.Tile[,] Tiles = new Objects.Tile[iHeight, iWidth];

            float fPerColumn = 1.72f;
            float fPerRow = 1.5f;

            Objects.Tile BaseTile = null;
            Objects.Tile SpawnTile = null;

            int iColCount = 0;
            float fXOffset = -1.0f * (iWidth / 2) * fPerColumn;
            while (iColCount < iWidth)
            {
                int iRowCount = 0;
                float fZOffset = -1.0f * (iHeight / 2) * fPerRow;
                while (iRowCount < iHeight)
                {
                    eTileType type = (eTileType)TileData[iRowCount, iColCount];
                    float fTileHeight = GlobalDefines.fTileHeight;
                    Objects.Tile t;
                    if (iRowCount % 2 == 0)
                    {
                        t = CreateTile(new Vector3(fXOffset, fTileHeight, fZOffset), type);
                    }
                    else
                    {
                        t = CreateTile(new Vector3(fXOffset - 0.875f, fTileHeight, fZOffset), type);
                    }

                    Tiles[iRowCount, iColCount] = t;
                    if (type == eTileType.Base)
                    {
                        BaseTile = t;
                    }
                    else if (type == eTileType.EnemySpawn)
                    {
                        SpawnTile = t;
                    }
                    fZOffset += fPerRow;
                    iRowCount++;
                }

                fXOffset += fPerColumn;
                iColCount++;
            }

            // Now loop through the array of tiles to assign neighbors.
            // Since these are hexagons, the row affects which hexagons are neighbors.
            for (int i = 0; i < iHeight; i++)
            {
                for (int j = 0; j < iWidth; j++)
                {
                    // East/West are same regardless of row modulus
                    // E
                    if (j + 1 < iWidth)
                    {
                        Tiles[i, j].AddNeighbor(Tiles[i, j + 1]);
                    }
                    // W
                    if (j - 1 >= 0)
                    {
                        Tiles[i, j].AddNeighbor(Tiles[i, j - 1]);
                    }

                    if (i % 2 == 0)
                    {
                        // NE
                        if ((i - 1 >= 0) && (j + 1 < iWidth))
                        {
                            Tiles[i, j].AddNeighbor(Tiles[i - 1, j + 1]);
                        }
                        // SE
                        if ((i + 1 < iHeight) && (j + 1 < iWidth))
                        {
                            Tiles[i, j].AddNeighbor(Tiles[i + 1, j + 1]);
                        }
                        // SW
                        if (i + 1 < iHeight)
                        {
                            Tiles[i, j].AddNeighbor(Tiles[i + 1, j]);
                        }
                        // NW
                        if (i - 1 >= 0)
                        {
                            Tiles[i, j].AddNeighbor(Tiles[i - 1, j]);
                        }
                    }
                    else
                    {
                        // NE
                        if (i - 1 >= 0)
                        {
                            Tiles[i, j].AddNeighbor(Tiles[i - 1, j]);
                        }
                        // SE
                        if (i + 1 < iHeight)
                        {
                            Tiles[i, j].AddNeighbor(Tiles[i + 1, j]);
                        }
                        // SW
                        if ((i + 1 < iHeight) && (j - 1 >= 0))
                        {
                            Tiles[i, j].AddNeighbor(Tiles[i + 1, j - 1]);
                        }
                        // NW
                        if ((i - 1 >= 0) && (j - 1 >= 0))
                        {
                            Tiles[i, j].AddNeighbor(Tiles[i - 1, j - 1]);
                        }
                    }
                }
            }

            // These values let the camera know what the maximum scroll area should be.
            GameState.Get().Camera.LevelMin = Tiles[0, 0].Position;
            GameState.Get().Camera.LevelMax = Tiles[iHeight - 1, iWidth - 1].Position;

            // Create the player's base and initial path for enemies
            if (BaseTile != null && SpawnTile != null)
            {
                BaseTile.Build(new Objects.Base(m_Game));

                Pathfinder.Get().GlobalStartTile = SpawnTile;
                Pathfinder.Get().GlobalGoalTile = BaseTile;
                Pathfinder.Get().ComputeAStar();

                GameState.Get().SetSelected(BaseTile);
            }
        }
Пример #10
0
        // Helper function that creates the correct type of tile
        Objects.Tile CreateTile(Vector3 vPos, eTileType type = eTileType.Default)
        {
            Objects.Tile Tile = null;
            switch (type)
            {
                case (eTileType.Default):
                    Tile = new Objects.Tile(m_Game);
                    break;
                case (eTileType.Green):
                    Tile = new Objects.TileGreen(m_Game);
                    break;
                case (eTileType.Base):
                    Tile = new Objects.TileGreen(m_Game);
                    break;
                case (eTileType.Red):
                    Tile = new Objects.TileRed(m_Game);
                    break;
                case (eTileType.EnemySpawn):
                    Tile = new Objects.TileRed(m_Game);
                    break;
            }

            if (Tile != null)
            {
                Tile.Position = vPos;
                GameState.Get().SpawnGameObject(Tile);
                m_Tiles.AddLast(Tile);
            }

            return Tile;
        }
Пример #11
0
        // Computes the enemy path using A*
        // Returns true if there is a valid path, false if not.
        // If the optional parameter is NOT set, it sets the global path that all enemies use by default
        // otherwise, this function calculates the path only for the passed in Enemy.
        // This is to allow recalculation of paths for currently active Enemiess.
        public bool ComputeAStar(Objects.Enemy e = null)
        {
            // Clear out the open/closed set from previous paths
            m_OpenSet.Clear();
            m_ClosedSet.Clear();

            Objects.Tile StartTile = GlobalStartTile;
            // If we have a specific Enemy, the starting tile is the one the Enemy is currently at
            if (e != null)
            {
                StartTile = e.CurrentTile;
            }

            // We start at the goal node instead of the start node
            // so that the parent linked list does not need to be reversed once the A* is complete.
            PathNode node = new PathNode();

            node.tile = GlobalGoalTile;
            node.g    = 0.0f;
            node.h    = 0.0f;
            node.f    = 0.0f;

            // Initialize the A* algorithm
            PathNode CurrentNode = node;

            m_ClosedSet.Add(CurrentNode.tile, CurrentNode);

            do
            {
                // Loop through all the nodes adjacent to the current one
                foreach (Objects.Tile t in CurrentNode.tile.m_Neighbors)
                {
                    // Is this tile already in the closed set?
                    if (m_ClosedSet.ContainsKey(t))
                    {
                        // If so, skip.
                        continue;
                    }
                    else if (m_OpenSet.ContainsKey(t))
                    {
                        // Check if node adoption should occur
                        float test_g = CurrentNode.g + Vector3.Distance(t.Position, CurrentNode.tile.Position);

                        // Is the new g(x) value lower than the current one?
                        node = m_OpenSet[t];
                        if (test_g < node.g)
                        {
                            // If so, change parent
                            node.parent = CurrentNode;
                            node.g      = test_g;
                            node.f      = node.g + node.h;
                        }
                    }
                    // Tiles with a building are not passable, so should be ignored...
                    // UNLESS it's the start node, which can happen if this is a Enemy repositioning
                    else if (t.Tower == null || t == StartTile)
                    {
                        // Add a new PathNode to open set with CurrentNode as parent
                        node        = new PathNode();
                        node.parent = CurrentNode;
                        node.tile   = t;

                        // Calculate h(x) using Euclidean distance
                        node.h = Vector3.Distance(GlobalGoalTile.Position, t.Position);

                        // Calculate g(x)
                        node.g = node.parent.g + Vector3.Distance(t.Position, node.parent.tile.Position);

                        // f(x) =  g(x) + h(x)
                        node.f = node.g + node.h;

                        // Add to open set
                        m_OpenSet.Add(t, node);
                    }
                }

                // If the open set is empty, we failed to find a path
                if (m_OpenSet.Count == 0)
                {
                    break;
                }

                // Search the open set for lowest f(x) cost
                float lowest_f = 10000000000.0f;
                foreach (PathNode p in m_OpenSet.Values)
                {
                    if (p.f < lowest_f)
                    {
                        CurrentNode = p;
                        lowest_f    = p.f;
                    }
                }

                // Move CurrentNode to closed set
                m_OpenSet.Remove(CurrentNode.tile);
                m_ClosedSet.Add(CurrentNode.tile, CurrentNode);
            }while (CurrentNode.tile != StartTile);

            // Check to see if we found a path
            if (CurrentNode.tile == StartTile)
            {
                // Set the start of the path to the current node
                // If there is no Enemy, this is the new global path
                if (e == null)
                {
                    GlobalPath = CurrentNode;
                }
                else
                {
                    e.m_Path = CurrentNode;
                    e.ResetPath(true);
                }

                return(true);
            }
            else
            {
                // If there is no Enemy, this is the new global path
                if (e == null)
                {
                    GlobalPath = null;
                }
                else
                {
                    e.m_Path = null;
                    e.ResetPath(true);
                }
                return(false);
            }
        }
Пример #12
0
        public virtual void LoadLevel(string sLevelName)
        {
            m_Tiles.Clear();
            int iWidth  = 10;
            int iHeight = 5;

            int[,] TileData =
            {
                { 2, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                { 2, 2, 0, 0, 0, 0, 0, 0, 0, 0 },
                { 4, 0, 0, 0, 0, 0, 0, 0, 0, 3 },
                { 2, 2, 0, 0, 0, 0, 0, 0, 0, 0 },
                { 2, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
            };

            // Generate tile array based on width/height
            // (used to setup neighbors)
            Objects.Tile[,] Tiles = new Objects.Tile[iHeight, iWidth];

            float fPerColumn = 1.72f;
            float fPerRow    = 1.5f;

            Objects.Tile BaseTile  = null;
            Objects.Tile SpawnTile = null;

            int   iColCount = 0;
            float fXOffset  = -1.0f * (iWidth / 2) * fPerColumn;

            while (iColCount < iWidth)
            {
                int   iRowCount = 0;
                float fZOffset  = -1.0f * (iHeight / 2) * fPerRow;
                while (iRowCount < iHeight)
                {
                    eTileType    type        = (eTileType)TileData[iRowCount, iColCount];
                    float        fTileHeight = GlobalDefines.fTileHeight;
                    Objects.Tile t;
                    if (iRowCount % 2 == 0)
                    {
                        t = CreateTile(new Vector3(fXOffset, fTileHeight, fZOffset), type);
                    }
                    else
                    {
                        t = CreateTile(new Vector3(fXOffset - 0.875f, fTileHeight, fZOffset), type);
                    }

                    Tiles[iRowCount, iColCount] = t;
                    if (type == eTileType.Base)
                    {
                        BaseTile = t;
                    }
                    else if (type == eTileType.EnemySpawn)
                    {
                        SpawnTile = t;
                    }
                    fZOffset += fPerRow;
                    iRowCount++;
                }

                fXOffset += fPerColumn;
                iColCount++;
            }

            // Now loop through the array of tiles to assign neighbors.
            // Since these are hexagons, the row affects which hexagons are neighbors.
            for (int i = 0; i < iHeight; i++)
            {
                for (int j = 0; j < iWidth; j++)
                {
                    // East/West are same regardless of row modulus
                    // E
                    if (j + 1 < iWidth)
                    {
                        Tiles[i, j].AddNeighbor(Tiles[i, j + 1]);
                    }
                    // W
                    if (j - 1 >= 0)
                    {
                        Tiles[i, j].AddNeighbor(Tiles[i, j - 1]);
                    }

                    if (i % 2 == 0)
                    {
                        // NE
                        if ((i - 1 >= 0) && (j + 1 < iWidth))
                        {
                            Tiles[i, j].AddNeighbor(Tiles[i - 1, j + 1]);
                        }
                        // SE
                        if ((i + 1 < iHeight) && (j + 1 < iWidth))
                        {
                            Tiles[i, j].AddNeighbor(Tiles[i + 1, j + 1]);
                        }
                        // SW
                        if (i + 1 < iHeight)
                        {
                            Tiles[i, j].AddNeighbor(Tiles[i + 1, j]);
                        }
                        // NW
                        if (i - 1 >= 0)
                        {
                            Tiles[i, j].AddNeighbor(Tiles[i - 1, j]);
                        }
                    }
                    else
                    {
                        // NE
                        if (i - 1 >= 0)
                        {
                            Tiles[i, j].AddNeighbor(Tiles[i - 1, j]);
                        }
                        // SE
                        if (i + 1 < iHeight)
                        {
                            Tiles[i, j].AddNeighbor(Tiles[i + 1, j]);
                        }
                        // SW
                        if ((i + 1 < iHeight) && (j - 1 >= 0))
                        {
                            Tiles[i, j].AddNeighbor(Tiles[i + 1, j - 1]);
                        }
                        // NW
                        if ((i - 1 >= 0) && (j - 1 >= 0))
                        {
                            Tiles[i, j].AddNeighbor(Tiles[i - 1, j - 1]);
                        }
                    }
                }
            }

            // These values let the camera know what the maximum scroll area should be.
            GameState.Get().Camera.LevelMin = Tiles[0, 0].Position;
            GameState.Get().Camera.LevelMax = Tiles[iHeight - 1, iWidth - 1].Position;


            // Create the player's base and initial path for enemies
            if (BaseTile != null && SpawnTile != null)
            {
                BaseTile.Build(new Objects.Base(m_Game));

                Pathfinder.Get().GlobalStartTile = SpawnTile;
                Pathfinder.Get().GlobalGoalTile  = BaseTile;
                Pathfinder.Get().ComputeAStar();

                GameState.Get().SetSelected(BaseTile);
            }
        }