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(); } } } }
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; }
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); }
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; }
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 } } } }
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(); }