Пример #1
0
        public void Update(GameTime gameTime)
        {
            if (IsSpawning && !IsDoneSpawning)
            {
                RunnerSpawnDelayer.Update(gameTime);
                if (RunnerSpawnDelayer.IsDone)
                {
                    for (int i = 0; i < WaveRunners.Count; i++)
                    {
                        BaseRunner runner = WaveRunners[i].Runners.Last();
                        Level.Instance.ActiveRunners.Add(runner);
                        WaveRunners[i].Runners.Remove(runner);
                        runner.SetLocation(WaveRunners[i].startWP);

                        if (WaveRunners[i].Runners.Count == 0)
                        {
                            WaveRunners.RemoveAt(i);
                            i--;
                        }
                    }

                    if (WaveRunners.Count == 0)
                    {
                        IsDoneSpawning = true;
                    }
                    else
                    {
                        RunnerSpawnDelayer.Reset();
                    }
                }
            }
        }
Пример #2
0
 public static BaseRunner GetClosestRunner(Vector2 location, out float distance)
 {
     distance = float.MaxValue;
     BaseRunner result = null;
     foreach (BaseRunner r in Level.Instance.ActiveRunners)
     {
         if (result == null || distance > Vector2.Distance(result.FeetLoc, r.FeetLoc))
         {
             result = r;
             distance = Vector2.Distance(location, result.FeetLoc);
         }
     }
     return result;
 }
Пример #3
0
        BaseRunner GetNewTarget(bool onlyUnoccupiedTargets)
        {
            // Get all runners in range
            List <IEntity> runnersInRange = BroadPhase.Instance.GetAllEntitiesInRange(this, MeleeSightRange, e => e.EntityType == eEntityType.Runner);

            float      nearestRunnerNotTargetted = float.MaxValue;
            float      nearestRunnerTargetted    = float.MaxValue;
            BaseRunner target = null;
            bool       skipTargettedRunners = onlyUnoccupiedTargets;

            foreach (BaseRunner r in runnersInRange)
            {
                if (r.IsGround) // Ignore flying enemies.
                {
                    float distance = Vector2.Distance(FeetLoc, r.FeetLoc);
                    if (r.TargettedByDefenders.Count > 0) // Add targetted runner
                    {
                        if (!skipTargettedRunners && nearestRunnerTargetted > distance)
                        {
                            nearestRunnerTargetted = distance;
                            target = r;
                        }
                    }
                    else
                    {
                        if (nearestRunnerNotTargetted > distance) // add untargetted runner
                        {
                            nearestRunnerNotTargetted = distance;
                            target = r;
                            skipTargettedRunners = true;
                        }
                    }
                }
            }

            return(target);
        }
Пример #4
0
        public void Update(GameTime gameTime)
        {
            Animation.Update(gameTime);

            #region Move
            if (!IsFighting)
            {
                if (Target == null)
                {
                    #region MoveToWP
                    SetLocation(Animation.Location + MoveIncrement);
                    if (Vector2.Distance(FeetLoc, NextWP.Location + WPSpread) <= Velocity)
                    {
                        CurrentWP = NextWP;
                        if (CurrentWP.IsFinish)
                        {
                            ClearIncommings(); // Call before setting a new location to this runner.
                            Level.Instance.Player.Lives -= FinishDmg;
                            if (Recycles)
                                SetLocation(StartWP);
                        }
                        else
                        {
                            NextWP = CurrentWP.GetNextWP();
                            InitMoveToNextWP();
                        }
                    }
                    #endregion
                }
                else
                {
                    #region MoveToTargetIfNeeded
                    {
                        if (Vector2.Distance(FeetLoc, Target.FeetLoc) > 50)
                        {
                            Vector2 moveDir = Maths.GetMoveDir(FeetLoc, Target.FeetLoc);
                            Animation.Location += Velocity * moveDir;
                            Animation.SetDirectionByDir(moveDir);
                        }
                    }
                    #endregion
                }

                m_AABB.X = RelativeAABB.X + Animation.Location.Xi();
                m_AABB.Y = RelativeAABB.Y + Animation.Location.Yi();
            #endregion

                #region Attack
                #region if no target then attempt to set ranged target
                if (Target == null && HasRangedWeapon)
                {
                    Target = (ITargetable)BroadPhase.Instance.GetFirstEntityInRange(this, RangedWpnRange, e => e.EntityType == eEntityType.Defender);
                    if (Target != null)
                        IsFightingRanged = true;
                }
                #endregion

                if (Target != null)
                    Animation.SetDirection(FeetLoc, Target.FeetLoc);
            }
            else
            {
                if (Target == null)
                    Target = IsFightingWithDefenders[0];
                foreach (BaseWeapon wpn in Weapons)
                    wpn.Update(gameTime);
            }
                #endregion

            // Get the percentage from start-->finish based on the first startpoint from the global list.
            DistanceToFinish = Vector2.Distance(FeetLoc, NextWP.Location) + NextWP.ShortestRouteToFinishLength;
            DistanceTraveled = WayPoint.StartPoints[0].ShortestRouteToFinishLength - DistanceToFinish;
            PercentageToFinish = (DistanceTraveled / WayPoint.StartPoints[0].ShortestRouteToFinishLength) * 100;

            // Set this as the runner nearest to the finish if applicable
            if (RunnerNearestToFinish == null || RunnerNearestToFinish.PercentageToFinish < PercentageToFinish)
                RunnerNearestToFinish = this;
        }
