From 04695db47c684b96a657d3af5bdd800aa695a154 Mon Sep 17 00:00:00 2001 From: Bahil Botond <dxwbw9@inf.elte.hu> Date: Sat, 7 May 2022 16:52:06 +0200 Subject: [PATCH] Documenting Logic.Data --- Assets/Scripts/Logic/Data/World/Barrack.cs | 56 +++++++++++++- Assets/Scripts/Logic/Data/World/Castle.cs | 19 +++++ Assets/Scripts/Logic/Data/World/GameWorld.cs | 62 ++++++++++++++++ .../Logic/Data/World/IGameWorldConfig.cs | 30 ++++++++ .../Logic/Data/World/ITowerTypeData.cs | 32 +++++++- .../Scripts/Logic/Data/World/IUnitTypeData.cs | 20 ++++- Assets/Scripts/Logic/Data/World/TileObject.cs | 13 +++- .../Scripts/Logic/Data/World/TilePosition.cs | 50 +++++++++++++ Assets/Scripts/Logic/Data/World/Tower.cs | 34 +++++++++ Assets/Scripts/Logic/Data/World/Unit.cs | 50 ++++++++++++- Assets/Scripts/Logic/Data/World/Vector2.cs | 74 +++++++++++++++++++ 11 files changed, 431 insertions(+), 9 deletions(-) diff --git a/Assets/Scripts/Logic/Data/World/Barrack.cs b/Assets/Scripts/Logic/Data/World/Barrack.cs index 713f600..65b1c63 100644 --- a/Assets/Scripts/Logic/Data/World/Barrack.cs +++ b/Assets/Scripts/Logic/Data/World/Barrack.cs @@ -16,30 +16,61 @@ public class Barrack : Building { #region Properties + /// <summary> + /// The checkpoints for the units that spawn from this barrack. + /// </summary> public IReadOnlyCollection<TilePosition> CheckPoints => new List<TilePosition>(_checkPoints); + /// <summary> + /// The time remaining until the barrack can spawn a unit. + /// </summary> public float RemainingCooldownTime { get; private set; } + /// <summary> + ///Returns false if the barrack cooled down and can spawn a unit. + /// </summary> public bool IsOnCooldown => RemainingCooldownTime > 0; + /// <summary> + /// List of units that will be spawned from this barrack. + /// </summary> public IReadOnlyCollection<IUnitTypeData> QueuedUnits => new List<IUnitTypeData>(_queuedUnits); - public int Ordinal { get; } + /// <summary> + /// A unique number for each barrack from the same team. + /// </summary> + public int Ordinal { get; } #endregion #region Methods + /// <summary> + /// Creates a new barrack. + /// </summary> + /// <param name="world">The <see cref="GameWorld"/> in which the barrack will be created.</param> + /// <param name="position">The <see cref="TilePosition"/> of the barrack.</param> + /// <param name="owner">The <see cref="Color"/> of the barrack owner's team.</param> + /// <param name="ordinal">A unique number for each barrack from the same team.</param> internal Barrack(GameWorld world, TilePosition position, Color owner, int ordinal) : base(world, position, owner) { - Ordinal = ordinal; + Ordinal = ordinal; } + /// <summary> + /// Adds a unit's type data to the end of the barrack's spawn queue. These units will be spawned in Fight phase. + /// </summary> + /// <param name="type">The type of the unit.</param> internal void QueueUnit(IUnitTypeData type) { _queuedUnits.Add(type); World.Overview.Events.Raise(new UnitQueuedEvent(type, this)); } + /// <summary> + /// Puts a new checkpoint to the end of the checkpoints. + /// </summary> + /// <param name="tile">The position of the new checkpoint.</param> + /// <exception cref="ArgumentException">If the checkpoint is already in the list.</exception> internal void PushCheckPoint(TilePosition tile) { if (_checkPoints.Contains(tile)) { throw new ArgumentException("Position is already a checkpoint"); @@ -49,6 +80,11 @@ public class Barrack : Building { World.Overview.Events.Raise(new BarrackCheckpointCreatedEvent(this, tile)); } + /// <summary> + /// Removes a checkpoint from the checkpoints. + /// </summary> + /// <param name="tile">The position of the checkpoint.</param> + /// <exception cref="ArgumentException">If the position is not a checkpoint.</exception> internal void DeleteCheckPoint(TilePosition tile) { if (!_checkPoints.Remove(tile)) { throw new ArgumentException("Position is not a checkpoint"); @@ -57,6 +93,10 @@ public class Barrack : Building { World.Overview.Events.Raise(new BarrackCheckpointRemovedEvent(this, tile)); } + /// <summary> + /// Updates the remaining cooldown time as time passes. + /// </summary> + /// <param name="delta">The amount of time passed.</param> internal void UpdateCooldown(float delta) { RemainingCooldownTime -= delta; if (RemainingCooldownTime < 0) { @@ -64,10 +104,17 @@ public class Barrack : Building { } } + /// <summary> + /// Sets the remaining cooldown time for the start of a new round. + /// </summary> internal void ResetCooldown() { - RemainingCooldownTime = Ordinal * World.Config.BarrackSpawnTimeOffset; + RemainingCooldownTime = Ordinal * World.Config.BarrackSpawnTimeOffset; } + /// <summary> + /// Spawns the next queued unit. + /// </summary> + /// <exception cref="InvalidOperationException">If there are no units queued or the barrack is on cooldown.</exception> internal void Spawn() { if (!QueuedUnits.Any()) throw new InvalidOperationException("No queued units exist; nothing to spawn"); @@ -79,6 +126,9 @@ public class Barrack : Building { World.DeployUnit(this, type); } + /// <summary> + /// Removes checkpoints from the list that became unreachable due to new buildings. + /// </summary> internal void DeleteUnreachableCheckpoints() { HashSet<TilePosition> oldCheckpoints = new HashSet<TilePosition>(_checkPoints); oldCheckpoints.RemoveWhere(pos => World[pos] != null); diff --git a/Assets/Scripts/Logic/Data/World/Castle.cs b/Assets/Scripts/Logic/Data/World/Castle.cs index ffd01ec..3582098 100644 --- a/Assets/Scripts/Logic/Data/World/Castle.cs +++ b/Assets/Scripts/Logic/Data/World/Castle.cs @@ -5,19 +5,38 @@ namespace Logic.Data.World { public class Castle : Building { #region Properties + /// <summary> + /// Remaining health of the castle. + /// </summary> public float Health { get; private set; } + /// <summary> + /// Returns true if the castle is destroyed. + /// </summary> public bool IsDestroyed => Health <= 0; #endregion #region Methods + /// <summary> + /// Creates a new castle. + /// </summary> + /// <param name="world">The <see cref="GameWorld"/> in which the castle will be created.</param> + /// <param name="position">The <see cref="TilePosition"/> of the castle.</param> + /// <param name="owner">The <see cref="Color"/> of the castle owner's team.</param> internal Castle(GameWorld world, TilePosition position, Color owner) : base(world, position, owner) { Health = world.Config.CastleStartingHealth; } + /// <summary> + /// Damages the castle. Raises an event if the castle gets destroyed. + /// </summary> + /// <param name="attacker">The unit that attacked the castle.</param> + /// <param name="damage">The amount of damage inflicted.</param> + /// <exception cref="ArgumentException">If the damage was negative.</exception> + /// <exception cref="InvalidOperationException">If the castle is already destroyed.</exception> internal void Damage(Unit attacker, float damage) { if (damage < 0) throw new ArgumentException("Damage must not be negative"); if (IsDestroyed) throw new InvalidOperationException("Castle is already destroyed"); diff --git a/Assets/Scripts/Logic/Data/World/GameWorld.cs b/Assets/Scripts/Logic/Data/World/GameWorld.cs index f32bcb5..5c83b46 100644 --- a/Assets/Scripts/Logic/Data/World/GameWorld.cs +++ b/Assets/Scripts/Logic/Data/World/GameWorld.cs @@ -16,16 +16,37 @@ public class GameWorld { #region Properties + /// <summary> + /// The overview of the game. + /// </summary> public IGameOverview Overview { get; } + /// <summary> + /// The width of the world. + /// </summary> public int Width => Config.Width; + /// <summary> + /// The height of the world. + /// </summary> public int Height => Config.Height; + /// <summary> + /// The object at the given coordinates. + /// </summary> + /// <param name="x">The first coordinate.</param> + /// <param name="y">The second coordinate.</param> public TileObject this[int x, int y] => GetTile(x, y); + /// <summary> + /// The object at the given TilePosition. + /// </summary> + /// <param name="position">The TilePosition</param> public TileObject this[TilePosition position] => GetTile(position.X, position.Y); + /// <summary> + /// All the TileObjects in the game. + /// </summary> public IEnumerable<TileObject> TileObjects { get { for (int x = 0; x < Width; x++) @@ -35,16 +56,30 @@ public class GameWorld { } } + /// <summary> + /// The navigation system of the world. + /// </summary> internal WorldNavigation Navigation { get; } + /// <summary> + /// All the units alive in the world. + /// </summary> public IReadOnlyCollection<Unit> Units => new List<Unit>(_units); + /// <summary> + /// The configurations of the world. + /// </summary> public IGameWorldConfig Config { get; } #endregion #region Methods + /// <summary> + /// Creates a new world. Generates the obstacles, the castles and the barracks. + /// </summary> + /// <param name="overview">The overview of the world.</param> + /// <param name="config">The configurations of the world.</param> internal GameWorld(IGameOverview overview, IGameWorldConfig config) { Overview = overview; Config = config; @@ -53,14 +88,26 @@ public class GameWorld { Navigation = new WorldNavigation(_grid); } + /// <param name="x">The first coordinate.</param> + /// <param name="y">The second coordinate.</param> + /// <returns>Returns the object at the given coordinates.</returns> public TileObject GetTile(int x, int y) { return _grid[x, y]; } + /// <typeparam name="T">the type of the TileObjects.</typeparam> + /// <returns>Returns all the TileObjects of the given type. </returns> public IEnumerable<T> GetTileObjectsOfType<T>() where T : TileObject { return TileObjects.Where(o => o is T).Cast<T>(); } + /// <summary> + /// Builds a tower. + /// </summary> + /// <param name="team">The team of the tower.</param> + /// <param name="type">The type of the tower.</param> + /// <param name="position">The position of the tower.</param> + /// <exception cref="ArgumentException">If the position is already occupied.</exception> internal void BuildTower(GameTeam team, ITowerTypeData type, TilePosition position) { if (_grid[position.X, position.Y] != null) throw new ArgumentException($"Position {position} is already occupied"); @@ -70,6 +117,11 @@ public class GameWorld { Overview.Events.Raise(new TowerBuiltEvent(tower)); } + /// <summary> + /// Destroys a tower. + /// </summary> + /// <param name="tower">The tower to destroy.</param> + /// <exception cref="ArgumentException">If the Object on the grid at the tower's position isn't the tower.</exception> internal void DestroyTower(Tower tower) { if (_grid[tower.Position.X, tower.Position.Y] != tower) throw new ArgumentException("Tower is not at the position it says it is"); @@ -78,6 +130,11 @@ public class GameWorld { Overview.Events.Raise(new TowerDestroyedEvent(tower)); } + /// <summary> + /// Deploys a unit. + /// </summary> + /// <param name="barrack">The barrack from which the unit will be deployed.</param> + /// <param name="type">The type of the unit.</param> internal void DeployUnit(Barrack barrack, IUnitTypeData type) { Vector2 position = barrack.Position.ToVectorCentered(); Unit unit = new Unit(type, barrack.Owner, this, position, barrack.CheckPoints); @@ -85,6 +142,11 @@ public class GameWorld { Overview.Events.Raise(new UnitDeployedEvent(unit, barrack)); } + /// <summary> + /// Destroys a unit. + /// </summary> + /// <param name="unit">The unit to be destroyed.</param> + /// <exception cref="ArgumentException">If the world doesn't have the unit.</exception> internal void DestroyUnit(Unit unit) { if (!_units.Contains(unit)) throw new ArgumentException("Unit is not among this world's units"); diff --git a/Assets/Scripts/Logic/Data/World/IGameWorldConfig.cs b/Assets/Scripts/Logic/Data/World/IGameWorldConfig.cs index 10cf551..f39760c 100644 --- a/Assets/Scripts/Logic/Data/World/IGameWorldConfig.cs +++ b/Assets/Scripts/Logic/Data/World/IGameWorldConfig.cs @@ -1,11 +1,41 @@ ďťżnamespace Logic.Data.World { +/// <summary> +/// Container of configuration entries related to the <see cref="GameWorld"/> class. +/// </summary> public interface IGameWorldConfig { + /// <summary> + /// The width of the world. + /// </summary> public int Width { get; } + + /// <summary> + /// The height of the world. + /// </summary> public int Height { get; } + + /// <summary> + /// The cooldown time of the barracks between two spawning. + /// </summary> public float BarrackSpawnCooldownTime { get; } + + /// <summary> + /// The starting health of the castles. + /// </summary> public float CastleStartingHealth { get; } + + /// <summary> + /// The maximum distance a tower can be built from the team's buildings. + /// </summary> public int MaxBuildingDistance { get; } + + /// <summary> + /// True if obstacles will be generated into the world. + /// </summary> public bool GenerateObstacles { get; } + + /// <summary> + /// Base offset of the barracks' spawning. + /// </summary> public float BarrackSpawnTimeOffset { get; } } } diff --git a/Assets/Scripts/Logic/Data/World/ITowerTypeData.cs b/Assets/Scripts/Logic/Data/World/ITowerTypeData.cs index d48ccde..66f5ce6 100644 --- a/Assets/Scripts/Logic/Data/World/ITowerTypeData.cs +++ b/Assets/Scripts/Logic/Data/World/ITowerTypeData.cs @@ -1,15 +1,45 @@ ďťżnamespace Logic.Data.World { public interface ITowerTypeData { - #region Properties + /// <summary> + /// Name of the tower type. + /// </summary> public string Name { get; } + + /// <summary> + /// Damage of the tower type. + /// </summary> public float Damage { get; } + + /// <summary> + /// Range of the tower type. + /// </summary> public float Range { get; } + + /// <summary> + /// Cooldown time of the tower type between two shots. + /// </summary> public float CooldownTime { get; } + + /// <summary> + /// Building cost of the tower type. + /// </summary> public int BuildingCost { get; } + + /// <summary> + /// Amount of money refunded after destroying this type of tower. + /// </summary> public int DestroyRefund { get; } + + /// <summary> + /// Building cost of the tower type. + /// </summary> public int UpgradeCost { get; } + + /// <summary> + /// Type of the new tower after upgrade. + /// </summary> public ITowerTypeData AfterUpgradeType { get; } #endregion diff --git a/Assets/Scripts/Logic/Data/World/IUnitTypeData.cs b/Assets/Scripts/Logic/Data/World/IUnitTypeData.cs index b85669c..ad997e8 100644 --- a/Assets/Scripts/Logic/Data/World/IUnitTypeData.cs +++ b/Assets/Scripts/Logic/Data/World/IUnitTypeData.cs @@ -1,12 +1,30 @@ ďťżnamespace Logic.Data.World { public interface IUnitTypeData { - #region Properties + /// <summary> + /// Name of the unit type; + /// </summary> public string Name { get; } + + /// <summary> + /// Health of the unit type; + /// </summary> public float Health { get; } + + /// <summary> + /// Damage of the unit type; + /// </summary> public float Damage { get; } + + /// <summary> + /// Speed of the unit type; + /// </summary> public float Speed { get; } + + /// <summary> + /// Cost of the unit type; + /// </summary> public int Cost { get; } #endregion diff --git a/Assets/Scripts/Logic/Data/World/TileObject.cs b/Assets/Scripts/Logic/Data/World/TileObject.cs index 5b36c88..ba3705e 100644 --- a/Assets/Scripts/Logic/Data/World/TileObject.cs +++ b/Assets/Scripts/Logic/Data/World/TileObject.cs @@ -1,7 +1,13 @@ ďťżnamespace Logic.Data.World { - public abstract class TileObject { + /// <summary> + /// The world in which the TileObject is located. + /// </summary> public GameWorld World { get; } + + /// <summary> + /// The position of the TileObject. + /// </summary> public TilePosition Position { get; } private protected TileObject(GameWorld world, TilePosition position) { @@ -9,9 +15,12 @@ public abstract class TileObject { Position = position; } + /// <summary> + /// Formats the object for printing on screen. + /// </summary> + /// <returns>Printable format of the TileObject.</returns> public override string ToString() { return $"{GetType().Name}@{Position}"; } } - } diff --git a/Assets/Scripts/Logic/Data/World/TilePosition.cs b/Assets/Scripts/Logic/Data/World/TilePosition.cs index fcc6e84..6e6077c 100644 --- a/Assets/Scripts/Logic/Data/World/TilePosition.cs +++ b/Assets/Scripts/Logic/Data/World/TilePosition.cs @@ -2,7 +2,14 @@ namespace Logic.Data.World { public readonly struct TilePosition { + /// <summary> + /// First coordinate of the position. + /// </summary> public int X { get; } + + /// <summary> + /// Second coordinate of the position. + /// </summary> public int Y { get; } public TilePosition(int x, int y) { @@ -10,42 +17,85 @@ public readonly struct TilePosition { Y = y; } + /// <returns>A <see cref="Vector2"/>pointing at the bottom-left edge of the tile.</returns> public Vector2 ToVectorLower() { return new Vector2(X, Y); } + /// <returns>A <see cref="Vector2"/>pointing at the middle of the tile.</returns> public Vector2 ToVectorCentered() { return new Vector2(X + 0.5f, Y + 0.5f); } + /// <summary> + /// Calculates the manhattan-distance between two TilePositions. + /// </summary> + /// <param name="from">The other TilePosition.</param> + /// <returns>The manhattan distance between the two TilePositions.</returns> public int FirstNormDistance(TilePosition from) { return Math.Abs(X - from.X) + Math.Abs(Y - from.Y); } + /// <summary> + /// Calculates the squared "real" distance between two TilePositions. + /// </summary> + /// <param name="from">The other TilePosition.</param> + /// <returns>The squared "real" distance between the two TilePositions.</returns> public int Distance2(TilePosition from) { return (X - from.X) * (X - from.X) + (Y - from.Y) * (Y - from.Y); } + /// <summary> + /// Calculates the "real" distance between two TilePositions. + /// </summary> + /// <param name="from">The other TilePosition.</param> + /// <returns>The "real" distance between the two TilePositions.</returns> public float Distance(TilePosition from) { return (float) Math.Sqrt(Distance2(from)); } + /// <summary> + /// Makes a new TilePosition by adding two positions. + /// </summary> + /// <param name="other">The other position.</param> + /// <returns>The new TilePosition.</returns> public TilePosition Added(TilePosition other) { return Added(other.X, other.Y); } + /// <summary> + /// Makes a new TilePosition by adding two positions. + /// </summary> + /// <param name="x">The other position's first coordinate.</param> + /// <param name="y">The other position's second coordinate.</param> + /// <returns>The new TilePosition.</returns> public TilePosition Added(int x, int y) { return new TilePosition(X + x, Y + y); } + /// <summary> + /// Makes a new TilePosition by subtracting two positions. + /// </summary> + /// <param name="other">The other position.</param> + /// <returns>The new TilePosition.</returns> public TilePosition Subtracted(TilePosition other) { return Subtracted(other.X, other.Y); } + /// <summary> + /// Makes a new TilePosition by subtracting two positions. + /// </summary> + /// <param name="x">The other position's first coordinate.</param> + /// <param name="y">The other position's second coordinate.</param> + /// <returns>The new TilePosition.</returns> public TilePosition Subtracted(int x, int y) { return Added(-x, -y); } + /// <summary> + /// Formats the TilePosition for printing on screen. + /// </summary> + /// <returns>Printable format of the TilePosition.</returns> public override string ToString() { return $"({X};{Y})"; } diff --git a/Assets/Scripts/Logic/Data/World/Tower.cs b/Assets/Scripts/Logic/Data/World/Tower.cs index 31394d3..31fe3fb 100644 --- a/Assets/Scripts/Logic/Data/World/Tower.cs +++ b/Assets/Scripts/Logic/Data/World/Tower.cs @@ -13,6 +13,9 @@ public class Tower : Building { /// </summary> public Unit Target { get; private set; } + /// <summary> + /// The closest enemy unit to the tower. + /// </summary> public Unit ClosestEnemy { get { Unit closest = null; @@ -31,19 +34,36 @@ public class Tower : Building { } } + /// <summary> + /// Remaining cooldown time until the tower can shoot again. + /// </summary> public float RemainingCooldownTime { get; private set; } + /// <summary> + /// False if cooldown is over. + /// </summary> public bool IsOnCooldown => RemainingCooldownTime > 0; #endregion #region Methods + /// <summary> + /// Creates a tower. + /// </summary> + /// <param name="world">The <see cref="GameWorld"/> in which the tower will be created.</param> + /// <param name="position">The <see cref="TilePosition"/> of the tower.</param> + /// <param name="owner">The <see cref="Color"/> of the tower owner's team.</param> + /// <param name="type">The <see cref="ITowerTypeData"/> of the tower.</param> internal Tower(GameWorld world, TilePosition position, Color owner, ITowerTypeData type) : base(world, position, owner) { Type = type; } + /// <summary> + /// Upgrades the tower to the next level. + /// </summary> + /// <exception cref="InvalidOperationException">If the tower is not upgradable.</exception> internal void Upgrade() { if (Type.AfterUpgradeType == null) throw new InvalidOperationException($"{Type} is not upgradeable"); ITowerTypeData oldType = Type; @@ -51,6 +71,9 @@ public class Tower : Building { World.Overview.Events.Raise(new TowerUpgradedEvent(this, oldType)); } + /// <summary> + /// Finds a new target if the current target died or moved out of range. + /// </summary> internal void UpdateTarget() { if (Target != null && Position.ToVectorCentered().Distance(Target.Position) <= Type.Range && Target.IsAlive) @@ -66,16 +89,27 @@ public class Tower : Building { if (Target != oldTarget) World.Overview.Events.Raise(new TowerTargetChangedEvent(this, oldTarget)); } + /// <summary> + /// Updates the remaining cooldown time as time passes. + /// </summary> + /// <param name="delta">The amount of time passed.</param> internal void UpdateCooldown(float delta) { if (RemainingCooldownTime == 0) return; RemainingCooldownTime = Math.Max(RemainingCooldownTime - delta, 0); if (!IsOnCooldown) World.Overview.Events.Raise(new TowerCooledDownEvent(this)); } + /// <summary> + /// Sets the remaining cooldown time for the start of a new round. + /// </summary> internal void ResetCooldown() { RemainingCooldownTime = 0; } + /// <summary> + /// The tower at the target. + /// </summary> + /// <exception cref="InvalidOperationException">If the tower has no targets or is on cooldown.</exception> internal void Shoot() { if (Target == null) throw new InvalidOperationException("No target in tower range"); if (IsOnCooldown) throw new InvalidOperationException($"Shooting is on cooldown: {RemainingCooldownTime}"); diff --git a/Assets/Scripts/Logic/Data/World/Unit.cs b/Assets/Scripts/Logic/Data/World/Unit.cs index b9424df..dc52fe7 100644 --- a/Assets/Scripts/Logic/Data/World/Unit.cs +++ b/Assets/Scripts/Logic/Data/World/Unit.cs @@ -3,7 +3,6 @@ using System.Linq; using Logic.Event.World.Unit; namespace Logic.Data.World { - public class Unit { #region Fields @@ -15,26 +14,58 @@ public class Unit { #region Properties + /// <summary> + /// Team of the unit. + /// </summary> public GameTeam Owner { get; } + /// <summary> + /// Remaining health of the unit. + /// </summary> public float CurrentHealth { get; private set; } + /// <summary> + /// Next destination of the unit. + /// </summary> public TilePosition NextCheckpoint => _checkPoints[0]; + /// <summary> + /// The world in which the unit exists. + /// </summary> public GameWorld World { get; } + /// <summary> + /// The position of the unit. + /// </summary> public Vector2 Position { get; private set; } + /// <summary> + /// The Tile on which the unit is. + /// </summary> public TilePosition TilePosition => Position.ToTilePosition(); + /// <summary> + /// The type of the unit. + /// </summary> public IUnitTypeData Type { get; } + /// <summary> + /// True if the unit is alive. + /// </summary> public bool IsAlive => CurrentHealth > 0; #endregion #region Methods + /// <summary> + /// Creates a unit. + /// </summary> + /// <param name="type">Type of the unit.</param> + /// <param name="owner">Team of the unit.</param> + /// <param name="world">World in which the unit will be created.</param> + /// <param name="position">Spawn position of the unit.</param> + /// <param name="checkpoints">The list of checkpoints the unit will try to go through.</param> internal Unit(IUnitTypeData type, GameTeam owner, GameWorld world, Vector2 position, IEnumerable<TilePosition> checkpoints) { Type = type; @@ -46,6 +77,10 @@ public class Unit { _checkPoints.Add(Owner.Overview.GetEnemyTeam(Owner).Castle.Position); } + /// <summary> + /// Moves the unit as time passes. + /// </summary> + /// <param name="delta">The amount of time passed.</param> internal void Move(float delta) { TilePosition oldPosition = TilePosition; @@ -84,6 +119,9 @@ public class Unit { return true; //Checkpoint reached } + /// <summary> + /// Updates the planned path of a unit. + /// </summary> internal void UpdatePlannedPath() { _cachedCheckpointPath = null; @@ -100,6 +138,11 @@ public class Unit { } } + /// <summary> + /// Damages the unit. + /// </summary> + /// <param name="attacker">The tower that attacked the unit.</param> + /// <param name="damage">The amount of damage inflicted.</param> internal void InflictDamage(Tower attacker, float damage) { if (damage >= CurrentHealth) { damage = CurrentHealth; @@ -107,9 +150,13 @@ public class Unit { } else { CurrentHealth -= damage; } + World.Overview.Events.Raise(new UnitDamagedEvent(this, damage, attacker)); } + /// <summary> + /// Kills unit without it taking damage and raising an event. + /// </summary> internal void DestroyWithoutDamage() { CurrentHealth = 0; } @@ -126,5 +173,4 @@ public class Unit { } } } - } diff --git a/Assets/Scripts/Logic/Data/World/Vector2.cs b/Assets/Scripts/Logic/Data/World/Vector2.cs index f67f170..7b6680f 100644 --- a/Assets/Scripts/Logic/Data/World/Vector2.cs +++ b/Assets/Scripts/Logic/Data/World/Vector2.cs @@ -2,61 +2,135 @@ namespace Logic.Data.World { public readonly struct Vector2 { + /// <summary> + /// First coordinate of the vector. + /// </summary> public float X { get; } + + /// <summary> + /// Second coordinate of the vector. + /// </summary> public float Y { get; } + /// <summary> + /// Squared length of the vector. + /// </summary> public float Length2 => X * X + Y * Y; + + /// <summary> + /// Length of the vector; + /// </summary> public float Length => (float) Math.Sqrt(Length2); + /// <summary> + /// Creates a new Vector. + /// </summary> + /// <param name="x">First coordinate of the vector.</param> + /// <param name="y">Second coordinate of the vector.</param> public Vector2(float x, float y) { X = x; Y = y; } + /// <returns>The TilePosition on which the Vector2 is.</returns> public TilePosition ToTilePosition() { return new TilePosition((int) Math.Floor(X), (int) Math.Floor(Y)); } + /// <summary> + /// Calculates the squared distance of two Vector2s. + /// </summary> + /// <param name="other">The other Vector2.</param> + /// <returns>The squared distance of the two Vector2s.</returns> public float Distance2(Vector2 other) { return (X - other.X) * (X - other.X) + (Y - other.Y) * (Y - other.Y); } + /// <summary> + /// Calculates the distance of two Vector2s. + /// </summary> + /// <param name="other">The other Vector2.</param> + /// <returns>The distance of the two Vector2s.</returns> public float Distance(Vector2 other) { return (float) Math.Sqrt(Distance2(other)); } + /// <summary> + /// Creates a new Vector2 by multiplying one with a scalar. + /// </summary> + /// <param name="multiplier">The scalar to multiply with.</param> + /// <returns>the new multiplied Vector2.</returns> public Vector2 Multiplied(float multiplier) { return new Vector2(X * multiplier, Y * multiplier); } + /// <summary> + /// Makes a new Vector2 by adding two Vector2s. + /// </summary> + /// <param name="other">The other Vector2.</param> + /// <returns>The new Vector2.</returns> public Vector2 Added(Vector2 other) { return Added(other.X, other.Y); } + /// <summary> + /// Makes a new Vector2 by adding coordinates to a Vector2. + /// </summary> + /// <param name="x">The first coordinate.</param> + /// <param name="y">The second coordinate.</param> + /// <returns>The new Vector2.</returns> public Vector2 Added(float x, float y) { return new Vector2(X + x, Y + y); } + /// <summary> + /// Makes a new Vector2 by subtracting two Vector2s. + /// </summary> + /// <param name="other">The other Vector2.</param> + /// <returns>The new Vector2.</returns> public Vector2 Subtracted(Vector2 other) { return Subtracted(other.X, other.Y); } + /// <summary> + /// Makes a new Vector2 by subtracting coordinates from a Vector2. + /// </summary> + /// <param name="x">The first coordinate.</param> + /// <param name="y">The second coordinate.</param> + /// <returns>The new Vector2.</returns> public Vector2 Subtracted(float x, float y) { return Added(-x, -y); } + /// <summary> + /// Creates the perpendicular of the Vector2. + /// </summary> + /// <returns>The perpendicular of the Vector2.</returns> public Vector2 Perpendicular() { return new Vector2(-Y, X); } + /// <summary> + /// Normalizes the Vector2. + /// </summary> + /// <returns>The normalized Vector2.</returns> public Vector2 Normalized() { return Multiplied(1 / Length); } + /// <summary> + /// Formats the Vector2 for printing on screen. + /// </summary> + /// <returns>Printable format of the Vector2.</returns> public override string ToString() { return $"({X:F2};{Y:F2})"; } + /// <summary> + /// Checks whether two Vector2s are the same. + /// </summary> + /// <param name="other">The other Vector2.</param> + /// <returns>True if they are at the same position.$</returns> public bool EqualsWithThreshold(Vector2 other) { return Subtracted(other).Length < 0.001; } -- GitLab