Пример #5
0
        public void Update(GameTime gameTime)
        {
            if (IsSpawned)
            {
                if (IsAlive)
                {
                    // Update animation
                    Animation.Update(gameTime);

                    if (State == eState.Fighting)
                    {
                        #region Attempt to attack another unoccupied target when the current target has > 1 defender
                        if (((BaseRunner)Target).TargettedByDefenders.Count > 1)
                        {
                            BaseRunner newTarget = GetNewTarget(true);
                            if (newTarget != null)
                            {
                                Target = newTarget;
                                State  = eState.Running; // If the new target would be in range then the next cycle will set this state to fighting but if we don't set it to fighting the defender might not walk to the new enemy.
                            }
                        }
                        #endregion

                        #region Update weapons
                        foreach (BaseWeapon wpn in Weapons)
                        {
                            wpn.Update(gameTime);
                        }
                        #endregion
                    }
                    else
                    {
                        // Get new target if needed
                        if (Target == null)
                        {
                            Target = GetNewTarget(false);
                        }

                        if (Target != null)
                        {
                            float distanceToTarget = Vector2.Distance(FeetLoc, Target.FeetLoc);
                            if (distanceToTarget <= MeleeSightRange)
                            {
                                if (distanceToTarget > ShortestWeaponRange)
                                {
                                    #region Run to target
                                    SwitchAnimation(RunAni);
                                    Vector2 moveDir = Maths.GetMoveDir(FeetLoc, Target.FeetLoc);
                                    Animation.Location += moveDir * Velocity;
                                    Animation.SetDirectionByDir(moveDir);
                                    #endregion
                                }
                                else
                                {
                                    #region Start fighting
                                    State = eState.Fighting;
                                    SwitchAnimation(AtkAni);
                                    ((BaseRunner)Target).IsFightingWithDefenders.Add(this);
                                    #endregion
                                }
                            }
                            else // Runner walked out of sightrange. So release the target and walk back to the rallypoint if needed. (looking for a new target in range will occur next cycle).
                            {
                                WalkBackToNearRallyPoint();
                            }
                        }
                        else
                        {
                            WalkBackToNearRallyPoint();
                        }
                    }

                    m_AABB.X = RelativeAABB.X + Animation.Location.Xi();
                    m_AABB.Y = RelativeAABB.Y + Animation.Location.Yi();
                }
                else
                {
                    if (State == eState.Dying)
                    {
                        Animation.Update(gameTime);
                        if (DieAni.IsDisposed)
                        {
                            State = eState.Dead;
                            DieAni.Reset();
                        }
                    }
                    else
                    {
                        #region Not alive but spawned so respawn code goes here
                        RespawnTimer.Update(gameTime);
                        if (RespawnTimer.IsDone)
                        {
                            RespawnTimer.Reset();
                            Resurrect();
                        }
                        #endregion
                    }
                }
            }
        }
Пример #6
0
        public void Load(string xmlName)
        {
            // Resets
            SpawnedDeadDefenders  = new List <BaseDefender>(MAX_ACTIVE_DEFENDERS);
            SpawnedAliveDefenders = new List <BaseDefender>(MAX_ACTIVE_DEFENDERS);
            Towers                   = new List <BaseTower>(MAX_TOWERS);
            TowerBeneathMouse        = SelectedTower = null;
            NextWaveButton.IsEnabled = true;
            Player.ResetForNewLevel(10);
            WaveProgressBar.Percentage = 0;
            State        = eState.PreSpawn;
            Environments = new List <Environment>();

            XDocument doc = XDocument.Load("Data/Levels/" + xmlName + ".xml");

            #region Level Info
            XElement levelInfoNode = doc.Root.Element("LevelInfo");
            if (levelInfoNode == null)
            {
                throw new NullReferenceException("LevelInfo node not found. " + xmlName);
            }

            // Level display name
            LevelDisplayName = new StringBuilder(levelInfoNode.Element("Name").Value);
            // Start Gold
            Player.Gold = int.Parse(levelInfoNode.Element("StartGold").Value);
            // Level Size
            LevelSize = Common.Str2Point(levelInfoNode.Element("LevelSize").Value);
            if (LevelSize.X < 1280 || LevelSize.Y < 800)
            {
                throw new Exception("Level size must be at least 1280x800. Otherwise there would be a black border around the level plus the camera can not stay in such a small boundary.");
            }

            // Broadphase
            BroadPhase.Instance = new BroadPhase(int.Parse(levelInfoNode.Element("CollisionGridSize").Value), LevelSize);
            BroadPhase.Instance.Init();
            #endregion

            #region Load Waypoints
            XElement wpMainNode = doc.Root.Element("Waypoints");
            if (wpMainNode == null)
            {
                throw new NullReferenceException("Waypoints node missing. " + xmlName);
            }

            WayPoint.Spread = int.Parse(wpMainNode.Attribute("spread").Value);

            WayPoint.StartPoints = new List <WayPoint>();
            foreach (XElement wp in wpMainNode.Elements())
            {
                List <int> nextWpIds   = new List <int>();
                XElement   nextWPsNode = wp.Element("NextWaypoints");
                if (nextWPsNode != null)
                {
                    foreach (XElement nextwpID in nextWPsNode.Elements())
                    {
                        nextWpIds.Add(int.Parse(nextwpID.Value));
                    }
                }

                // Start & Finish
                bool isStart = false;
                if (wp.Attribute("isStart") != null)
                {
                    isStart = bool.Parse(wp.Attribute("isStart").Value);
                }
                bool isFinish = false;
                if (wp.Attribute("isFinish") != null)
                {
                    isFinish = bool.Parse(wp.Attribute("isFinish").Value);
                }

                WayPoints.Add(new WayPoint(int.Parse(wp.Attribute("id").Value), Common.Str2Vector(wp.Attribute("location").Value), isStart, isFinish, nextWpIds.ToArray()));
            }

            WayPoints.ForEach(w => w.Initialize());
            WayPoint.CalculateTotalRoutelength();
            #endregion

            // Waves after waypoints.
            CurrentWaveNr = 0;
            #region Waves
            Waves = new List <Wave>();

            XElement wavesmainNode = doc.Root.Element("Waves");
            if (wavesmainNode == null)
            {
                throw new NullReferenceException("Node Waves missing." + xmlName);
            }

            foreach (XElement waveNode in wavesmainNode.Elements())
            {
                Wave newWave = new Wave(int.Parse(waveNode.Attribute("nr").Value), int.Parse(waveNode.Attribute("spawnDelay").Value));
                newWave.TimeUntilNextWaveInMS = int.Parse(waveNode.Attribute("timeUntilNextWave").Value);

                foreach (XElement startWPNode in waveNode.Elements())
                {
                    List <BaseRunner> runners = new List <BaseRunner>();
                    int startWPID             = int.Parse(startWPNode.Attribute("id").Value);
                    foreach (XElement runnerNode in startWPNode.Elements())
                    {
                        int runnerID = int.Parse(runnerNode.Attribute("id").Value);
                        int amount   = int.Parse(runnerNode.Attribute("amount").Value);

                        for (int i = 0; i < amount; i++)
                        {
                            BaseRunner newRunner = new BaseRunner();
                            newRunner.Initialize(runnerID);
                            newRunner.SetLocation(WayPoints.Find(w => w.ID == startWPID));
                            runners.Add(newRunner);
                        }
                    }
                    newWave.WaveRunners.Add(new WaveSpawnHelper(startWPID, runners.ToArray()));
                }
                Waves.Add(newWave);
            }
            TotalWaves = Waves.Count;
            #endregion

            #region BuildGrid
            BuildGrid = new BuildGrid();
            XElement unBuildablesNode = doc.Root.Element("UnBuildables");
            if (unBuildablesNode != null)
            {
                BuildGrid.SetUnBuildables(unBuildablesNode.Value);
            }
            #endregion

            #region BackGround (before minimap region)
            BGMgr = new BGMgr();
            XElement bgMainNode = doc.Root.Element("BackGround");
            if (bgMainNode != null)
            {
                BGMgr.Load(bgMainNode);
            }
            #endregion

            #region MiniMap
            MiniMap = new MiniMap(new Vector2(0, Engine.Instance.Height - MiniMap.Size.Y), LevelSize);
            MiniMap.PreRender();
            #endregion

            #region Initial towers
            XElement initialTowersMainNode = doc.Root.Element("InitialTowers");
            if (initialTowersMainNode != null)
            {
                foreach (XElement initialTowerNode in initialTowersMainNode.Elements())
                {
                    BaseTower bt = new BaseTower();
                    bt.Initialize(int.Parse(initialTowerNode.Element("ID").Value));
                    bt.SetLocation(Common.Str2Vector(initialTowerNode.Element("GridIdx").Value) * BuildGrid.GRID_SIZE);
                    AddTower(bt);
                }
            }
            #endregion

            #region Buildable Towers
            BuildableTowers = new List <int>();
            XElement buildableTowersMainNode = doc.Root.Element("BuildableTowers");
            if (BuildableTowers != null)
            {
                if (buildableTowersMainNode.Attribute("type").Value == "restricted")
                {
                    // Add all towers
                    for (int i = 0; i < DataStructs.Towers.Count; i++)
                    {
                        BuildableTowers.Add(DataStructs.Towers[i].ID);
                    }

                    // Remove restricted towers
                    foreach (XElement restrictedTowerNode in buildableTowersMainNode.Elements())
                    {
                        BuildableTowers.Remove(int.Parse(restrictedTowerNode.Value));
                    }
                }
                else
                {
                    // Add allowed towers
                    foreach (XElement restrictedTowerNode in buildableTowersMainNode.Elements())
                    {
                        BuildableTowers.Add(int.Parse(restrictedTowerNode.Value));
                    }
                }
            }
            else
            {
                // Add all towers
                for (int i = 0; i < DataStructs.Towers.Count; i++)
                {
                    BuildableTowers.Add(DataStructs.Towers[i].ID);
                }
            }
            #endregion

            #region Perma Disable CategoryButtons when they have no towers at all (place this code after region: Buildable Towers)
            foreach (Button btn in CategoryButtons)
            {
                TowerCategoryStruct tcs = (TowerCategoryStruct)btn.Tag;
                bool hasNoTowers        = true;
                for (int i = 0; i < tcs.TowersInThisCat.Count; i++)
                {
                    if (BuildableTowers.Contains(tcs.TowersInThisCat[i].ID))
                    {
                        hasNoTowers = false;
                        break;
                    }
                }
                btn.Tag2 = hasNoTowers;
                btn.IsEntirelyDisabled = hasNoTowers;
            }
            #endregion

            #region Environments
            XElement environmentMainNode = doc.Root.Element("Environments");
            if (environmentMainNode != null)
            {
                foreach (XElement environmentNode in environmentMainNode.Elements())
                {
                    Environments.Add(new Environment((eAnimation)Enum.Parse(typeof(eAnimation), environmentNode.Element("Type").Value), Common.Str2Vector(environmentNode.Element("Location").Value)));
                }
            }
            #endregion

            // GC
            GC.Collect();
        }