diff --git a/DoomDeathmatch/src/Component/ConsumableComponent.cs b/DoomDeathmatch/src/Component/ConsumableComponent.cs
index 9a06378..867abf2 100644
--- a/DoomDeathmatch/src/Component/ConsumableComponent.cs
+++ b/DoomDeathmatch/src/Component/ConsumableComponent.cs
@@ -8,16 +8,42 @@ using OpenTK.Mathematics;
namespace DoomDeathmatch.Component;
+///
+/// Represents a consumable item in the game, handling interaction with players and other objects.
+///
public class ConsumableComponent : Engine.Scene.Component.Component
{
+ ///
+ /// The consumable logic tied to this component.
+ ///
private readonly IConsumable _consumable;
+
+ ///
+ /// The collider used for detecting interactions with other objects.
+ ///
private readonly AABBColliderComponent _collider;
+
+ ///
+ /// The 2D box renderer used to display the consumable's icon.
+ ///
private readonly Box2DRenderer _box2DRenderer;
+ ///
+ /// Provides random values for movement adjustments.
+ ///
private readonly Random _random = new();
+ ///
+ /// Controls the movement of the consumable object.
+ ///
private MovementController _movementController = null!;
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The consumable logic associated with this component.
+ /// The collider for detecting interactions.
+ /// The renderer for displaying the consumable's visual representation.
public ConsumableComponent(IConsumable parConsumable, AABBColliderComponent parCollider,
Box2DRenderer parBox2DRenderer)
{
@@ -36,6 +62,10 @@ public class ConsumableComponent : Engine.Scene.Component.Component
ArgumentNullException.ThrowIfNull(_movementController);
}
+ ///
+ /// Handles collision events with other objects.
+ ///
+ /// The collider of the object that this collided with.
private void OnCollision(AABBColliderComponent parCollider)
{
if (parCollider.ColliderGroups.Contains("player"))
@@ -48,6 +78,10 @@ public class ConsumableComponent : Engine.Scene.Component.Component
}
}
+ ///
+ /// Attempts to consume the consumable if it collided with a player.
+ ///
+ /// The player's collider component.
private void TryConsume(AABBColliderComponent parCollider)
{
var playerController = parCollider.GameObject.GetComponent();
@@ -61,6 +95,10 @@ public class ConsumableComponent : Engine.Scene.Component.Component
EngineUtil.SceneManager.CurrentScene!.Remove(GameObject);
}
+ ///
+ /// Moves the consumable away if it collides with another consumable.
+ ///
+ /// The collider of the other consumable.
private void MoveAway(AABBColliderComponent parCollider)
{
var direction = _collider.GameObject.Transform.GetFullTranslation() -
@@ -78,6 +116,10 @@ public class ConsumableComponent : Engine.Scene.Component.Component
_movementController.ApplyMovement(direction);
}
+ ///
+ /// Generates a random direction vector for movement.
+ ///
+ /// A normalized random direction vector.
private Vector3 GetRandomDirection()
{
var x = (_random.NextSingle() * 2) - 1;
diff --git a/DoomDeathmatch/src/Component/MVC/Enemy/EnemyController.cs b/DoomDeathmatch/src/Component/MVC/Enemy/EnemyController.cs
index a95526e..93d459c 100644
--- a/DoomDeathmatch/src/Component/MVC/Enemy/EnemyController.cs
+++ b/DoomDeathmatch/src/Component/MVC/Enemy/EnemyController.cs
@@ -2,21 +2,50 @@
using DoomDeathmatch.Component.Util;
using DoomDeathmatch.Script.Model.Enemy;
using DoomDeathmatch.Script.Model.Enemy.Attack;
+using DoomDeathmatch.Script.MVC;
using Engine.Util;
namespace DoomDeathmatch.Component.MVC.Enemy;
+///
+/// Controls enemy behavior, including movement, health, and attacks.
+///
public class EnemyController : Engine.Scene.Component.Component
{
+ ///
+ /// Manages the health of the enemy.
+ ///
public HealthController HealthController { get; private set; } = null!;
+ ///
+ /// Data associated with the enemy, including stats and behaviors.
+ ///
private readonly EnemyData _enemyData;
+ ///
+ /// Reference to the game controller.
+ ///
private GameController _gameController = null!;
- private MovementController _movementController = null!;
- private AttackBehavior _attackBehavior = null!;
- private EnemyView _enemyView = null!;
+ ///
+ /// Controls the movement of the enemy.
+ ///
+ private MovementController _movementController = null!;
+
+ ///
+ /// Handles the enemy's attack behavior.
+ ///
+ private AttackBehavior _attackBehavior = null!;
+
+ ///
+ /// Handles visual representation of the enemy.
+ ///
+ private IView _enemyView = null!;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Data for the enemy, including stats and behaviors.
public EnemyController(EnemyData parEnemyData)
{
_enemyData = parEnemyData;
@@ -26,7 +55,7 @@ public class EnemyController : Engine.Scene.Component.Component
{
_gameController = EngineUtil.SceneManager.CurrentScene!.FindFirstComponent()!;
HealthController = GameObject.GetComponent()!;
- _enemyView = GameObject.GetComponent()!;
+ _enemyView = GameObject.GetComponent>()!;
_movementController = GameObject.GetComponent()!;
ArgumentNullException.ThrowIfNull(_gameController);
@@ -69,6 +98,9 @@ public class EnemyController : Engine.Scene.Component.Component
_attackBehavior.Attack(parDeltaTime);
}
+ ///
+ /// Handles the death of the enemy by removing it from the scene and updating the score.
+ ///
private void OnDeath()
{
EngineUtil.SceneManager.CurrentScene!.Remove(GameObject);
diff --git a/DoomDeathmatch/src/Component/MVC/Enemy/EnemyView.cs b/DoomDeathmatch/src/Component/MVC/Enemy/EnemyView.cs
index 90594e3..f3608a6 100644
--- a/DoomDeathmatch/src/Component/MVC/Enemy/EnemyView.cs
+++ b/DoomDeathmatch/src/Component/MVC/Enemy/EnemyView.cs
@@ -1,19 +1,31 @@
using DoomDeathmatch.Script.Model.Enemy;
+using DoomDeathmatch.Script.MVC;
using Engine.Graphics.Texture;
using Engine.Scene.Component.BuiltIn.Renderer;
using Engine.Util;
namespace DoomDeathmatch.Component.MVC.Enemy;
-public class EnemyView : Engine.Scene.Component.Component
+///
+/// View component for displaying the enemy.
+///
+public class EnemyView : Engine.Scene.Component.Component, IView
{
+ ///
+ /// The box2d renderer used to display the enemy.
+ ///
private readonly Box2DRenderer _box2DRenderer;
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Box2d renderer for displaying the enemy.
public EnemyView(Box2DRenderer parBox2DRenderer)
{
_box2DRenderer = parBox2DRenderer;
}
+ ///
public void UpdateView(EnemyData parEnemyData)
{
_box2DRenderer.Texture = EngineUtil.AssetResourceManager.Load(parEnemyData.Texture);
diff --git a/DoomDeathmatch/src/Component/MVC/GameController.cs b/DoomDeathmatch/src/Component/MVC/GameController.cs
index 8418a59..8bfb09f 100644
--- a/DoomDeathmatch/src/Component/MVC/GameController.cs
+++ b/DoomDeathmatch/src/Component/MVC/GameController.cs
@@ -7,19 +7,50 @@ using Engine.Util;
namespace DoomDeathmatch.Component.MVC;
+///
+/// Controls the main game logic, including pausing, unpausing, and handling game over states.
+///
public class GameController : Engine.Scene.Component.Component
{
+ ///
+ /// Indicates whether the game is currently paused.
+ ///
public bool IsPaused { get; private set; }
+
+ ///
+ /// Indicates whether the game is over.
+ ///
public bool IsGameOver { get; private set; }
+ ///
+ /// The player controller managing the player's state and actions.
+ ///
public PlayerController PlayerController { get; private set; } = null!;
+
+ ///
+ /// The score controller tracking the player's score.
+ ///
public ScoreController ScoreController { get; private set; } = null!;
+ ///
+ /// The input handler for handling keyboard and mouse input.
+ ///
private readonly IInputHandler _inputHandler = EngineUtil.InputHandler;
+
+ ///
+ /// The menu controller for handling the main menu.
+ ///
private readonly MenuControllerComponent _menuController;
+ ///
+ /// The timer controller for managing the game timer.
+ ///
private TimerController _timerController = null!;
+ ///
+ /// Initializes a new instance of the class with a specified menu controller.
+ ///
+ /// The menu controller used for menu navigation during the game.
public GameController(MenuControllerComponent parMenuController)
{
_menuController = parMenuController;
@@ -39,20 +70,6 @@ public class GameController : Engine.Scene.Component.Component
_timerController.OnFinished += GameOver;
}
- public void Unpause()
- {
- EngineUtil.SceneManager.CurrentScene!.TimeScale = 1.0f;
- IsPaused = false;
- _menuController.SelectMenuItem("play");
- }
-
- public void Pause()
- {
- EngineUtil.SceneManager.CurrentScene!.TimeScale = 0.0f;
- IsPaused = true;
- _menuController.SelectMenuItem("escape");
- }
-
public override void Update(double parDeltaTime)
{
if (_inputHandler.IsKeyJustPressed(KeyboardButtonCode.Escape))
@@ -68,6 +85,29 @@ public class GameController : Engine.Scene.Component.Component
}
}
+ ///
+ /// Pauses the game.
+ ///
+ public void Pause()
+ {
+ EngineUtil.SceneManager.CurrentScene!.TimeScale = 0.0f;
+ IsPaused = true;
+ _menuController.SelectMenuItem("escape");
+ }
+
+ ///
+ /// Resumes the game from a paused state.
+ ///
+ public void Unpause()
+ {
+ EngineUtil.SceneManager.CurrentScene!.TimeScale = 1.0f;
+ IsPaused = false;
+ _menuController.SelectMenuItem("play");
+ }
+
+ ///
+ /// Handles the game over state, transitioning to the Game Over scene.
+ ///
private void GameOver()
{
IsGameOver = true;
diff --git a/DoomDeathmatch/src/Component/MVC/Health/EnemyHealthView.cs b/DoomDeathmatch/src/Component/MVC/Health/EnemyHealthView.cs
index b56e19b..c1d12c2 100644
--- a/DoomDeathmatch/src/Component/MVC/Health/EnemyHealthView.cs
+++ b/DoomDeathmatch/src/Component/MVC/Health/EnemyHealthView.cs
@@ -1,15 +1,30 @@
using DoomDeathmatch.Script.Model;
+using DoomDeathmatch.Script.MVC;
using Engine.Scene.Component.BuiltIn.Renderer;
namespace DoomDeathmatch.Component.MVC.Health;
-public class EnemyHealthView : HealthView
+///
+/// View component for displaying the health status of an enemy.
+///
+public class EnemyHealthView : Engine.Scene.Component.Component, IView
{
- public EnemyHealthView(TextRenderer parHealthTextRenderer) : base(parHealthTextRenderer)
+ ///
+ /// The text renderer used to display the health.
+ ///
+ private readonly TextRenderer _healthTextRenderer;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Text renderer for displaying the health status text.
+ public EnemyHealthView(TextRenderer parHealthTextRenderer)
{
+ _healthTextRenderer = parHealthTextRenderer;
}
- public override void UpdateView(HealthModel parHealthModel)
+ ///
+ public void UpdateView(HealthModel parHealthModel)
{
_healthTextRenderer.Text = $"Здоровье: {parHealthModel.Health:000}";
}
diff --git a/DoomDeathmatch/src/Component/MVC/Health/HealthController.cs b/DoomDeathmatch/src/Component/MVC/Health/HealthController.cs
index 6854e1d..a84cb0f 100644
--- a/DoomDeathmatch/src/Component/MVC/Health/HealthController.cs
+++ b/DoomDeathmatch/src/Component/MVC/Health/HealthController.cs
@@ -1,15 +1,37 @@
using DoomDeathmatch.Script.Model;
+using DoomDeathmatch.Script.MVC;
namespace DoomDeathmatch.Component.MVC.Health;
+///
+/// Manages health-related logic, including damage, healing, and health changes.
+///
public class HealthController : Engine.Scene.Component.Component
{
+ ///
+ /// Triggered when the entity dies.
+ ///
public event Action? OnDeath;
+
+ ///
+ /// Indicates whether the entity is alive.
+ ///
public bool IsAlive => _healthModel.Health > 0;
+ ///
+ /// The health model containing the current and maximum health.
+ ///
private readonly HealthModel _healthModel;
- private HealthView? _healthView;
+ ///
+ /// The view responsible for displaying health information.
+ ///
+ private IView? _healthView;
+
+ ///
+ /// Initializes a new instance of the class with an optional starting health value.
+ ///
+ /// Initial health value. Defaults to 100.
public HealthController(float parHealth = 100)
{
_healthModel = new HealthModel(parHealth);
@@ -18,7 +40,7 @@ public class HealthController : Engine.Scene.Component.Component
public override void Awake()
{
_healthModel.HealthChanged += OnHealthChanged;
- _healthView = GameObject.GetComponent();
+ _healthView = GameObject.GetComponent>();
if (_healthView != null)
{
@@ -27,22 +49,38 @@ public class HealthController : Engine.Scene.Component.Component
}
}
+ ///
+ /// Sets the maximum health and restores the entity's health to the maximum value.
+ ///
+ /// The maximum health value.
public void SetMaxHealth(float parMaxHealth)
{
_healthModel.MaxHealth = parMaxHealth;
_healthModel.Health = parMaxHealth;
}
+ ///
+ /// Reduces the entity's health by the specified damage value.
+ ///
+ /// The amount of damage to apply.
public void TakeDamage(float parDamage)
{
_healthModel.Health -= parDamage;
}
+ ///
+ /// Increases the entity's health by the specified heal value.
+ ///
+ /// The amount of healing to apply.
public void Heal(float parHeal)
{
_healthModel.Health += parHeal;
}
+ ///
+ /// Handles health changes and triggers death logic if health reaches zero.
+ ///
+ /// The updated health model.
private void OnHealthChanged(HealthModel parHealthModel)
{
if (!IsAlive)
diff --git a/DoomDeathmatch/src/Component/MVC/Health/HealthView.cs b/DoomDeathmatch/src/Component/MVC/Health/HealthView.cs
index 9141eae..176a90a 100644
--- a/DoomDeathmatch/src/Component/MVC/Health/HealthView.cs
+++ b/DoomDeathmatch/src/Component/MVC/Health/HealthView.cs
@@ -1,17 +1,29 @@
using DoomDeathmatch.Script.Model;
+using DoomDeathmatch.Script.MVC;
using Engine.Scene.Component.BuiltIn.Renderer;
namespace DoomDeathmatch.Component.MVC.Health;
-public class HealthView : Engine.Scene.Component.Component
+///
+/// View component for displaying the health status.
+///
+public class HealthView : Engine.Scene.Component.Component, IView
{
- protected readonly TextRenderer _healthTextRenderer;
+ ///
+ /// The text renderer used to display the health percentage.
+ ///
+ private readonly TextRenderer _healthTextRenderer;
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Text renderer for displaying the health status text.
public HealthView(TextRenderer parHealthTextRenderer)
{
_healthTextRenderer = parHealthTextRenderer;
}
+ ///
public virtual void UpdateView(HealthModel parHealthModel)
{
var percentage = parHealthModel.Health / parHealthModel.MaxHealth * 100;
diff --git a/DoomDeathmatch/src/Component/MVC/MovementController.cs b/DoomDeathmatch/src/Component/MVC/MovementController.cs
index a23498c..2ee7ac5 100644
--- a/DoomDeathmatch/src/Component/MVC/MovementController.cs
+++ b/DoomDeathmatch/src/Component/MVC/MovementController.cs
@@ -3,11 +3,24 @@ using OpenTK.Mathematics;
namespace DoomDeathmatch.Component.MVC;
+///
+/// Controls the movement logic for a game object, applying movement forces to the rigidbody.
+///
public class MovementController : Engine.Scene.Component.Component
{
+ ///
+ /// The movement speed.
+ ///
public float Speed { get; set; } = 10.0f;
+ ///
+ /// The rigidbody component for the game object.
+ ///
private RigidbodyComponent _rigidbody = null!;
+
+ ///
+ /// The drag component for the game object.
+ ///
private DragComponent _dragComponent = null!;
public override void Awake()
@@ -19,6 +32,10 @@ public class MovementController : Engine.Scene.Component.Component
ArgumentNullException.ThrowIfNull(_dragComponent);
}
+ ///
+ /// Applies a directional movement force to the object.
+ ///
+ /// The direction of movement.
public void ApplyMovement(Vector3 parDirection)
{
_rigidbody.Force += _dragComponent.Drag * Speed * parDirection.Normalized();
diff --git a/DoomDeathmatch/src/Component/MVC/PlayerController.cs b/DoomDeathmatch/src/Component/MVC/PlayerController.cs
index 36c4736..b4af6b1 100644
--- a/DoomDeathmatch/src/Component/MVC/PlayerController.cs
+++ b/DoomDeathmatch/src/Component/MVC/PlayerController.cs
@@ -9,17 +9,45 @@ using OpenTK.Mathematics;
namespace DoomDeathmatch.Component.MVC;
+///
+/// Controls the player's actions and state, including health, weapons, and input handling.
+///
public class PlayerController : Engine.Scene.Component.Component
{
+ ///
+ /// Event triggered when the player dies.
+ ///
public event Action? OnDeath;
+ ///
+ /// Indicates whether the player is alive.
+ ///
public bool IsAlive => HealthController.IsAlive;
+
+ ///
+ /// The health controller managing the player's health.
+ ///
public HealthController HealthController { get; private set; } = null!;
+
+ ///
+ /// The weapon controller managing the player's weapons.
+ ///
public WeaponController WeaponController { get; private set; } = null!;
+
+ ///
+ /// The player's camera providing a perspective view.
+ ///
public PerspectiveCamera Camera { get; }
+ ///
+ /// The input handler for handling keyboard and mouse input.
+ ///
private readonly IInputHandler _inputHandler = EngineUtil.InputHandler;
+ ///
+ /// Initializes a new instance of the class with a specified camera.
+ ///
+ /// The player's perspective camera.
public PlayerController(PerspectiveCamera parCamera)
{
Camera = parCamera;
@@ -66,24 +94,32 @@ public class PlayerController : Engine.Scene.Component.Component
return;
}
- var position = Camera.GameObject.Transform.GetFullTranslation();
- var forward = (Camera.Forward - position).Normalized();
- var right = Vector3.Cross(forward, Vector3.UnitZ).Normalized();
+ HandleShootingRaycast();
+ }
+ }
- var collisionManager = EngineUtil.SceneManager.CurrentScene!.FindFirstComponent();
+ ///
+ /// Handles the shooting raycast for the player.
+ ///
+ private void HandleShootingRaycast()
+ {
+ var position = Camera.GameObject.Transform.GetFullTranslation();
+ var forward = (Camera.Forward - position).Normalized();
+ var right = Vector3.Cross(forward, Vector3.UnitZ).Normalized();
- var offsets = WeaponController.WeaponData.ShootPattern.GetShootPattern(forward, Vector3.UnitZ, right);
- foreach (var offset in offsets)
+ var collisionManager = EngineUtil.SceneManager.CurrentScene!.FindFirstComponent();
+
+ var offsets = WeaponController.WeaponData.ShootPattern.GetShootPattern(forward, Vector3.UnitZ, right);
+ foreach (var offset in offsets)
+ {
+ var direction = forward + offset;
+ if (!collisionManager!.Raycast(position, direction, ["enemy", "wall"], out var result))
{
- var direction = forward + offset;
- if (!collisionManager!.Raycast(position, direction, ["enemy", "wall"], out var result))
- {
- continue;
- }
-
- var enemyController = result.HitObject.GetComponent();
- enemyController?.HealthController.TakeDamage(WeaponController.WeaponData.Damage);
+ continue;
}
+
+ var enemyController = result.HitObject.GetComponent();
+ enemyController?.HealthController.TakeDamage(WeaponController.WeaponData.Damage);
}
}
}
\ No newline at end of file
diff --git a/DoomDeathmatch/src/Component/MVC/Score/ScoreController.cs b/DoomDeathmatch/src/Component/MVC/Score/ScoreController.cs
index 5d6bf6a..02e90d1 100644
--- a/DoomDeathmatch/src/Component/MVC/Score/ScoreController.cs
+++ b/DoomDeathmatch/src/Component/MVC/Score/ScoreController.cs
@@ -1,21 +1,39 @@
using DoomDeathmatch.Script.Model;
+using DoomDeathmatch.Script.MVC;
namespace DoomDeathmatch.Component.MVC.Score;
+///
+/// Manages the player's score, including updating and displaying it.
+///
public class ScoreController : Engine.Scene.Component.Component
{
+ ///
+ /// Current score value.
+ ///
public int Score => _scoreModel.Score;
+ ///
+ /// The score model containing the current score.
+ ///
private readonly ScoreModel _scoreModel = new();
- private ScoreView _scoreView = null!;
+
+ ///
+ /// The view responsible for displaying score information.
+ ///
+ private IView _scoreView = null!;
public override void Awake()
{
- _scoreView = GameObject.GetComponent()!;
+ _scoreView = GameObject.GetComponent>()!;
_scoreView.UpdateView(_scoreModel);
_scoreModel.ScoreChanged += _scoreView.UpdateView;
}
+ ///
+ /// Adds the specified value to the current score.
+ ///
+ /// The score value to add.
public void AddScore(int parScore)
{
_scoreModel.Score += parScore;
diff --git a/DoomDeathmatch/src/Component/MVC/Score/ScoreView.cs b/DoomDeathmatch/src/Component/MVC/Score/ScoreView.cs
index 63868b4..7f46332 100644
--- a/DoomDeathmatch/src/Component/MVC/Score/ScoreView.cs
+++ b/DoomDeathmatch/src/Component/MVC/Score/ScoreView.cs
@@ -1,17 +1,29 @@
using DoomDeathmatch.Script.Model;
+using DoomDeathmatch.Script.MVC;
using Engine.Scene.Component.BuiltIn.Renderer;
namespace DoomDeathmatch.Component.MVC.Score;
-public class ScoreView : Engine.Scene.Component.Component
+///
+/// View component for displaying the score.
+///
+public class ScoreView : Engine.Scene.Component.Component, IView
{
+ ///
+ /// The text renderer used to display the score.
+ ///
private readonly TextRenderer _scoreTextRenderer;
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Text renderer for displaying the score text.
public ScoreView(TextRenderer parScoreTextRenderer)
{
_scoreTextRenderer = parScoreTextRenderer;
}
+ ///
public void UpdateView(ScoreModel parScoreModel)
{
_scoreTextRenderer.Text = $"Счет: {parScoreModel.Score:00000}";
diff --git a/DoomDeathmatch/src/Component/MVC/Timer/TimerController.cs b/DoomDeathmatch/src/Component/MVC/Timer/TimerController.cs
index 77b9b95..2e31e93 100644
--- a/DoomDeathmatch/src/Component/MVC/Timer/TimerController.cs
+++ b/DoomDeathmatch/src/Component/MVC/Timer/TimerController.cs
@@ -1,19 +1,41 @@
-using Engine.Util;
+using DoomDeathmatch.Script.MVC;
+using Engine.Util;
namespace DoomDeathmatch.Component.MVC.Timer;
+///
+/// Controls the timer functionality, including updates and view synchronization.
+///
public class TimerController : Engine.Scene.Component.Component
{
+ ///
+ /// Triggered when the timer finishes.
+ ///
public event Action? OnFinished;
- private readonly TickableTimer _tickableTimer = new(60 + 10);
+ ///
+ /// Internal timer that tracks the current countdown time.
+ ///
+ private readonly TickableTimer _tickableTimer;
- private TimerView _timerView = null!;
+ ///
+ /// View responsible for displaying the timer's current state.
+ ///
+ private IView _timerView = null!;
+
+ ///
+ /// Initializes a new instance of the class with an optional starting time.
+ ///
+ /// The initial time value. Defaults to 60 seconds.
+ public TimerController(float parTime = 60)
+ {
+ _tickableTimer = new TickableTimer(parTime);
+ }
public override void Awake()
{
- _timerView = GameObject.GetComponent()!;
- _timerView.UpdateView(_tickableTimer.CurrentTime);
+ _timerView = GameObject.GetComponent>()!;
+ _timerView.UpdateView(_tickableTimer);
_tickableTimer.OnUpdate += OnTimeChanged;
_tickableTimer.OnFinished += OnFinished;
@@ -24,8 +46,12 @@ public class TimerController : Engine.Scene.Component.Component
_tickableTimer.Update(parDeltaTime);
}
+ ///
+ /// Updates the timer view with the new time value.
+ ///
+ /// The updated time value.
private void OnTimeChanged(double parTime)
{
- _timerView.UpdateView(parTime);
+ _timerView.UpdateView(_tickableTimer);
}
}
\ No newline at end of file
diff --git a/DoomDeathmatch/src/Component/MVC/Timer/TimerView.cs b/DoomDeathmatch/src/Component/MVC/Timer/TimerView.cs
index fb7193a..125e4b0 100644
--- a/DoomDeathmatch/src/Component/MVC/Timer/TimerView.cs
+++ b/DoomDeathmatch/src/Component/MVC/Timer/TimerView.cs
@@ -1,20 +1,34 @@
-using Engine.Scene.Component.BuiltIn.Renderer;
+using DoomDeathmatch.Script.MVC;
+using Engine.Scene.Component.BuiltIn.Renderer;
+using Engine.Util;
namespace DoomDeathmatch.Component.MVC.Timer;
-public class TimerView : Engine.Scene.Component.Component
+///
+/// View component for displaying the timer.
+///
+public class TimerView : Engine.Scene.Component.Component, IView
{
+ ///
+ /// The text renderer used to display the timer.
+ ///
private readonly TextRenderer _timerTextRenderer;
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Text renderer for displaying the timer text.
public TimerView(TextRenderer parTimerTextRenderer)
{
_timerTextRenderer = parTimerTextRenderer;
}
- public void UpdateView(double parTime)
+ ///
+ public void UpdateView(TickableTimer parTime)
{
- var seconds = Math.Floor(parTime) % 60;
- var minutes = Math.Floor(parTime / 60) % 60;
+ var time = parTime.CurrentTime;
+ var seconds = Math.Floor(time) % 60;
+ var minutes = Math.Floor(time / 60) % 60;
_timerTextRenderer.Text = $"Время: {minutes:00}:{seconds:00}";
}
diff --git a/DoomDeathmatch/src/Component/MVC/Weapon/AmmoData.cs b/DoomDeathmatch/src/Component/MVC/Weapon/AmmoData.cs
new file mode 100644
index 0000000..ecea149
--- /dev/null
+++ b/DoomDeathmatch/src/Component/MVC/Weapon/AmmoData.cs
@@ -0,0 +1,17 @@
+namespace DoomDeathmatch.Component.MVC.Weapon;
+
+///
+/// Data for ammo information.
+///
+public struct AmmoData
+{
+ ///
+ /// The maximum amount of ammo.
+ ///
+ public int MaxAmmo { get; set; }
+
+ ///
+ /// The current amount of ammo.
+ ///
+ public int Ammo { get; set; }
+}
\ No newline at end of file
diff --git a/DoomDeathmatch/src/Component/MVC/Weapon/IWeaponView.cs b/DoomDeathmatch/src/Component/MVC/Weapon/IWeaponView.cs
new file mode 100644
index 0000000..09ec8a9
--- /dev/null
+++ b/DoomDeathmatch/src/Component/MVC/Weapon/IWeaponView.cs
@@ -0,0 +1,15 @@
+using DoomDeathmatch.Script.Model.Weapon;
+using DoomDeathmatch.Script.MVC;
+
+namespace DoomDeathmatch.Component.MVC.Weapon;
+
+///
+/// Interface for weapon view components.
+///
+public interface IWeaponView : IView, IView
+{
+ ///
+ /// Starts the weapon fire animation.
+ ///
+ public void PlayFireAnimation();
+}
\ No newline at end of file
diff --git a/DoomDeathmatch/src/Component/MVC/Weapon/WeaponController.cs b/DoomDeathmatch/src/Component/MVC/Weapon/WeaponController.cs
index 174f9ae..b50f0b8 100644
--- a/DoomDeathmatch/src/Component/MVC/Weapon/WeaponController.cs
+++ b/DoomDeathmatch/src/Component/MVC/Weapon/WeaponController.cs
@@ -3,23 +3,48 @@ using DoomDeathmatch.Script.Model.Weapon;
namespace DoomDeathmatch.Component.MVC.Weapon;
+///
+/// Manages weapon functionality, including shooting, reloading, and weapon selection.
+///
public class WeaponController : Engine.Scene.Component.Component
{
+ ///
+ /// Triggered when a weapon is fired.
+ ///
public event Action? OnWeaponShot;
+
+ ///
+ /// The currently selected weapon's data.
+ ///
public WeaponData WeaponData => _weaponModel.SelectedWeapon;
+ ///
+ /// The internal weapon model containing weapon-related data.
+ ///
private readonly WeaponModel _weaponModel = new();
- private WeaponView _weaponView = null!;
+
+ ///
+ /// View responsible for displaying weapon information and animations.
+ ///
+ private IWeaponView _weaponView = null!;
public override void Awake()
{
- _weaponView = GameObject.GetComponent()!;
+ _weaponView = GameObject.GetComponent()!;
_weaponView.UpdateView(_weaponModel.SelectedWeapon);
+ _weaponView.UpdateView(new AmmoData
+ {
+ Ammo = _weaponModel.SelectedWeapon.Ammo, MaxAmmo = _weaponModel.SelectedWeapon.MaxAmmo
+ });
_weaponModel.OnWeaponSelected += WeaponSelected;
WeaponSelected(null, _weaponModel.SelectedWeapon);
}
+ ///
+ /// Attempts to fire the currently selected weapon.
+ ///
+ /// true if the weapon is fired successfully; otherwise, false.
public bool TryShoot()
{
if (_weaponModel.SelectedWeapon.Ammo <= 0)
@@ -30,16 +55,23 @@ public class WeaponController : Engine.Scene.Component.Component
_weaponModel.SelectedWeapon.Ammo--;
OnWeaponShot?.Invoke(_weaponModel.SelectedWeapon);
- _weaponView.Fire();
+ _weaponView.PlayFireAnimation();
return true;
}
+ ///
+ /// Reloads the currently selected weapon, restoring its ammo to the maximum value.
+ ///
public void Reload()
{
_weaponModel.SelectedWeapon.Ammo = _weaponModel.SelectedWeapon.MaxAmmo;
}
+ ///
+ /// Adds a new weapon to the weapon model if it does not already exist.
+ ///
+ /// The weapon data to add.
public void AddWeapon(WeaponData parWeaponData)
{
if (_weaponModel.Weapons.Contains(parWeaponData))
@@ -50,6 +82,10 @@ public class WeaponController : Engine.Scene.Component.Component
_weaponModel.Weapons.Add(parWeaponData);
}
+ ///
+ /// Adds a weapon to the model or merges its ammo with an existing weapon of the same type.
+ ///
+ /// The weapon data to add or merge.
public void AddOrMergeWeapon(WeaponData parWeaponData)
{
if (!_weaponModel.Weapons.Contains(parWeaponData))
@@ -62,6 +98,10 @@ public class WeaponController : Engine.Scene.Component.Component
}
}
+ ///
+ /// Removes a weapon from the model by its index.
+ ///
+ /// The index of the weapon to remove.
public void RemoveWeapon(int parIndex)
{
if (parIndex <= 0 || parIndex >= _weaponModel.Weapons.Count)
@@ -75,6 +115,10 @@ public class WeaponController : Engine.Scene.Component.Component
_weaponModel.Weapons.RemoveAt(parIndex);
}
+ ///
+ /// Selects a weapon from the model by its index.
+ ///
+ /// The index of the weapon to select.
public void SelectWeapon(int parIndex)
{
if (parIndex >= _weaponModel.Weapons.Count)
@@ -85,14 +129,26 @@ public class WeaponController : Engine.Scene.Component.Component
_weaponModel.SelectedWeaponIndex = parIndex;
}
+ ///
+ /// Updates the view when the selected weapon changes.
+ ///
+ /// The previously selected weapon.
+ /// The newly selected weapon.
private void WeaponSelected(WeaponData? parOldWeapon, WeaponData parNewWeapon)
{
if (parOldWeapon != null)
{
- parOldWeapon.OnAmmoChanged -= _weaponView.UpdateAmmoView;
+ parOldWeapon.OnAmmoChanged -= AmmoChanged;
}
- parNewWeapon.OnAmmoChanged += _weaponView.UpdateAmmoView;
+ parNewWeapon.OnAmmoChanged += AmmoChanged;
_weaponView.UpdateView(parNewWeapon);
}
+
+ private void AmmoChanged(WeaponData parWeapon)
+ {
+ var ammoData = new AmmoData { Ammo = parWeapon.Ammo, MaxAmmo = parWeapon.MaxAmmo };
+
+ _weaponView.UpdateView(ammoData);
+ }
}
\ No newline at end of file
diff --git a/DoomDeathmatch/src/Component/MVC/Weapon/WeaponView.cs b/DoomDeathmatch/src/Component/MVC/Weapon/WeaponView.cs
index dd2c446..d4af643 100644
--- a/DoomDeathmatch/src/Component/MVC/Weapon/WeaponView.cs
+++ b/DoomDeathmatch/src/Component/MVC/Weapon/WeaponView.cs
@@ -6,16 +6,42 @@ using Engine.Util;
namespace DoomDeathmatch.Component.MVC.Weapon;
-public class WeaponView : Engine.Scene.Component.Component
+///
+/// View component for displaying weapon information such as name, ammo, and sprite.
+///
+public class WeaponView : Engine.Scene.Component.Component, IWeaponView
{
+ ///
+ /// The text renderer used to display the weapon name.
+ ///
private readonly TextRenderer _weaponName;
+
+ ///
+ /// The text renderer used to display the weapon ammo.
+ ///
private readonly TextRenderer _weaponAmmo;
+
+ ///
+ /// The box2d renderer used to display the weapon sprite.
+ ///
private readonly Box2DRenderer _weaponSprite;
+ ///
+ /// The texture used for the weapon sprite when it is idle.
+ ///
private Texture? _idleTexture;
+ ///
+ /// The animation player used to display the weapon sprite when it is firing.
+ ///
private AnimationPlayer? _weaponFireAnimation;
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Text renderer for displaying the weapon name.
+ /// Text renderer for displaying the ammo count.
+ /// Renderer for displaying the weapon sprite.
public WeaponView(TextRenderer parWeaponName, TextRenderer parWeaponAmmo, Box2DRenderer parWeaponSprite)
{
_weaponName = parWeaponName;
@@ -28,9 +54,9 @@ public class WeaponView : Engine.Scene.Component.Component
_weaponFireAnimation?.Update(parDeltaTime);
}
+ ///
public void UpdateView(WeaponData parWeaponData)
{
- UpdateAmmoView(parWeaponData);
_weaponName.Text = $"Оружие: {parWeaponData.Name}";
_idleTexture = EngineUtil.AssetResourceManager.Load(parWeaponData.IdleTexture);
@@ -50,21 +76,30 @@ public class WeaponView : Engine.Scene.Component.Component
_weaponFireAnimation.OnFinish += OnAnimationFinish;
}
- public void UpdateAmmoView(WeaponData parWeaponData)
+ ///
+ public void UpdateView(AmmoData parAmmoData)
{
- _weaponAmmo.Text = $"Патроны: {parWeaponData.Ammo}/{parWeaponData.MaxAmmo}";
+ _weaponAmmo.Text = $"Патроны: {parAmmoData.Ammo}/{parAmmoData.MaxAmmo}";
}
- public void Fire()
+ ///
+ public void PlayFireAnimation()
{
_weaponFireAnimation?.Start();
}
+ ///
+ /// Handles the animation frame change event.
+ ///
+ /// The current frame texture.
private void OnAnimationFrame(Texture parFrameTexture)
{
_weaponSprite.Texture = parFrameTexture;
}
+ ///
+ /// Handles the animation finish event.
+ ///
private void OnAnimationFinish()
{
_weaponSprite.Texture = _idleTexture;
diff --git a/DoomDeathmatch/src/Component/ObjectSpawnerComponent.cs b/DoomDeathmatch/src/Component/ObjectSpawnerComponent.cs
index e91b0b3..2edb7ff 100644
--- a/DoomDeathmatch/src/Component/ObjectSpawnerComponent.cs
+++ b/DoomDeathmatch/src/Component/ObjectSpawnerComponent.cs
@@ -2,6 +2,9 @@
namespace DoomDeathmatch.Component;
+///
+/// Component for spawning objects using .
+///
public class ObjectSpawnerComponent(ObjectSpawner parObjectSpawner) : Engine.Scene.Component.Component
{
public override void Update(double parDeltaTime)
diff --git a/DoomDeathmatch/src/Component/Physics/Collision/AABBColliderComponent.cs b/DoomDeathmatch/src/Component/Physics/Collision/AABBColliderComponent.cs
index 67bb0ec..b980307 100644
--- a/DoomDeathmatch/src/Component/Physics/Collision/AABBColliderComponent.cs
+++ b/DoomDeathmatch/src/Component/Physics/Collision/AABBColliderComponent.cs
@@ -3,16 +3,44 @@ using OpenTK.Mathematics;
namespace DoomDeathmatch.Component.Physics.Collision;
+///
+/// Represents an axis-aligned bounding box (AABB) collider component used for collision detection.
+///
public class AABBColliderComponent : Engine.Scene.Component.Component
{
+ ///
+ /// Triggered when a collision occurs with another .
+ ///
public event Action? OnCollision;
+ ///
+ /// The collider defining the bounds of this component.
+ ///
public AABBCollider Collider { get; set; } = new();
+
+ ///
+ /// Offset applied to the collider position relative to the parent object.
+ ///
public Vector3 Offset { get; set; } = Vector3.Zero;
+
+ ///
+ /// A set of groups that this collider belongs to.
+ ///
public ISet ColliderGroups => _colliderGroups;
+
+ ///
+ /// A set of groups that this collider will not collide with.
+ ///
public ISet ExcludeColliderCollideGroups => _excludeColliderCollideGroups;
+ ///
+ /// A set of groups that this collider belongs to.
+ ///
private readonly HashSet _colliderGroups = ["default"];
+
+ ///
+ /// A set of groups that this collider will not collide with.
+ ///
private readonly HashSet _excludeColliderCollideGroups = [];
public override void Update(double parDeltaTime)
@@ -20,13 +48,12 @@ public class AABBColliderComponent : Engine.Scene.Component.Component
Collider.Position = GameObject.Transform.GetFullTranslation() + Offset;
}
+ ///
+ /// Invokes the collision logic for this collider with the specified collider.
+ ///
+ /// The collider with which this component collided.
public void CollideWith(AABBColliderComponent parCollider)
{
OnCollision?.Invoke(parCollider);
}
-
- public bool InColliderGroup(string parGroup)
- {
- return ColliderGroups.Contains(parGroup);
- }
}
\ No newline at end of file
diff --git a/DoomDeathmatch/src/Component/Physics/Collision/ColliderForceFieldComponent.cs b/DoomDeathmatch/src/Component/Physics/Collision/ColliderForceFieldComponent.cs
index 6e08e47..4c5db22 100644
--- a/DoomDeathmatch/src/Component/Physics/Collision/ColliderForceFieldComponent.cs
+++ b/DoomDeathmatch/src/Component/Physics/Collision/ColliderForceFieldComponent.cs
@@ -2,6 +2,9 @@
namespace DoomDeathmatch.Component.Physics.Collision;
+///
+/// A force field component that applies collision-based velocity changes to rigid bodies.
+///
public class ColliderForceFieldComponent : Engine.Scene.Component.Component
{
private AABBColliderComponent _collider = null!;
@@ -12,6 +15,10 @@ public class ColliderForceFieldComponent : Engine.Scene.Component.Component
_collider.OnCollision += OnCollision;
}
+ ///
+ /// Handles collision events and modifies the velocity of colliding rigid bodies.
+ ///
+ /// The collider involved in the collision.
private void OnCollision(AABBColliderComponent parCollider)
{
var rigidbody = parCollider.GameObject.GetComponent();
@@ -27,6 +34,6 @@ public class ColliderForceFieldComponent : Engine.Scene.Component.Component
return;
}
- rigidbody.Velocity -= normal * (speedAlongNormal * 1.75f);
+ rigidbody.Velocity -= normal * speedAlongNormal;
}
}
\ No newline at end of file
diff --git a/DoomDeathmatch/src/Component/Physics/Collision/CollisionManagerComponent.cs b/DoomDeathmatch/src/Component/Physics/Collision/CollisionManagerComponent.cs
index e82021e..a73cbd9 100644
--- a/DoomDeathmatch/src/Component/Physics/Collision/CollisionManagerComponent.cs
+++ b/DoomDeathmatch/src/Component/Physics/Collision/CollisionManagerComponent.cs
@@ -5,8 +5,14 @@ using OpenTK.Mathematics;
namespace DoomDeathmatch.Component.Physics.Collision;
+///
+/// Manages collisions between AABB colliders in the current scene.
+///
public class CollisionManagerComponent : Engine.Scene.Component.Component
{
+ ///
+ /// A list of colliders in the current scene.
+ ///
private List _colliders = [];
public override void PreUpdate(double parDeltaTime)
@@ -24,34 +30,19 @@ public class CollisionManagerComponent : Engine.Scene.Component.Component
{
var colliderB = _colliders[j];
- var canCollideAB = colliderA.ExcludeColliderCollideGroups.Count == 0 ||
- !colliderB.ColliderGroups.Overlaps(colliderA.ExcludeColliderCollideGroups);
- var canCollideBA = colliderB.ExcludeColliderCollideGroups.Count == 0 ||
- !colliderA.ColliderGroups.Overlaps(colliderB.ExcludeColliderCollideGroups);
-
- if (!canCollideAB && !canCollideBA)
- {
- continue;
- }
-
- if (!colliderA.Collider.Intersects(colliderB.Collider))
- {
- continue;
- }
-
- if (canCollideAB)
- {
- colliderA.CollideWith(colliderB);
- }
-
- if (canCollideBA)
- {
- colliderB.CollideWith(colliderA);
- }
+ PerformCollisionCheck(colliderA, colliderB);
}
}
}
+ ///
+ /// Performs a raycast and finds the closest collider intersected by the ray.
+ ///
+ /// The starting point of the ray.
+ /// The direction of the ray.
+ /// The collider groups to consider for the raycast.
+ /// The result of the raycast, if an intersection occurs.
+ /// true if an intersection occurs; otherwise, false.
public bool Raycast(Vector3 parStart, Vector3 parDirection, HashSet parColliderGroups,
[MaybeNullWhen(false)] out RaycastResult parResult)
{
@@ -90,6 +81,48 @@ public class CollisionManagerComponent : Engine.Scene.Component.Component
return parResult != null;
}
+ ///
+ /// Performs a collision check between two colliders and invokes the appropriate collision events.
+ ///
+ /// The first collider.
+ /// The second collider.
+ private static void PerformCollisionCheck(AABBColliderComponent parColliderA, AABBColliderComponent parColliderB)
+ {
+ var canCollideAB = parColliderA.ExcludeColliderCollideGroups.Count == 0 ||
+ !parColliderB.ColliderGroups.Overlaps(parColliderA.ExcludeColliderCollideGroups);
+ var canCollideBA = parColliderB.ExcludeColliderCollideGroups.Count == 0 ||
+ !parColliderA.ColliderGroups.Overlaps(parColliderB.ExcludeColliderCollideGroups);
+
+ if (!canCollideAB && !canCollideBA)
+ {
+ return;
+ }
+
+ if (!parColliderA.Collider.Intersects(parColliderB.Collider))
+ {
+ return;
+ }
+
+ if (canCollideAB)
+ {
+ parColliderA.CollideWith(parColliderB);
+ }
+
+ if (canCollideBA)
+ {
+ parColliderB.CollideWith(parColliderA);
+ }
+ }
+
+ ///
+ /// Checks for intersection between a ray and an AABB collider.
+ ///
+ /// The origin of the ray.
+ /// The direction of the ray.
+ /// The collider to test against.
+ /// The intersection point, if the ray intersects.
+ /// The normal of the intersection surface.
+ /// true if the ray intersects the collider; otherwise, false.
private static bool RaycastAABB(Vector3 parOrigin, Vector3 parDirection, AABBCollider parCollider,
out Vector3 parHitPoint,
out Vector3 parHitNormal)
diff --git a/DoomDeathmatch/src/Component/Physics/DragComponent.cs b/DoomDeathmatch/src/Component/Physics/DragComponent.cs
index f9fa47b..8d865f3 100644
--- a/DoomDeathmatch/src/Component/Physics/DragComponent.cs
+++ b/DoomDeathmatch/src/Component/Physics/DragComponent.cs
@@ -2,11 +2,24 @@
namespace DoomDeathmatch.Component.Physics;
+///
+/// Applies drag to a rigidbody to simulate resistance to motion.
+///
public class DragComponent : Engine.Scene.Component.Component
{
+ ///
+ /// The drag coefficient applied to the velocity of the rigidbody.
+ ///
public float Drag { get; set; } = 1f;
+
+ ///
+ /// A multiplier applied to each axis of the velocity when calculating drag.
+ ///
public Vector3 Multiplier { get; set; } = Vector3.One;
+ ///
+ /// The rigidbody to apply drag to.
+ ///
private RigidbodyComponent _rigidbody = null!;
public override void Awake()
diff --git a/DoomDeathmatch/src/Component/Physics/GravityComponent.cs b/DoomDeathmatch/src/Component/Physics/GravityComponent.cs
index fa9d6d3..f663314 100644
--- a/DoomDeathmatch/src/Component/Physics/GravityComponent.cs
+++ b/DoomDeathmatch/src/Component/Physics/GravityComponent.cs
@@ -2,24 +2,45 @@
namespace DoomDeathmatch.Component.Physics;
+///
+/// Simulates the effect of gravity on a rigidbody.
+///
public class GravityComponent : Engine.Scene.Component.Component
{
+ ///
+ /// Indicates whether the object is currently in the air.
+ ///
public bool IsInAir { get; private set; }
+ ///
+ /// The strength of the gravitational force.
+ ///
public float Strength { get; set; } = 10.0f;
+ ///
+ /// The direction of the gravitational force.
+ ///
public Vector3 Direction
{
get => _direction;
set => _direction = value.Normalized();
}
+ ///
+ /// The height at which gravity stops affecting the object.
+ ///
public float Floor { get; set; } = 5.0f;
-
- private RigidbodyComponent _rigidbody = null!;
+ ///
+ /// The direction of the gravitational force.
+ ///
private Vector3 _direction = -Vector3.UnitZ;
+ ///
+ /// The rigidbody to apply gravity to.
+ ///
+ private RigidbodyComponent _rigidbody = null!;
+
public override void Awake()
{
_rigidbody = GameObject.GetComponent()!;
diff --git a/DoomDeathmatch/src/Component/Physics/RigidbodyComponent.cs b/DoomDeathmatch/src/Component/Physics/RigidbodyComponent.cs
index dcceded..19fb26b 100644
--- a/DoomDeathmatch/src/Component/Physics/RigidbodyComponent.cs
+++ b/DoomDeathmatch/src/Component/Physics/RigidbodyComponent.cs
@@ -2,11 +2,24 @@
namespace DoomDeathmatch.Component.Physics;
+///
+/// Represents a rigidbody component that simulates physics behavior such as force, velocity, and acceleration.
+///
public class RigidbodyComponent : Engine.Scene.Component.Component
{
+ ///
+ /// The mass of the rigidbody.
+ ///
public float Mass { get; set; } = 1.0f;
+
+ ///
+ /// Indicates whether the rigidbody is static and unaffected by forces.
+ ///
public bool IsStatic { get; set; } = false;
+ ///
+ /// The force currently applied to the rigidbody.
+ ///
public Vector3 Force
{
get => _force;
@@ -21,6 +34,9 @@ public class RigidbodyComponent : Engine.Scene.Component.Component
}
}
+ ///
+ /// The velocity of the rigidbody.
+ ///
public Vector3 Velocity
{
get => _velocity;
@@ -35,11 +51,22 @@ public class RigidbodyComponent : Engine.Scene.Component.Component
}
}
+ ///
+ /// The force currently applied to the rigidbody.
+ ///
private Vector3 _force = Vector3.Zero;
- private Vector3 _velocity = Vector3.Zero;
+
+ ///
+ /// The acceleration of the rigidbody.
+ ///
private Vector3 _acceleration = Vector3.Zero;
- public override void Update(double parDeltaTime)
+ ///
+ /// The velocity of the rigidbody.
+ ///
+ private Vector3 _velocity = Vector3.Zero;
+
+ public override void PostUpdate(double parDeltaTime)
{
if (IsStatic)
{
diff --git a/DoomDeathmatch/src/Component/UI/MenuControllerComponent.cs b/DoomDeathmatch/src/Component/UI/MenuControllerComponent.cs
index 4a2475b..b8801e8 100644
--- a/DoomDeathmatch/src/Component/UI/MenuControllerComponent.cs
+++ b/DoomDeathmatch/src/Component/UI/MenuControllerComponent.cs
@@ -2,20 +2,39 @@
namespace DoomDeathmatch.Component.UI;
+///
+/// A component responsible for managing and selecting menu items in a UI.
+///
public class MenuControllerComponent : Engine.Scene.Component.Component
{
+ ///
+ /// A dictionary of menu items, mapping their names to their game objects.
+ ///
private readonly Dictionary _menuItems = new();
+ ///
+ /// Adds a new menu item to the menu.
+ ///
+ /// The name of the menu item.
+ /// The game object representing the menu item.
public void AddMenuItem(string parName, GameObject parGameObject)
{
_menuItems.Add(parName, parGameObject);
}
+ ///
+ /// Removes a menu item from the menu by name.
+ ///
+ /// The name of the menu item to remove.
public void RemoveMenuItem(string parName)
{
_menuItems.Remove(parName);
}
+ ///
+ /// Selects a menu item by name, enabling only the selected item.
+ ///
+ /// The name of the menu item to select.
public void SelectMenuItem(string parName)
{
foreach (var (name, menuItem) in _menuItems)
diff --git a/DoomDeathmatch/src/Component/UI/SelectorComponent.cs b/DoomDeathmatch/src/Component/UI/SelectorComponent.cs
index 44614f0..2ca50d3 100644
--- a/DoomDeathmatch/src/Component/UI/SelectorComponent.cs
+++ b/DoomDeathmatch/src/Component/UI/SelectorComponent.cs
@@ -3,17 +3,44 @@ using Engine.Util;
namespace DoomDeathmatch.Component.UI;
+///
+/// A component that manages selection of UI components using keyboard inputs.
+///
public class SelectorComponent : Engine.Scene.Component.Component
{
+ ///
+ /// Event triggered when a UI component is selected.
+ ///
public event Action? OnSelect;
+ ///
+ /// The list of selectable UI components.
+ ///
public List Children { get; } = [];
+
+ ///
+ /// The key used to navigate to the next item in the list.
+ ///
public KeyboardButtonCode NextKey { get; set; } = KeyboardButtonCode.Down;
+
+ ///
+ /// The key used to navigate to the previous item in the list.
+ ///
public KeyboardButtonCode PrevKey { get; set; } = KeyboardButtonCode.Up;
+
+ ///
+ /// The key used to select the currently selected item.
+ ///
public KeyboardButtonCode SelectKey { get; set; } = KeyboardButtonCode.Space;
+ ///
+ /// The input handler used to check for keyboard input.
+ ///
private readonly IInputHandler _inputHandler = EngineUtil.InputHandler;
+ ///
+ /// The index of the currently selected item.
+ ///
private int _selectedIndex;
public override void Start()
@@ -58,11 +85,17 @@ public class SelectorComponent : Engine.Scene.Component.Component
UpdatePosition();
}
+ ///
+ /// Triggers the event for the currently selected child.
+ ///
private void SelectionChanged()
{
OnSelect?.Invoke(Children[_selectedIndex]);
}
+ ///
+ /// Updates the position of the selector based on the selected child component.
+ ///
private void UpdatePosition()
{
var child = Children[_selectedIndex];
@@ -77,6 +110,10 @@ public class SelectorComponent : Engine.Scene.Component.Component
GameObject.Transform.Size.Y = scale.Y;
}
+ ///
+ /// Selects a UI component when the mouse hovers over it.
+ ///
+ /// The UI component to select.
private void Select(UiComponent parComponent)
{
var index = Children.IndexOf(parComponent);
diff --git a/DoomDeathmatch/src/Component/UI/StackComponent.cs b/DoomDeathmatch/src/Component/UI/StackComponent.cs
index 29e92f8..e2ae5ed 100644
--- a/DoomDeathmatch/src/Component/UI/StackComponent.cs
+++ b/DoomDeathmatch/src/Component/UI/StackComponent.cs
@@ -3,9 +3,19 @@ using OpenTK.Mathematics;
namespace DoomDeathmatch.Component.UI;
+///
+/// A UI container that arranges its child components in a stack, either horizontally or vertically.
+///
public class StackComponent : UiContainerComponent
{
+ ///
+ /// The child components contained in this stack.
+ ///
public List Children { get; } = [];
+
+ ///
+ /// The orientation of the stack, which determines whether the components are arranged horizontally or vertically.
+ ///
public Orientation Orientation { get; set; } = Orientation.Vertical;
public override void Update(double parDeltaTime)
diff --git a/DoomDeathmatch/src/Component/UI/TextAlignComponent.cs b/DoomDeathmatch/src/Component/UI/TextAlignComponent.cs
index 4ef9b4a..eaff416 100644
--- a/DoomDeathmatch/src/Component/UI/TextAlignComponent.cs
+++ b/DoomDeathmatch/src/Component/UI/TextAlignComponent.cs
@@ -4,11 +4,24 @@ using OpenTK.Mathematics;
namespace DoomDeathmatch.Component.UI;
+///
+/// A component that handles text alignment for UI elements that use text rendering.
+///
public class TextAlignComponent : Engine.Scene.Component.Component
{
+ ///
+ /// The alignment of the text within its bounding box.
+ ///
public Align Alignment { get; set; } = Align.Left;
+ ///
+ /// The text renderer used to measure the text size.
+ ///
private TextRenderer _textRenderer = null!;
+
+ ///
+ /// The cached text to avoid unnecessary measurements.
+ ///
private string? _cachedText;
public override void Awake()
@@ -36,6 +49,11 @@ public class TextAlignComponent : Engine.Scene.Component.Component
GameObject.Transform.Translation.Xy = offset;
}
+ ///
+ /// Calculates the offset for the text alignment based on the given size.
+ ///
+ /// The size of the text.
+ /// The calculated offset.
public Vector2 GetOffset(Vector2 parSize)
{
return Alignment switch
diff --git a/DoomDeathmatch/src/Component/UI/TextInputComponent.cs b/DoomDeathmatch/src/Component/UI/TextInputComponent.cs
index 0984de6..fe49f76 100644
--- a/DoomDeathmatch/src/Component/UI/TextInputComponent.cs
+++ b/DoomDeathmatch/src/Component/UI/TextInputComponent.cs
@@ -3,26 +3,60 @@ using Engine.Util;
namespace DoomDeathmatch.Component.UI;
+///
+/// A component that handles text input from the user, such as typing and backspacing.
+///
public class TextInputComponent : Engine.Scene.Component.Component
{
+ ///
+ /// Event triggered when there is new input.
+ ///
public event Action? OnInput;
+ ///
+ /// Indicates whether the input component is active and accepting input.
+ ///
public bool IsActive { get; set; } = false;
+
+ ///
+ /// The current input string the user has typed.
+ ///
public string Input { get; private set; } = "";
+ ///
+ /// The time delay before input is registered after a key is pressed.
+ ///
public float InputDelay
{
get => (float)_inputTimer.TotalTime;
set => _inputTimer.TotalTime = value;
}
+ ///
+ /// The keys that are accepted as input.
+ ///
private readonly KeyboardButtonCode[] _acceptedKeys =
KeyboardButtonCodeHelper.GetAllPrintableKeys().Append(KeyboardButtonCode.Backspace).ToArray();
+ ///
+ /// The input handler used to check for keyboard input.
+ ///
private readonly IInputHandler _inputHandler = EngineUtil.InputHandler;
+
+ ///
+ /// The timer used to delay input.
+ ///
private readonly TickableTimer _inputTimer;
+
+ ///
+ /// The keys that were last pressed.
+ ///
private readonly HashSet _lastKeys = [];
+ ///
+ /// Initializes a new instance of the class with an optional input delay.
+ ///
+ /// The input delay before registering the next key press.
public TextInputComponent(float parInputDelay = 0.2f)
{
_inputTimer = new TickableTimer(parInputDelay) { CurrentTime = 0 };
diff --git a/DoomDeathmatch/src/Component/UI/UiComponent.cs b/DoomDeathmatch/src/Component/UI/UiComponent.cs
index f349c8b..c9ec6bd 100644
--- a/DoomDeathmatch/src/Component/UI/UiComponent.cs
+++ b/DoomDeathmatch/src/Component/UI/UiComponent.cs
@@ -6,16 +6,44 @@ using Math = System.Math;
namespace DoomDeathmatch.Component.UI;
+///
+/// Represents a UI element that can interact with user input.
+///
public class UiComponent : Engine.Scene.Component.Component
{
+ ///
+ /// Invoked when this UI component is clicked.
+ ///
public event Action? OnClick;
+
+ ///
+ /// Invoked when the mouse is hovering over this UI component.
+ ///
public event Action? OnMouseOver;
+ ///
+ /// The parent container of this UI component.
+ ///
public UiContainerComponent? Container { get; set; }
+
+ ///
+ /// The alignment of this component's center within its container.
+ ///
public Anchor Center { get; set; } = Anchor.Center;
+
+ ///
+ /// The anchor point of this component relative to its container.
+ ///
public Anchor Anchor { get; set; } = Anchor.Center;
+
+ ///
+ /// The positional offset of this component relative to its anchor point.
+ ///
public Vector2 Offset { get; set; } = Vector2.Zero;
+ ///
+ /// The input handler used to check for mouse input.
+ ///
private readonly IInputHandler _inputHandler = EngineUtil.InputHandler;
public override void Update(double parDeltaTime)
@@ -26,8 +54,8 @@ public class UiComponent : Engine.Scene.Component.Component
}
var size = GameObject.Transform.Size * GameObject.Transform.Scale;
- GameObject.Transform.Translation.Xy = GetAnchorPosition(Container.GameObject.Transform.Size.Xy, Anchor) + Offset -
- GetAnchorPosition(size.Xy, Center);
+ GameObject.Transform.Translation.Xy = Anchor.GetPosition(Container.GameObject.Transform.Size.Xy) + Offset -
+ Center.GetPosition(size.Xy);
var transformMatrix = GameObject.Transform.FullTransformMatrix;
var actualSize = transformMatrix.ExtractScale();
@@ -46,30 +74,11 @@ public class UiComponent : Engine.Scene.Component.Component
}
}
+ ///
+ /// Manually triggers the click event for this component.
+ ///
public void InvokeClick()
{
OnClick?.Invoke(this);
}
-
- private static Vector2 GetAnchorPosition(Vector2 parSize, Anchor parAnchor)
- {
- return parSize * GetAnchorRatio(parAnchor);
- }
-
- private static Vector2 GetAnchorRatio(Anchor parAnchor)
- {
- return parAnchor switch
- {
- Anchor.TopLeft => new Vector2(-0.5f, 0.5f),
- Anchor.TopCenter => new Vector2(0, 0.5f),
- Anchor.TopRight => new Vector2(0.5f, 0.5f),
- Anchor.CenterLeft => new Vector2(-0.5f, 0),
- Anchor.Center => new Vector2(0, 0),
- Anchor.CenterRight => new Vector2(0.5f, 0),
- Anchor.BottomLeft => new Vector2(-0.5f, -0.5f),
- Anchor.BottomCenter => new Vector2(0, -0.5f),
- Anchor.BottomRight => new Vector2(0.5f, -0.5f),
- _ => throw new ArgumentOutOfRangeException(nameof(parAnchor), parAnchor, null)
- };
- }
}
\ No newline at end of file
diff --git a/DoomDeathmatch/src/Component/UI/UiContainerComponent.cs b/DoomDeathmatch/src/Component/UI/UiContainerComponent.cs
index 31ba59d..bc9e5a1 100644
--- a/DoomDeathmatch/src/Component/UI/UiContainerComponent.cs
+++ b/DoomDeathmatch/src/Component/UI/UiContainerComponent.cs
@@ -5,11 +5,24 @@ using OpenTK.Mathematics;
namespace DoomDeathmatch.Component.UI;
+///
+/// Represents a container for UI components, responsible for handling mouse position and camera interactions.
+///
public class UiContainerComponent : UiComponent
{
+ ///
+ /// The camera used to calculate the mouse position in world space.
+ ///
public Camera? Camera { get; set; }
+
+ ///
+ /// The current mouse position in world coordinates.
+ ///
public Vector3 MousePosition { get; private set; }
+ ///
+ /// The input handler used to check for mouse input.
+ ///
private readonly IInputHandler _inputHandler = EngineUtil.InputHandler;
public override void Update(double parDeltaTime)
diff --git a/DoomDeathmatch/src/Component/Util/BillboardComponent.cs b/DoomDeathmatch/src/Component/Util/BillboardComponent.cs
index 80e7108..de2e32b 100644
--- a/DoomDeathmatch/src/Component/Util/BillboardComponent.cs
+++ b/DoomDeathmatch/src/Component/Util/BillboardComponent.cs
@@ -3,9 +3,19 @@ using OpenTK.Mathematics;
namespace DoomDeathmatch.Component.Util;
+///
+/// A component that aligns the orientation of an object to always face a target, similar to a billboard.
+///
public class BillboardComponent : Engine.Scene.Component.Component
{
+ ///
+ /// The target transform that the object will face.
+ ///
public Transform? Target { get; set; }
+
+ ///
+ /// The upward direction used as a reference for recalculating orientation.
+ ///
public Vector3 Up { get; set; } = Vector3.UnitZ;
public override void Update(double parDeltaTime)
@@ -17,15 +27,28 @@ public class BillboardComponent : Engine.Scene.Component.Component
var targetPosition = Target.GetFullTranslation();
var currentPosition = GameObject.Transform.GetFullTranslation();
+ var rotationMatrix = CalculateRotationMatrix(currentPosition, targetPosition, Up);
- var forward = targetPosition - currentPosition;
- forward -= Vector3.Dot(forward, Up) * Up;
+ GameObject.Transform.Rotation = Quaternion.FromMatrix(rotationMatrix);
+ }
+
+ ///
+ /// Calculates the rotation matrix required to align the object to face the target.
+ ///
+ /// The current position of the object.
+ /// The target position the object should face.
+ /// The upward direction used for orientation adjustment.
+ /// A representing the required rotation.
+ private static Matrix3 CalculateRotationMatrix(Vector3 parCurrentPosition, Vector3 parTargetPosition, Vector3 parUp)
+ {
+ var forward = parTargetPosition - parCurrentPosition;
+ forward -= Vector3.Dot(forward, parUp) * parUp;
if (forward.LengthSquared > 0)
{
forward.Normalize();
}
- var right = Vector3.Cross(Up, forward);
+ var right = Vector3.Cross(parUp, forward);
if (right.LengthSquared > 0)
{
right.Normalize();
@@ -39,6 +62,6 @@ public class BillboardComponent : Engine.Scene.Component.Component
right.Z, recalculatedUp.Z, forward.Z
);
- GameObject.Transform.Rotation = Quaternion.FromMatrix(rotationMatrix);
+ return rotationMatrix;
}
}
\ No newline at end of file
diff --git a/DoomDeathmatch/src/Component/Util/CopySizeComponent.cs b/DoomDeathmatch/src/Component/Util/CopySizeComponent.cs
index 7313929..5bd1e47 100644
--- a/DoomDeathmatch/src/Component/Util/CopySizeComponent.cs
+++ b/DoomDeathmatch/src/Component/Util/CopySizeComponent.cs
@@ -3,9 +3,19 @@ using OpenTK.Mathematics;
namespace DoomDeathmatch.Component.Util;
+///
+/// A component that synchronizes the size of an object with a target object's size, applying a multiplier.
+///
public class CopySizeComponent : Engine.Scene.Component.Component
{
+ ///
+ /// The target transform whose size is copied.
+ ///
public Transform? Target { get; set; }
+
+ ///
+ /// The multiplier applied to the target's size when copying.
+ ///
public Vector3 Multiplier { get; set; } = Vector3.One;
public override void Update(double parDeltaTime)
diff --git a/DoomDeathmatch/src/Component/Util/FireballComponent.cs b/DoomDeathmatch/src/Component/Util/FireballComponent.cs
index d7e9129..22eeabb 100644
--- a/DoomDeathmatch/src/Component/Util/FireballComponent.cs
+++ b/DoomDeathmatch/src/Component/Util/FireballComponent.cs
@@ -4,8 +4,14 @@ using Engine.Util;
namespace DoomDeathmatch.Component.Util;
+///
+/// Represents a fireball that deals damage on collision.
+///
public class FireballComponent : Engine.Scene.Component.Component
{
+ ///
+ /// The amount of damage the fireball inflicts on collision.
+ ///
public float Damage { get; set; }
public override void Awake()
@@ -17,6 +23,10 @@ public class FireballComponent : Engine.Scene.Component.Component
collider.OnCollision += OnCollision;
}
+ ///
+ /// Handles collision logic, dealing damage to colliding objects.
+ ///
+ /// The collider of the object this fireball collided with.
private void OnCollision(AABBColliderComponent parCollider)
{
var healthController = parCollider.GameObject.GetComponent();
diff --git a/DoomDeathmatch/src/Component/Util/PlayerMovementComponent.cs b/DoomDeathmatch/src/Component/Util/PlayerMovementComponent.cs
index 77e2bdb..100c107 100644
--- a/DoomDeathmatch/src/Component/Util/PlayerMovementComponent.cs
+++ b/DoomDeathmatch/src/Component/Util/PlayerMovementComponent.cs
@@ -5,12 +5,24 @@ using OpenTK.Mathematics;
namespace DoomDeathmatch.Component.Util;
+///
+/// Handles player movement based on input and applies rotation to the player object.
+///
public class PlayerMovementComponent : Engine.Scene.Component.Component
{
+ ///
+ /// The speed at which the player rotates.
+ ///
public float RotationSpeed { get; set; } = 110.0f;
+ ///
+ /// Handles input from the player.
+ ///
private readonly IInputHandler _inputHandler = EngineUtil.InputHandler;
+ ///
+ /// Controls the movement logic of the player.
+ ///
private MovementController _movementController = null!;
public override void Awake()
diff --git a/DoomDeathmatch/src/Scene/Play/PlayScene.cs b/DoomDeathmatch/src/Scene/Play/PlayScene.cs
index e208c26..15d26d1 100644
--- a/DoomDeathmatch/src/Scene/Play/PlayScene.cs
+++ b/DoomDeathmatch/src/Scene/Play/PlayScene.cs
@@ -57,7 +57,7 @@ public static class PlayScene
var gameControllerObject = GameObjectUtil.CreateGameObject(scene, [
new GameController(menuController),
- new TimerController(),
+ new TimerController(5 * 60),
plaTimerView,
new ScoreController(),
@@ -88,11 +88,10 @@ public static class PlayScene
var monsterSpawnPoints = MeshToSpawnPoints(
EngineUtil.AssetResourceManager.Load($"map/{parMapName}/monster_spawners.obj"));
- var valuableSpawnPoints = MeshToSpawnPoints(
- EngineUtil.AssetResourceManager.Load($"map/{parMapName}/valuable_spawners.obj"));
-
parScene.AddChild(mapObject, collidersObject);
+ #region Monster Objects
+
var monsterVector3ValueProvider =
new RandomListValueProvider(monsterSpawnPoints.Select(ConstValueProvider.Create));
@@ -114,6 +113,12 @@ public static class PlayScene
parScene.AddChild(parGameControllerObject, monsterSpawnerObject);
+ #endregion
+
+ #region Consumable Objects
+
+ var valuableSpawnPoints = MeshToSpawnPoints(
+ EngineUtil.AssetResourceManager.Load($"map/{parMapName}/valuable_spawners.obj"));
var consumableVector3ValueProvider =
new RandomListValueProvider(valuableSpawnPoints.Select(ConstValueProvider.Create));
@@ -157,6 +162,8 @@ public static class PlayScene
parScene.AddChild(parGameControllerObject, consumableSpawnerObject);
+ #endregion
+
return mapObject;
}
diff --git a/DoomDeathmatch/src/Script/AnimationPlayer.cs b/DoomDeathmatch/src/Script/AnimationPlayer.cs
index 754c62c..c4c3f64 100644
--- a/DoomDeathmatch/src/Script/AnimationPlayer.cs
+++ b/DoomDeathmatch/src/Script/AnimationPlayer.cs
@@ -3,17 +3,55 @@ using Engine.Util;
namespace DoomDeathmatch.Script;
-public class AnimationPlayer(float parInterval) : IUpdate
+///
+/// Handles the playback of animations consisting of frames of type .
+///
+/// The type of the animation frames.
+public class AnimationPlayer : IUpdate
{
+ ///
+ /// Occurs when the animation finishes playing.
+ ///
public event Action? OnFinish;
+
+ ///
+ /// Occurs when the animation advances to a new frame.
+ ///
public event Action? OnFrameChanged;
+ ///
+ /// Indicates whether the animation is currently playing.
+ ///
public bool IsPlaying { get; private set; }
+
+ ///
+ /// The list of frames in the animation.
+ ///
public List Frames { get; init; } = [];
+
+ ///
+ /// The index of the next frame to be displayed.
+ ///
public int NextFrame { get; private set; }
- private readonly TickableTimer _timer = new(parInterval);
+ ///
+ /// The timer used to control frame intervals.
+ ///
+ private readonly TickableTimer _timer;
+ ///
+ /// Initializes a new instance of the class with a specified frame interval.
+ ///
+ /// The total time in seconds for whole animation.
+ public AnimationPlayer(float parInterval)
+ {
+ _timer = new TickableTimer(parInterval);
+ }
+
+ ///
+ /// Updates the animation's playback state based on the elapsed time.
+ ///
+ /// The time in seconds since the last update.
public void Update(double parDeltaTime)
{
if (!IsPlaying)
@@ -37,12 +75,18 @@ public class AnimationPlayer(float parInterval) : IUpdate
}
}
+ ///
+ /// Starts the animation playback from the beginning.
+ ///
public void Start()
{
Reset();
IsPlaying = true;
}
+ ///
+ /// Resets the animation to its initial state.
+ ///
public void Reset()
{
_timer.Reset();
diff --git a/DoomDeathmatch/src/Script/Collision/AABBCollider.cs b/DoomDeathmatch/src/Script/Collision/AABBCollider.cs
index e72390c..3b2b011 100644
--- a/DoomDeathmatch/src/Script/Collision/AABBCollider.cs
+++ b/DoomDeathmatch/src/Script/Collision/AABBCollider.cs
@@ -2,14 +2,36 @@
namespace DoomDeathmatch.Script.Collision;
+///
+/// Represents an Axis-Aligned Bounding Box (AABB) collider for 3D collision detection.
+///
public class AABBCollider
{
+ ///
+ /// The position of the collider's center in 3D space.
+ ///
public Vector3 Position { get; set; }
+
+ ///
+ /// The size (width, height, depth) of the collider.
+ ///
public Vector3 Size { get; set; }
+ ///
+ /// The minimum point (corner) of the collider in 3D space.
+ ///
public Vector3 Min => Position - (Size / 2);
+
+ ///
+ /// The maximum point (corner) of the collider in 3D space.
+ ///
public Vector3 Max => Position + (Size / 2);
+ ///
+ /// Checks if this collider intersects with another AABB collider.
+ ///
+ /// The other collider to check for intersection.
+ /// if the colliders intersect; otherwise, .
public bool Intersects(AABBCollider parCollider)
{
var max = Max;
@@ -21,6 +43,14 @@ public class AABBCollider
max.Z >= otherMin.Z && min.Z <= otherMax.Z;
}
+ ///
+ /// Calculates the collision normal between this collider and another collider.
+ ///
+ /// The other collider involved in the collision.
+ ///
+ /// A representing the normal of the collision surface.
+ /// This indicates the direction of the collision resolution.
+ ///
public Vector3 GetCollisionNormal(AABBCollider parOther)
{
var normal = Vector3.Zero;
diff --git a/DoomDeathmatch/src/Script/Collision/RaycastResult.cs b/DoomDeathmatch/src/Script/Collision/RaycastResult.cs
index 437d38f..2e9dc8b 100644
--- a/DoomDeathmatch/src/Script/Collision/RaycastResult.cs
+++ b/DoomDeathmatch/src/Script/Collision/RaycastResult.cs
@@ -3,11 +3,28 @@ using OpenTK.Mathematics;
namespace DoomDeathmatch.Script.Collision;
+///
+/// Represents the result of a raycast in 3D space.
+///
public class RaycastResult
{
+ ///
+ /// The distance from the ray's origin to the hit point.
+ ///
public float Distance { get; init; }
+
+ ///
+ /// The point in 3D space where the ray hit an object.
+ ///
public Vector3 HitPoint { get; init; }
+
+ ///
+ /// The normal vector at the surface of the hit object.
+ ///
public Vector3 Normal { get; init; }
+ ///
+ /// The game object that was hit by the ray.
+ ///
public GameObject HitObject { get; init; }
}
\ No newline at end of file
diff --git a/DoomDeathmatch/src/Script/Condition/ICondition.cs b/DoomDeathmatch/src/Script/Condition/ICondition.cs
index 93e0e5d..a9b81ef 100644
--- a/DoomDeathmatch/src/Script/Condition/ICondition.cs
+++ b/DoomDeathmatch/src/Script/Condition/ICondition.cs
@@ -2,11 +2,23 @@
namespace DoomDeathmatch.Script.Condition;
+///
+/// Represents a condition that can be updated and triggers an event when it becomes true.
+///
public interface ICondition : IUpdate
{
+ ///
+ /// Occurs when the condition evaluates to true.
+ ///
public event Action? OnTrue;
+ ///
+ /// Indicates whether the condition is currently true.
+ ///
public bool IsTrue { get; }
+ ///
+ /// Resets the condition to its initial state.
+ ///
public void Reset();
}
\ No newline at end of file
diff --git a/DoomDeathmatch/src/Script/Condition/TickableTimerCondition.cs b/DoomDeathmatch/src/Script/Condition/TickableTimerCondition.cs
index 6ca051f..6a54999 100644
--- a/DoomDeathmatch/src/Script/Condition/TickableTimerCondition.cs
+++ b/DoomDeathmatch/src/Script/Condition/TickableTimerCondition.cs
@@ -2,25 +2,49 @@
namespace DoomDeathmatch.Script.Condition;
+///
+/// Represents a condition based on a timer that can be updated over time.
+/// The condition becomes true when the timer finishes.
+///
public class TickableTimerCondition : ICondition
{
+ ///
+ /// Occurs when the timer finishes, causing the condition to become true.
+ ///
public event Action? OnTrue;
+ ///
+ /// Indicates whether the timer has finished, making the condition true.
+ ///
public bool IsTrue => _timer.IsFinished;
+ ///
+ /// The timer used to evaluate the condition's state.
+ ///
private readonly TickableTimer _timer;
+ ///
+ /// Initializes a new instance of the class with a specified interval.
+ ///
+ /// The interval in seconds for the timer.
public TickableTimerCondition(float parInterval)
{
_timer = new TickableTimer(parInterval);
_timer.OnFinished += () => OnTrue?.Invoke();
}
+ ///
+ /// Updates the timer with the elapsed time, progressing the condition's state.
+ ///
+ /// The time in seconds since the last update.
public void Update(double parDeltaTime)
{
_timer.Update(parDeltaTime);
}
+ ///
+ /// Resets the timer and the condition to their initial state.
+ ///
public void Reset()
{
_timer.Reset();
diff --git a/DoomDeathmatch/src/Script/Consumable/HealthPackConsumable.cs b/DoomDeathmatch/src/Script/Consumable/HealthPackConsumable.cs
index f3c6b79..b34f6da 100644
--- a/DoomDeathmatch/src/Script/Consumable/HealthPackConsumable.cs
+++ b/DoomDeathmatch/src/Script/Consumable/HealthPackConsumable.cs
@@ -2,12 +2,32 @@
namespace DoomDeathmatch.Script.Consumable;
-public class HealthPackConsumable(float parHealth) : IConsumable
+///
+/// Represents a health pack consumable that restores health to the player.
+///
+/// The amount of health restored by the consumable.
+public class HealthPackConsumable : IConsumable
{
+ ///
public string Icon => "texture/health_pack.png";
+ ///
+ /// The amount of health restored by the consumable.
+ ///
+ private readonly float _health;
+
+ ///
+ /// Initializes a new instance of the class with a specified health restoration value.
+ ///
+ /// The amount of health this consumable restores.
+ public HealthPackConsumable(float parHealth)
+ {
+ _health = parHealth;
+ }
+
+ ///
public void Consume(PlayerController parPlayerController)
{
- parPlayerController.HealthController.Heal(parHealth);
+ parPlayerController.HealthController.Heal(_health);
}
}
\ No newline at end of file
diff --git a/DoomDeathmatch/src/Script/Consumable/IConsumable.cs b/DoomDeathmatch/src/Script/Consumable/IConsumable.cs
index 442e11e..40365ad 100644
--- a/DoomDeathmatch/src/Script/Consumable/IConsumable.cs
+++ b/DoomDeathmatch/src/Script/Consumable/IConsumable.cs
@@ -2,9 +2,21 @@
namespace DoomDeathmatch.Script.Consumable;
+///
+/// Represents a consumable item in the game.
+/// Consumables can be used by a player to apply specific effects, such as healing or adding a weapon.
+///
public interface IConsumable
{
+ ///
+ /// The icon path associated with the consumable.
+ /// Used for displaying the consumable in the user interface.
+ ///
public string Icon { get; }
+ ///
+ /// Consumes the item and applies its effect to the specified player.
+ ///
+ /// The player controller to apply the consumable effect to.
public void Consume(PlayerController parPlayerController);
}
\ No newline at end of file
diff --git a/DoomDeathmatch/src/Script/Consumable/WeaponConsumable.cs b/DoomDeathmatch/src/Script/Consumable/WeaponConsumable.cs
index 98893f9..e9b118e 100644
--- a/DoomDeathmatch/src/Script/Consumable/WeaponConsumable.cs
+++ b/DoomDeathmatch/src/Script/Consumable/WeaponConsumable.cs
@@ -3,12 +3,31 @@ using DoomDeathmatch.Script.Model.Weapon;
namespace DoomDeathmatch.Script.Consumable;
-public class WeaponConsumable(WeaponData parWeaponData) : IConsumable
+///
+/// Represents a weapon consumable that grants weapon or reloads ammo to the player.
+///
+public class WeaponConsumable : IConsumable
{
- public string Icon => parWeaponData.IdleTexture;
+ ///
+ public string Icon => _weaponData.IdleTexture;
+ ///
+ /// The weapon data associated with this consumable.
+ ///
+ private readonly WeaponData _weaponData;
+
+ ///
+ /// Initializes a new instance of the class with the specified weapon data.
+ ///
+ /// The weapon data associated with this consumable.
+ public WeaponConsumable(WeaponData parWeaponData)
+ {
+ _weaponData = parWeaponData;
+ }
+
+ ///
public void Consume(PlayerController parPlayerController)
{
- parPlayerController.WeaponController.AddOrMergeWeapon(parWeaponData);
+ parPlayerController.WeaponController.AddOrMergeWeapon(_weaponData);
}
}
\ No newline at end of file
diff --git a/DoomDeathmatch/src/Script/MVC/IView.cs b/DoomDeathmatch/src/Script/MVC/IView.cs
new file mode 100644
index 0000000..a4b6851
--- /dev/null
+++ b/DoomDeathmatch/src/Script/MVC/IView.cs
@@ -0,0 +1,14 @@
+namespace DoomDeathmatch.Script.MVC;
+
+///
+/// Interface for view components.
+///
+/// The type of the model to display.
+public interface IView
+{
+ ///
+ /// Updates the view based on the specified model.
+ ///
+ /// The model to display.
+ public void UpdateView(T parModel);
+}
\ No newline at end of file
diff --git a/DoomDeathmatch/src/Script/Model/Enemy/Attack/AttackBehavior.cs b/DoomDeathmatch/src/Script/Model/Enemy/Attack/AttackBehavior.cs
index 8e9d173..7819c1d 100644
--- a/DoomDeathmatch/src/Script/Model/Enemy/Attack/AttackBehavior.cs
+++ b/DoomDeathmatch/src/Script/Model/Enemy/Attack/AttackBehavior.cs
@@ -3,10 +3,36 @@ using DoomDeathmatch.Component.MVC.Health;
namespace DoomDeathmatch.Script.Model.Enemy.Attack;
-public abstract class AttackBehavior(EnemyController parEnemyController, HealthController parHealthController)
+///
+/// Represents the base class for defining enemy attack behaviors.
+///
+public abstract class AttackBehavior
{
- protected readonly EnemyController _enemyController = parEnemyController;
- protected readonly HealthController _healthController = parHealthController;
+ ///
+ /// The controller for the enemy performing the attack.
+ ///
+ protected readonly EnemyController _enemyController;
+ ///
+ /// The controller for the health of the target being attacked.
+ ///
+ protected readonly HealthController _healthController;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The enemy controller.
+ /// The health controller of the target.
+ protected AttackBehavior(EnemyController parEnemyController, HealthController parHealthController)
+ {
+ _enemyController = parEnemyController;
+ _healthController = parHealthController;
+ }
+
+ ///
+ /// Performs the attack behavior.
+ ///
+ /// The time elapsed since the last update.
+ /// True if the attack was successful; otherwise, false.
public abstract bool Attack(double parDeltaTime);
}
\ No newline at end of file
diff --git a/DoomDeathmatch/src/Script/Model/Enemy/Attack/CloseContinuousAttackBehavior.cs b/DoomDeathmatch/src/Script/Model/Enemy/Attack/CloseContinuousAttackBehavior.cs
index 932822c..2dc1487 100644
--- a/DoomDeathmatch/src/Script/Model/Enemy/Attack/CloseContinuousAttackBehavior.cs
+++ b/DoomDeathmatch/src/Script/Model/Enemy/Attack/CloseContinuousAttackBehavior.cs
@@ -3,22 +3,47 @@ using DoomDeathmatch.Component.MVC.Health;
namespace DoomDeathmatch.Script.Model.Enemy.Attack;
-public class CloseContinuousAttackBehavior(
- EnemyController parEnemyController,
- HealthController parHealthController,
- float parRadius,
- float parDamage)
- : AttackBehavior(parEnemyController, parHealthController)
+///
+/// Represents a behavior where the enemy continuously attacks when in close proximity.
+///
+public class CloseContinuousAttackBehavior : AttackBehavior
{
+ ///
+ /// The attack radius within which the attack is triggered.
+ ///
+ private readonly float _radius;
+
+ ///
+ /// The amount of damage dealt per second.
+ ///
+ private readonly float _damage;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The enemy controller.
+ /// The health controller of the target.
+ /// The attack radius.
+ /// The damage dealt per second.
+ public CloseContinuousAttackBehavior(EnemyController parEnemyController,
+ HealthController parHealthController,
+ float parRadius,
+ float parDamage) : base(parEnemyController, parHealthController)
+ {
+ _radius = parRadius;
+ _damage = parDamage;
+ }
+
+ ///
public override bool Attack(double parDeltaTime)
{
var distanceSquared =
(_enemyController.GameObject.Transform.Translation - _healthController.GameObject.Transform.Translation)
.LengthSquared;
- if (distanceSquared <= parRadius * parRadius)
+ if (distanceSquared <= _radius * _radius)
{
- _healthController.TakeDamage(parDamage * (float)parDeltaTime);
+ _healthController.TakeDamage(_damage * (float)parDeltaTime);
return true;
}
diff --git a/DoomDeathmatch/src/Script/Model/Enemy/Attack/CloseCooldownAttackBehavior.cs b/DoomDeathmatch/src/Script/Model/Enemy/Attack/CloseCooldownAttackBehavior.cs
index cded27a..88e15e8 100644
--- a/DoomDeathmatch/src/Script/Model/Enemy/Attack/CloseCooldownAttackBehavior.cs
+++ b/DoomDeathmatch/src/Script/Model/Enemy/Attack/CloseCooldownAttackBehavior.cs
@@ -3,26 +3,53 @@ using DoomDeathmatch.Component.MVC.Health;
namespace DoomDeathmatch.Script.Model.Enemy.Attack;
-public class CloseCooldownAttackBehavior(
- EnemyController parEnemyController,
- HealthController parHealthController,
- float parRadius,
- float parCooldown,
- float parDamage)
- : CooldownAttackBehavior(parEnemyController, parHealthController, parCooldown)
+///
+/// Represents a behavior where the enemy performs a cooldown-based close-range attack.
+///
+public class CloseCooldownAttackBehavior : CooldownAttackBehavior
{
+ ///
+ /// The attack radius within which the attack is triggered.
+ ///
+ private readonly float _radius;
+
+ ///
+ /// The damage dealt by the attack.
+ ///
+ private readonly float _damage;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The enemy controller.
+ /// The health controller of the target.
+ /// The attack radius.
+ /// The cooldown duration.
+ /// The damage dealt by the attack.
+ public CloseCooldownAttackBehavior(EnemyController parEnemyController,
+ HealthController parHealthController,
+ float parRadius,
+ float parCooldown,
+ float parDamage) : base(parEnemyController, parHealthController, parCooldown)
+ {
+ _radius = parRadius;
+ _damage = parDamage;
+ }
+
+ ///
protected override bool CanAttack()
{
var distanceSquared =
(_enemyController.GameObject.Transform.Translation - _healthController.GameObject.Transform.Translation)
.LengthSquared;
- return distanceSquared <= parRadius * parRadius;
+ return distanceSquared <= _radius * _radius;
}
+ ///
protected override bool ActivateAttack()
{
- _healthController.TakeDamage(parDamage);
+ _healthController.TakeDamage(_damage);
return true;
}
diff --git a/DoomDeathmatch/src/Script/Model/Enemy/Attack/CompositeAttackBehavior.cs b/DoomDeathmatch/src/Script/Model/Enemy/Attack/CompositeAttackBehavior.cs
index 3a8d6ec..093fca6 100644
--- a/DoomDeathmatch/src/Script/Model/Enemy/Attack/CompositeAttackBehavior.cs
+++ b/DoomDeathmatch/src/Script/Model/Enemy/Attack/CompositeAttackBehavior.cs
@@ -3,17 +3,35 @@ using DoomDeathmatch.Component.MVC.Health;
namespace DoomDeathmatch.Script.Model.Enemy.Attack;
-public class CompositeAttackBehavior(
- EnemyController parEnemyController,
- HealthController parHealthController,
- List parBehaviors)
- : AttackBehavior(parEnemyController, parHealthController)
+///
+/// Represents a composite attack behavior combining multiple attack behaviors.
+///
+public class CompositeAttackBehavior : AttackBehavior
{
+ ///
+ /// A collection of individual attack behaviors.
+ ///
+ private readonly List _behaviors;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The enemy controller.
+ /// The health controller of the target.
+ /// The collection of attack behaviors.
+ public CompositeAttackBehavior(EnemyController parEnemyController,
+ HealthController parHealthController,
+ IEnumerable parBehaviors) : base(parEnemyController, parHealthController)
+ {
+ _behaviors = parBehaviors.ToList();
+ }
+
+ ///
public override bool Attack(double parDeltaTime)
{
var result = false;
- foreach (var behavior in parBehaviors)
+ foreach (var behavior in _behaviors)
{
result |= behavior.Attack(parDeltaTime);
}
diff --git a/DoomDeathmatch/src/Script/Model/Enemy/Attack/CooldownAttackBehavior.cs b/DoomDeathmatch/src/Script/Model/Enemy/Attack/CooldownAttackBehavior.cs
index b803b09..1cbfffe 100644
--- a/DoomDeathmatch/src/Script/Model/Enemy/Attack/CooldownAttackBehavior.cs
+++ b/DoomDeathmatch/src/Script/Model/Enemy/Attack/CooldownAttackBehavior.cs
@@ -4,14 +4,30 @@ using Engine.Util;
namespace DoomDeathmatch.Script.Model.Enemy.Attack;
-public abstract class CooldownAttackBehavior(
- EnemyController parEnemyController,
- HealthController parHealthController,
- float parCooldown)
- : AttackBehavior(parEnemyController, parHealthController)
+///
+/// Represents a base class for attacks with cooldown functionality.
+///
+public abstract class CooldownAttackBehavior : AttackBehavior
{
- private readonly TickableTimer _tickableTimer = new(parCooldown);
+ ///
+ /// Timer that tracks the cooldown duration between attacks.
+ ///
+ private readonly TickableTimer _tickableTimer;
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The enemy controller.
+ /// The health controller of the target.
+ /// The cooldown duration.
+ protected CooldownAttackBehavior(EnemyController parEnemyController,
+ HealthController parHealthController,
+ float parCooldown) : base(parEnemyController, parHealthController)
+ {
+ _tickableTimer = new TickableTimer(parCooldown);
+ }
+
+ ///
public sealed override bool Attack(double parDeltaTime)
{
_tickableTimer.Update(parDeltaTime);
@@ -33,6 +49,15 @@ public abstract class CooldownAttackBehavior(
return false;
}
+ ///
+ /// Determines whether the attack can be performed.
+ ///
+ /// True if the attack can be performed; otherwise, false.
protected abstract bool CanAttack();
+
+ ///
+ /// Executes the attack logic.
+ ///
+ /// True if the attack was successful; otherwise, false.
protected abstract bool ActivateAttack();
}
\ No newline at end of file
diff --git a/DoomDeathmatch/src/Script/Model/Enemy/Attack/FuncAttackBehaviorCreator.cs b/DoomDeathmatch/src/Script/Model/Enemy/Attack/FuncAttackBehaviorCreator.cs
index 26de5b6..27c981c 100644
--- a/DoomDeathmatch/src/Script/Model/Enemy/Attack/FuncAttackBehaviorCreator.cs
+++ b/DoomDeathmatch/src/Script/Model/Enemy/Attack/FuncAttackBehaviorCreator.cs
@@ -3,11 +3,31 @@ using DoomDeathmatch.Component.MVC.Health;
namespace DoomDeathmatch.Script.Model.Enemy.Attack;
-public class FuncAttackBehaviorCreator(Func parFunc)
- : IAttackBehaviorCreator
+///
+/// A creator that uses a function to generate instances of .
+///
+public class FuncAttackBehaviorCreator : IAttackBehaviorCreator
{
+ ///
+ /// The function used to create instances.
+ ///
+ private readonly Func _func;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// A function that takes an and
+ /// and returns a new instance of .
+ ///
+ public FuncAttackBehaviorCreator(Func parFunc)
+ {
+ _func = parFunc;
+ }
+
+ ///
public AttackBehavior Create(EnemyController parEnemyController, HealthController parHealthController)
{
- return parFunc(parEnemyController, parHealthController);
+ return _func(parEnemyController, parHealthController);
}
}
\ No newline at end of file
diff --git a/DoomDeathmatch/src/Script/Model/Enemy/Attack/IAttackBehaviorCreator.cs b/DoomDeathmatch/src/Script/Model/Enemy/Attack/IAttackBehaviorCreator.cs
index 81e96f2..cace4aa 100644
--- a/DoomDeathmatch/src/Script/Model/Enemy/Attack/IAttackBehaviorCreator.cs
+++ b/DoomDeathmatch/src/Script/Model/Enemy/Attack/IAttackBehaviorCreator.cs
@@ -3,7 +3,16 @@ using DoomDeathmatch.Component.MVC.Health;
namespace DoomDeathmatch.Script.Model.Enemy.Attack;
+///
+/// Interface for creating instances of .
+///
public interface IAttackBehaviorCreator
{
+ ///
+ /// Creates a new instance of an .
+ ///
+ /// The enemy controller for the behavior.
+ /// The health controller for the target.
+ /// An instance of .
public AttackBehavior Create(EnemyController parEnemyController, HealthController parHealthController);
}
\ No newline at end of file
diff --git a/DoomDeathmatch/src/Script/Model/Enemy/Attack/ObjectSpawnAttackBehavior.cs b/DoomDeathmatch/src/Script/Model/Enemy/Attack/ObjectSpawnAttackBehavior.cs
index cc93840..4e22678 100644
--- a/DoomDeathmatch/src/Script/Model/Enemy/Attack/ObjectSpawnAttackBehavior.cs
+++ b/DoomDeathmatch/src/Script/Model/Enemy/Attack/ObjectSpawnAttackBehavior.cs
@@ -5,22 +5,42 @@ using Engine.Util;
namespace DoomDeathmatch.Script.Model.Enemy.Attack;
-public class ObjectSpawnAttackBehavior(
- EnemyController parEnemyController,
- HealthController parHealthController,
- float parCooldown,
- Func parObjectSpawnFunc
-)
- : CooldownAttackBehavior(parEnemyController, parHealthController, parCooldown)
+///
+/// Represents a behavior where an object is spawned as part of the attack.
+///
+public class ObjectSpawnAttackBehavior : CooldownAttackBehavior
{
+ ///
+ /// The function used to spawn an object based on the enemy and target controllers.
+ ///
+ private readonly Func _objectSpawnFunc;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The enemy controller.
+ /// The health controller of the target.
+ /// The cooldown duration between spawns.
+ /// The function used to create the spawned object.
+ public ObjectSpawnAttackBehavior(EnemyController parEnemyController,
+ HealthController parHealthController,
+ float parCooldown,
+ Func parObjectSpawnFunc) : base(parEnemyController,
+ parHealthController, parCooldown)
+ {
+ _objectSpawnFunc = parObjectSpawnFunc;
+ }
+
+ ///
protected override bool CanAttack()
{
return true;
}
+ ///
protected override bool ActivateAttack()
{
- var enemyObject = parObjectSpawnFunc(_enemyController, _healthController);
+ var enemyObject = _objectSpawnFunc(_enemyController, _healthController);
EngineUtil.SceneManager.CurrentScene!.Add(enemyObject);
return true;
diff --git a/DoomDeathmatch/src/Script/Model/Enemy/EnemyData.cs b/DoomDeathmatch/src/Script/Model/Enemy/EnemyData.cs
index 1f7bf55..466391e 100644
--- a/DoomDeathmatch/src/Script/Model/Enemy/EnemyData.cs
+++ b/DoomDeathmatch/src/Script/Model/Enemy/EnemyData.cs
@@ -6,8 +6,14 @@ using OpenTK.Mathematics;
namespace DoomDeathmatch.Script.Model.Enemy;
+///
+/// Represents data associated with an enemy type, including its stats, behavior, and appearance.
+///
public class EnemyData
{
+ ///
+ /// Data for the "Demon" enemy type.
+ ///
public static EnemyData Demon =>
new()
{
@@ -24,6 +30,9 @@ public class EnemyData
)
};
+ ///
+ /// Data for the "Imp" enemy type.
+ ///
public static EnemyData Imp =>
new()
{
@@ -61,25 +70,58 @@ public class EnemyData
)
};
+ ///
+ /// Unique identifier for the enemy type.
+ ///
public string Id { get; private init; } = "";
+
+ ///
+ /// Display name for the enemy type.
+ ///
public string Name { get; private init; } = "";
+ ///
+ /// Path to the texture file used to render the enemy.
+ ///
public string Texture { get; private init; } = "";
+ ///
+ /// The base health of the enemy.
+ ///
public float BaseHealth { get; private init; }
+
+ ///
+ /// The base score awarded for defeating this enemy.
+ ///
public int BaseScore { get; private init; }
+
+ ///
+ /// The base speed of the enemy.
+ ///
public float BaseSpeed { get; private init; }
+ ///
+ /// The movement behavior defining how the enemy moves.
+ ///
public IMovementBehavior MovementBehavior { get; private init; }
+
+ ///
+ /// The creator for the enemy's attack behavior.
+ ///
public IAttackBehaviorCreator AttackBehaviorCreator { get; private init; }
+ ///
+ /// Private constructor to prevent direct instantiation. Use the predefined static properties instead.
+ ///
private EnemyData() { }
+ ///
public override bool Equals(object? parObj)
{
return parObj is EnemyData enemyData && Id == enemyData.Id;
}
+ ///
public override int GetHashCode()
{
return HashCode.Combine(Id);
diff --git a/DoomDeathmatch/src/Script/Model/Enemy/Movement/FollowPlayerMovementBehavior.cs b/DoomDeathmatch/src/Script/Model/Enemy/Movement/FollowPlayerMovementBehavior.cs
index 74bb2f2..d3374ca 100644
--- a/DoomDeathmatch/src/Script/Model/Enemy/Movement/FollowPlayerMovementBehavior.cs
+++ b/DoomDeathmatch/src/Script/Model/Enemy/Movement/FollowPlayerMovementBehavior.cs
@@ -2,11 +2,34 @@
namespace DoomDeathmatch.Script.Model.Enemy.Movement;
-public class FollowPlayerMovementBehavior(float parRadius) : IMovementBehavior
+///
+/// Movement behavior where the enemy follows the player while maintaining a specific radius.
+///
+public class FollowPlayerMovementBehavior : IMovementBehavior
{
+ ///
+ /// The radius to maintain between the enemy and the player.
+ ///
+ private readonly float _radius;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The radius to maintain between the enemy and the player.
+ public FollowPlayerMovementBehavior(float parRadius)
+ {
+ _radius = parRadius;
+ }
+
+ ///
+ /// Calculates the next position for the enemy, keeping it at the specified radius from the player.
+ ///
+ /// The current position of the enemy.
+ /// The current position of the player.
+ /// The next position of the enemy, maintaining the specified radius from the player.
public Vector3 GetNextPosition(Vector3 parPosition, Vector3 parPlayerPosition)
{
var direction = (parPosition - parPlayerPosition).Normalized();
- return parPlayerPosition + (parRadius * direction);
+ return parPlayerPosition + (_radius * direction);
}
}
\ No newline at end of file
diff --git a/DoomDeathmatch/src/Script/Model/Enemy/Movement/IMovementBehavior.cs b/DoomDeathmatch/src/Script/Model/Enemy/Movement/IMovementBehavior.cs
index 41bbde1..c75fd7c 100644
--- a/DoomDeathmatch/src/Script/Model/Enemy/Movement/IMovementBehavior.cs
+++ b/DoomDeathmatch/src/Script/Model/Enemy/Movement/IMovementBehavior.cs
@@ -2,7 +2,16 @@
namespace DoomDeathmatch.Script.Model.Enemy.Movement;
+///
+/// Interface for defining enemy movement behavior.
+///
public interface IMovementBehavior
{
+ ///
+ /// Calculates the next position for the enemy based on the current position and the player's position.
+ ///
+ /// The current position of the enemy.
+ /// The current position of the player.
+ /// The next position of the enemy.
public Vector3 GetNextPosition(Vector3 parPosition, Vector3 parPlayerPosition);
}
\ No newline at end of file
diff --git a/DoomDeathmatch/src/Script/Model/Enemy/Movement/StandingMovementBehavior.cs b/DoomDeathmatch/src/Script/Model/Enemy/Movement/StandingMovementBehavior.cs
index cbbeaed..ffb68a3 100644
--- a/DoomDeathmatch/src/Script/Model/Enemy/Movement/StandingMovementBehavior.cs
+++ b/DoomDeathmatch/src/Script/Model/Enemy/Movement/StandingMovementBehavior.cs
@@ -2,8 +2,17 @@
namespace DoomDeathmatch.Script.Model.Enemy.Movement;
+///
+/// Movement behavior where the enemy remains stationary.
+///
public class StandingMovementBehavior : IMovementBehavior
{
+ ///
+ /// Returns the current position of the enemy without any change, as the enemy does not move.
+ ///
+ /// The current position of the enemy.
+ /// The current position of the player (ignored).
+ /// The current position of the enemy.
public Vector3 GetNextPosition(Vector3 parPosition, Vector3 parPlayerPosition)
{
return parPosition;
diff --git a/DoomDeathmatch/src/Script/Model/HealthModel.cs b/DoomDeathmatch/src/Script/Model/HealthModel.cs
index 6e64d4a..c7bf5f2 100644
--- a/DoomDeathmatch/src/Script/Model/HealthModel.cs
+++ b/DoomDeathmatch/src/Script/Model/HealthModel.cs
@@ -1,9 +1,20 @@
namespace DoomDeathmatch.Script.Model;
+///
+/// Represents the health state of a player or entity in the game.
+/// Provides functionality to track and modify health, and notify listeners when health changes.
+///
public class HealthModel
{
+ ///
+ /// Occurs when the health value changes.
+ ///
public event Action? HealthChanged;
+ ///
+ /// The current health value of the entity.
+ /// Health is clamped between 0 and .
+ ///
public float Health
{
get => _health;
@@ -20,6 +31,10 @@ public class HealthModel
}
}
+ ///
+ /// The maximum health value of the entity.
+ /// When modified, the current health is clamped between 0 and the new .
+ ///
public float MaxHealth
{
get => _maxHealth;
@@ -31,9 +46,21 @@ public class HealthModel
}
}
+ ///
+ /// The current health value of the entity.
+ ///
private float _health;
+
+ ///
+ /// The maximum health value of the entity.
+ ///
private float _maxHealth;
+ ///
+ /// Initializes a new instance of the class with a specified maximum health.
+ /// Sets the initial health to the maximum health.
+ ///
+ /// The maximum health value.
public HealthModel(float parMaxHealth)
{
MaxHealth = parMaxHealth;
diff --git a/DoomDeathmatch/src/Script/Model/ScoreModel.cs b/DoomDeathmatch/src/Script/Model/ScoreModel.cs
index edfa21d..6e36708 100644
--- a/DoomDeathmatch/src/Script/Model/ScoreModel.cs
+++ b/DoomDeathmatch/src/Script/Model/ScoreModel.cs
@@ -1,9 +1,20 @@
namespace DoomDeathmatch.Script.Model;
+///
+/// Represents the score state of a player or entity in the game.
+/// Provides functionality to track and modify the score, and notify listeners when the score changes.
+///
public class ScoreModel
{
+ ///
+ /// Occurs when the score value changes.
+ ///
public event Action? ScoreChanged;
+ ///
+ /// The current score of the player or entity.
+ /// The score cannot be negative.
+ ///
public int Score
{
get => _score;
@@ -14,5 +25,8 @@ public class ScoreModel
}
}
+ ///
+ /// The current score of the player or entity.
+ ///
private int _score;
}
\ No newline at end of file
diff --git a/DoomDeathmatch/src/Script/Model/Weapon/IShootPattern.cs b/DoomDeathmatch/src/Script/Model/Weapon/IShootPattern.cs
index 74dc1c2..21f30d9 100644
--- a/DoomDeathmatch/src/Script/Model/Weapon/IShootPattern.cs
+++ b/DoomDeathmatch/src/Script/Model/Weapon/IShootPattern.cs
@@ -2,7 +2,17 @@
namespace DoomDeathmatch.Script.Model.Weapon;
+///
+/// Defines a shooting pattern for a weapon.
+///
public interface IShootPattern
{
+ ///
+ /// Computes the shooting pattern based on directional vectors.
+ ///
+ /// The forward direction of the weapon.
+ /// The upward direction of the weapon.
+ /// The rightward direction of the weapon.
+ /// A collection of directional offsets representing the shoot pattern.
public IEnumerable GetShootPattern(Vector3 parForward, Vector3 parUp, Vector3 parRight);
}
\ No newline at end of file
diff --git a/DoomDeathmatch/src/Script/Model/Weapon/LineShootPattern.cs b/DoomDeathmatch/src/Script/Model/Weapon/LineShootPattern.cs
index 8b23a26..c37262c 100644
--- a/DoomDeathmatch/src/Script/Model/Weapon/LineShootPattern.cs
+++ b/DoomDeathmatch/src/Script/Model/Weapon/LineShootPattern.cs
@@ -2,8 +2,18 @@
namespace DoomDeathmatch.Script.Model.Weapon;
+///
+/// Represents a simple linear shooting pattern.
+///
public class LineShootPattern : IShootPattern
{
+ ///
+ /// Computes a linear shooting pattern, which always shoots straight ahead.
+ ///
+ /// The forward direction of the weapon.
+ /// The upward direction of the weapon.
+ /// The rightward direction of the weapon.
+ /// A collection containing a single zero vector, indicating no offset.
public IEnumerable GetShootPattern(Vector3 parForward, Vector3 parUp, Vector3 parRight)
{
return [Vector3.Zero];
diff --git a/DoomDeathmatch/src/Script/Model/Weapon/RandomFlatSpreadShootPattern.cs b/DoomDeathmatch/src/Script/Model/Weapon/RandomFlatSpreadShootPattern.cs
index 147ca26..b87c8bb 100644
--- a/DoomDeathmatch/src/Script/Model/Weapon/RandomFlatSpreadShootPattern.cs
+++ b/DoomDeathmatch/src/Script/Model/Weapon/RandomFlatSpreadShootPattern.cs
@@ -2,15 +2,49 @@
namespace DoomDeathmatch.Script.Model.Weapon;
-public class RandomFlatSpreadShootPattern(float parAngle, uint parCount) : IShootPattern
+///
+/// Represents a shooting pattern with a random flat spread.
+///
+public class RandomFlatSpreadShootPattern : IShootPattern
{
+ ///
+ /// The random number generator for calculating spread angles.
+ ///
private readonly Random _random = new();
+ ///
+ /// The maximum angle of spread in radians.
+ ///
+ private readonly float _angle;
+
+ ///
+ /// The number of projectiles in the spread.
+ ///
+ private readonly uint _count;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The maximum angle of spread in radians.
+ /// The number of projectiles in the spread.
+ public RandomFlatSpreadShootPattern(float parAngle, uint parCount)
+ {
+ _angle = parAngle;
+ _count = parCount;
+ }
+
+ ///
+ /// Computes a random flat spread shooting pattern.
+ ///
+ /// The forward direction of the weapon.
+ /// The upward direction of the weapon.
+ /// The rightward direction of the weapon.
+ /// A collection of directional offsets representing the spread pattern.
public IEnumerable GetShootPattern(Vector3 parForward, Vector3 parUp, Vector3 parRight)
{
- for (var i = 0; i < parCount; i++)
+ for (var i = 0; i < _count; i++)
{
- var angle = parAngle * (((float)_random.NextDouble() * 2) - 1);
+ var angle = _angle * (((float)_random.NextDouble() * 2) - 1);
var delta = MathF.Tan(angle);
var offset = parRight * delta;
diff --git a/DoomDeathmatch/src/Script/Model/Weapon/WeaponData.cs b/DoomDeathmatch/src/Script/Model/Weapon/WeaponData.cs
index 3137bbf..8bc34d9 100644
--- a/DoomDeathmatch/src/Script/Model/Weapon/WeaponData.cs
+++ b/DoomDeathmatch/src/Script/Model/Weapon/WeaponData.cs
@@ -2,8 +2,14 @@
namespace DoomDeathmatch.Script.Model.Weapon;
+///
+/// Represents data associated with a weapon, including its stats, animations, and shooting pattern.
+///
public class WeaponData
{
+ ///
+ /// Data for the "Pistol" weapon.
+ ///
public static WeaponData Pistol =>
new(30)
{
@@ -19,6 +25,9 @@ public class WeaponData
ShootPattern = new LineShootPattern()
};
+ ///
+ /// Data for the "Shotgun" weapon.
+ ///
public static WeaponData Shotgun =>
new(10)
{
@@ -31,12 +40,24 @@ public class WeaponData
ShootPattern = new RandomFlatSpreadShootPattern(MathHelper.DegreesToRadians(10), 40)
};
+ ///
+ /// Triggered when the ammo of the weapon changes.
+ ///
public event Action? OnAmmoChanged;
-
+ ///
+ /// A unique identifier for the weapon.
+ ///
public string Id { get; private init; } = "";
+
+ ///
+ /// The display name of the weapon.
+ ///
public string Name { get; private init; } = "";
+ ///
+ /// The current ammo count of the weapon. Updates trigger the event.
+ ///
public int Ammo
{
get => _ammo;
@@ -62,29 +83,58 @@ public class WeaponData
}
}
+ ///
+ /// The maximum ammo capacity of the weapon.
+ ///
public int MaxAmmo { get; }
+ ///
+ /// The base damage dealt by the weapon.
+ ///
public int Damage { get; private init; }
+ ///
+ /// The path to the texture used when the weapon is idle.
+ ///
public string IdleTexture { get; private init; } = "";
+
+ ///
+ /// The duration of the weapon's firing animation, in seconds.
+ ///
public float FireAnimationDuration { get; private init; }
+
+ ///
+ /// A list of textures used for the weapon's firing animation.
+ ///
public List FireAnimation { get; } = [];
+ ///
+ /// The shooting pattern associated with the weapon.
+ ///
public IShootPattern ShootPattern { get; private init; }
+ ///
+ ///The current ammo count of the weapon.
+ ///
private int _ammo;
+ ///
+ /// Initializes a new instance of the class with the specified maximum ammo.
+ ///
+ /// The maximum ammo capacity for the weapon.
private WeaponData(int parMaxAmmo)
{
MaxAmmo = parMaxAmmo;
Ammo = MaxAmmo;
}
+ ///
public override bool Equals(object? parObj)
{
return parObj is WeaponData weaponModel && Id == weaponModel.Id;
}
+ ///
public override int GetHashCode()
{
return HashCode.Combine(Id);
diff --git a/DoomDeathmatch/src/Script/Model/WeaponModel.cs b/DoomDeathmatch/src/Script/Model/WeaponModel.cs
index f8917c1..9726e2e 100644
--- a/DoomDeathmatch/src/Script/Model/WeaponModel.cs
+++ b/DoomDeathmatch/src/Script/Model/WeaponModel.cs
@@ -2,13 +2,31 @@
namespace DoomDeathmatch.Script.Model;
+///
+/// Represents the weapon state of a player or entity in the game.
+/// Provides functionality to track available weapons, the selected weapon, and notify listeners when the selected weapon changes.
+///
public class WeaponModel
{
+ ///
+ /// Occurs when the selected weapon changes.
+ ///
public event Action? OnWeaponSelected;
+ ///
+ /// The list of available weapons for the player or entity.
+ ///
public IList Weapons => _weapons;
+
+ ///
+ /// The currently selected weapon.
+ ///
public WeaponData SelectedWeapon => _weapons[_selectedWeaponIndex];
+ ///
+ /// The index of the currently selected weapon in the weapons list.
+ /// When modified, triggers the event with the old and new selected weapons.
+ ///
public int SelectedWeaponIndex
{
get => _selectedWeaponIndex;
@@ -27,7 +45,13 @@ public class WeaponModel
}
}
+ ///
+ /// The list of available weapons for the player or entity.
+ ///
private readonly List _weapons = [WeaponData.Pistol];
+ ///
+ /// The index of the currently selected weapon in the weapons list.
+ ///
private int _selectedWeaponIndex;
}
\ No newline at end of file
diff --git a/DoomDeathmatch/src/Script/ObjectSpawner.cs b/DoomDeathmatch/src/Script/ObjectSpawner.cs
index d1defbf..ffa9fec 100644
--- a/DoomDeathmatch/src/Script/ObjectSpawner.cs
+++ b/DoomDeathmatch/src/Script/ObjectSpawner.cs
@@ -5,14 +5,37 @@ using OpenTK.Mathematics;
namespace DoomDeathmatch.Script;
+///
+/// Handles the spawning of game objects based on a condition and provided position and object data.
+///
public class ObjectSpawner : IUpdate
{
+ ///
+ /// Occurs when a new game object is spawned.
+ ///
public event Action? OnSpawned;
+ ///
+ /// Provides the game object to spawn.
+ ///
private readonly IValueProvider _gameObjectProvider;
+
+ ///
+ /// Provides the position where the game object will be spawned.
+ ///
private readonly IValueProvider _positionProvider;
+
+ ///
+ /// Determines when the spawner should spawn a new object.
+ ///
private readonly ICondition _condition;
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The provider for the game object to spawn.
+ /// The provider for the position of the spawned object.
+ /// The condition that triggers the spawning.
public ObjectSpawner(IValueProvider parGameObjectProvider, IValueProvider parPositionProvider,
ICondition parCondition)
{
@@ -23,11 +46,18 @@ public class ObjectSpawner : IUpdate
_condition.OnTrue += Spawn;
}
+ ///
+ /// Updates the state of the spawner, evaluating the condition to determine if a new object should spawn.
+ ///
+ /// The time elapsed since the last update, in seconds.
public void Update(double parDeltaTime)
{
_condition.Update(parDeltaTime);
}
+ ///
+ /// Spawns a new game object at the position provided by the position provider.
+ ///
private void Spawn()
{
var gameObject = _gameObjectProvider.GetValue();
diff --git a/DoomDeathmatch/src/Script/Provider/ConstValueProvider.cs b/DoomDeathmatch/src/Script/Provider/ConstValueProvider.cs
index db61517..3f962e5 100644
--- a/DoomDeathmatch/src/Script/Provider/ConstValueProvider.cs
+++ b/DoomDeathmatch/src/Script/Provider/ConstValueProvider.cs
@@ -1,9 +1,38 @@
namespace DoomDeathmatch.Script.Provider;
-public class ConstValueProvider(T parValue) : IValueProvider
+///
+/// Provides a constant value of type .
+///
+/// The type of value provided.
+public class ConstValueProvider : IValueProvider
{
- public T GetValue() => parValue;
+ ///
+ /// The value to provide.
+ ///
+ private readonly T _value;
+ ///
+ /// Initializes a new instance of .
+ ///
+ /// The value to store.
+ public ConstValueProvider(T parValue)
+ {
+ _value = parValue;
+ }
+
+ ///
+ public T GetValue() => _value;
+
+ ///
+ /// Creates a new instance of with the specified value.
+ ///
+ /// The constant value to provide.
+ /// A new instance of .
public static ConstValueProvider Create(T parValue) => new(parValue);
+
+ ///
+ /// Implicitly converts a value of type to a .
+ ///
+ /// The value to convert.
public static implicit operator ConstValueProvider(T parValue) => new(parValue);
}
\ No newline at end of file
diff --git a/DoomDeathmatch/src/Script/Provider/GeneratorValueProvider.cs b/DoomDeathmatch/src/Script/Provider/GeneratorValueProvider.cs
index 09dc744..836db62 100644
--- a/DoomDeathmatch/src/Script/Provider/GeneratorValueProvider.cs
+++ b/DoomDeathmatch/src/Script/Provider/GeneratorValueProvider.cs
@@ -1,9 +1,38 @@
namespace DoomDeathmatch.Script.Provider;
-public class GeneratorValueProvider(Func parGenerator) : IValueProvider
+///
+/// Provides a value generated by a function.
+///
+/// The type of value provided.
+public class GeneratorValueProvider : IValueProvider
{
- public T GetValue() => parGenerator();
+ ///
+ /// A function used to generate values.
+ ///
+ private readonly Func _generator;
+ ///
+ /// Initializes a new instance of .
+ ///
+ /// The function used to generate values.
+ public GeneratorValueProvider(Func parGenerator)
+ {
+ _generator = parGenerator;
+ }
+
+ ///
+ public T GetValue() => _generator();
+
+ ///
+ /// Creates a new instance of with the specified generator function.
+ ///
+ /// The function that generates values.
+ /// A new instance of .
public static GeneratorValueProvider Create(Func parGenerator) => new(parGenerator);
+
+ ///
+ /// Implicitly converts a function of type to a .
+ ///
+ /// The function to convert.
public static implicit operator GeneratorValueProvider(Func parGenerator) => new(parGenerator);
}
\ No newline at end of file
diff --git a/DoomDeathmatch/src/Script/Provider/IValueProvider.cs b/DoomDeathmatch/src/Script/Provider/IValueProvider.cs
index 6e0824b..3f63481 100644
--- a/DoomDeathmatch/src/Script/Provider/IValueProvider.cs
+++ b/DoomDeathmatch/src/Script/Provider/IValueProvider.cs
@@ -1,6 +1,14 @@
namespace DoomDeathmatch.Script.Provider;
+///
+/// Represents a provider that supplies a value of type .
+///
+/// The type of value provided.
public interface IValueProvider
{
+ ///
+ /// Retrieves the value provided by this instance.
+ ///
+ /// The value of type .
public T GetValue();
}
\ No newline at end of file
diff --git a/DoomDeathmatch/src/Script/Provider/RandomListValueProvider.cs b/DoomDeathmatch/src/Script/Provider/RandomListValueProvider.cs
index a165112..d5ce1ea 100644
--- a/DoomDeathmatch/src/Script/Provider/RandomListValueProvider.cs
+++ b/DoomDeathmatch/src/Script/Provider/RandomListValueProvider.cs
@@ -1,10 +1,25 @@
namespace DoomDeathmatch.Script.Provider;
+///
+/// Provides a value randomly selected from a list of value providers.
+///
+/// The type of value provided.
public class RandomListValueProvider : IValueProvider
{
+ ///
+ /// A collection of value providers to choose from.
+ ///
private readonly List> _providers = [];
+
+ ///
+ /// The random number generator for selecting providers.
+ ///
private readonly Random _random = new();
+ ///
+ /// Initializes a new instance of with the specified providers.
+ ///
+ /// The collection of value providers to select from.
public RandomListValueProvider(IEnumerable> parProviders)
{
foreach (var provider in parProviders)
@@ -13,6 +28,7 @@ public class RandomListValueProvider : IValueProvider
}
}
+ ///
public T GetValue()
{
return _providers[_random.Next(_providers.Count)].GetValue();
diff --git a/DoomDeathmatch/src/Script/Provider/WeightedRandomValueProvider.cs b/DoomDeathmatch/src/Script/Provider/WeightedRandomValueProvider.cs
index baf56c4..bf971e4 100644
--- a/DoomDeathmatch/src/Script/Provider/WeightedRandomValueProvider.cs
+++ b/DoomDeathmatch/src/Script/Provider/WeightedRandomValueProvider.cs
@@ -1,11 +1,31 @@
namespace DoomDeathmatch.Script.Provider;
+///
+/// Provides a value randomly selected from weighted value providers.
+///
+/// The type of value provided.
public class WeightedRandomValueProvider : IValueProvider
{
+ ///
+ /// A collection of weighted value providers.
+ ///
private readonly List<(int, IValueProvider)> _providers = [];
+
+ ///
+ /// The random number generator used to select a provider.
+ ///
private readonly Random _random = new();
+
+ ///
+ /// The total weight of all providers.
+ ///
private readonly int _totalWeight;
+ ///
+ /// Initializes a new instance of with the specified providers.
+ ///
+ /// The collection of weighted value providers.
+ /// Thrown if the total weight is less than or equal to 0.
public WeightedRandomValueProvider(IEnumerable<(int, IValueProvider)> parProviders)
{
foreach (var (weight, provider) in parProviders)
@@ -20,6 +40,7 @@ public class WeightedRandomValueProvider : IValueProvider
}
}
+ ///
public T GetValue()
{
var random = _random.Next(_totalWeight);
diff --git a/DoomDeathmatch/src/Script/Score/ScoreTable.cs b/DoomDeathmatch/src/Script/Score/ScoreTable.cs
index f09d0ce..58e9e50 100644
--- a/DoomDeathmatch/src/Script/Score/ScoreTable.cs
+++ b/DoomDeathmatch/src/Script/Score/ScoreTable.cs
@@ -7,7 +7,7 @@ namespace DoomDeathmatch.Script.Score;
[JsonSerializable(typeof(ScoreTable))]
public class ScoreTable
{
- public List Rows { get; } = new();
+ public List Rows { get; } = [];
private static readonly JsonSerializerOptions OPTIONS = new() { Converters = { new ScoreTableJsonConverter() } };
diff --git a/DoomDeathmatch/src/Script/UI/Align.cs b/DoomDeathmatch/src/Script/UI/Align.cs
index 0e22101..800d360 100644
--- a/DoomDeathmatch/src/Script/UI/Align.cs
+++ b/DoomDeathmatch/src/Script/UI/Align.cs
@@ -1,8 +1,22 @@
namespace DoomDeathmatch.Script.UI;
+///
+/// Specifies horizontal alignment options.
+///
public enum Align
{
+ ///
+ /// Align content to the left.
+ ///
Left,
+
+ ///
+ /// Align content to the center.
+ ///
Center,
+
+ ///
+ /// Align content to the right.
+ ///
Right
-}
\ No newline at end of file
+}
diff --git a/DoomDeathmatch/src/Script/UI/Anchor.cs b/DoomDeathmatch/src/Script/UI/Anchor.cs
index 619c7b3..de5fcb8 100644
--- a/DoomDeathmatch/src/Script/UI/Anchor.cs
+++ b/DoomDeathmatch/src/Script/UI/Anchor.cs
@@ -1,14 +1,90 @@
-namespace DoomDeathmatch.Script.UI;
+using OpenTK.Mathematics;
+namespace DoomDeathmatch.Script.UI;
+
+///
+/// Specifies anchoring options for positioning elements.
+///
public enum Anchor
{
+ ///
+ /// Anchor to the top-left corner.
+ ///
TopLeft,
+
+ ///
+ /// Anchor to the top-center.
+ ///
TopCenter,
+
+ ///
+ /// Anchor to the top-right corner.
+ ///
TopRight,
+
+ ///
+ /// Anchor to the center-left.
+ ///
CenterLeft,
+
+ ///
+ /// Anchor to the center.
+ ///
Center,
+
+ ///
+ /// Anchor to the center-right.
+ ///
CenterRight,
+
+ ///
+ /// Anchor to the bottom-left corner.
+ ///
BottomLeft,
+
+ ///
+ /// Anchor to the bottom-center.
+ ///
BottomCenter,
+
+ ///
+ /// Anchor to the bottom-right corner.
+ ///
BottomRight
+}
+
+public static class AnchorHelper
+{
+ ///
+ /// Retrieves the ratio of an anchor.
+ ///
+ /// The anchor to retrieve the ratio of.
+ /// The ratio of the anchor.
+ public static Vector2 GetRatio(this Anchor parAnchor)
+ {
+ return parAnchor switch
+ {
+ Anchor.TopLeft => new Vector2(-0.5f, 0.5f),
+ Anchor.TopCenter => new Vector2(0, 0.5f),
+ Anchor.TopRight => new Vector2(0.5f, 0.5f),
+ Anchor.CenterLeft => new Vector2(-0.5f, 0),
+ Anchor.Center => new Vector2(0, 0),
+ Anchor.CenterRight => new Vector2(0.5f, 0),
+ Anchor.BottomLeft => new Vector2(-0.5f, -0.5f),
+ Anchor.BottomCenter => new Vector2(0, -0.5f),
+ Anchor.BottomRight => new Vector2(0.5f, -0.5f),
+ _ => throw new ArgumentOutOfRangeException(nameof(parAnchor), parAnchor, null)
+ };
+ }
+
+ ///
+ /// Retrieves the position of an anchor relative to a size.
+ ///
+ /// The anchor to retrieve the position of.
+ /// The size to use for calculations.
+ /// The position of the anchor relative to the size.
+ public static Vector2 GetPosition(this Anchor parAnchor, Vector2 parSize)
+ {
+ return parSize * parAnchor.GetRatio();
+ }
}
\ No newline at end of file
diff --git a/DoomDeathmatch/src/Script/UI/Orientation.cs b/DoomDeathmatch/src/Script/UI/Orientation.cs
index cc35fe5..8d52c09 100644
--- a/DoomDeathmatch/src/Script/UI/Orientation.cs
+++ b/DoomDeathmatch/src/Script/UI/Orientation.cs
@@ -1,7 +1,17 @@
namespace DoomDeathmatch.Script.UI;
+///
+/// Specifies the orientation of UI elements.
+///
public enum Orientation
{
+ ///
+ /// Arrange elements horizontally.
+ ///
Horizontal,
+
+ ///
+ /// Arrange elements vertically.
+ ///
Vertical
}
\ No newline at end of file
diff --git a/Engine/src/Resource/Loader/ProgramLoader.cs b/Engine/src/Resource/Loader/ProgramLoader.cs
index 274f6a7..bad426a 100644
--- a/Engine/src/Resource/Loader/ProgramLoader.cs
+++ b/Engine/src/Resource/Loader/ProgramLoader.cs
@@ -17,7 +17,7 @@ public partial class ProgramLoader : IResourceLoader
/// The loaded shader program.
public object Load(string parPath, IResourceStreamProvider parStreamProvider)
{
- var textReader = new StreamReader(parStreamProvider.GetStream(parPath));
+ using var textReader = new StreamReader(parStreamProvider.GetStream(parPath));
var vertexSource = new StringBuilder();
var fragmentSource = new StringBuilder();
diff --git a/Engine/src/Scene/Component/Component.cs b/Engine/src/Scene/Component/Component.cs
index 0caf776..1cc49cc 100644
--- a/Engine/src/Scene/Component/Component.cs
+++ b/Engine/src/Scene/Component/Component.cs
@@ -45,6 +45,14 @@ public abstract class Component : IUpdate, IRender
{
}
+ ///
+ /// Called after the main update loop.
+ ///
+ /// Time elapsed since the last frame.
+ public virtual void PostUpdate(double parDeltaTime)
+ {
+ }
+
///
/// Called during the main render loop.
///
diff --git a/Engine/src/Scene/GameObject.cs b/Engine/src/Scene/GameObject.cs
index 452c845..a3b557e 100644
--- a/Engine/src/Scene/GameObject.cs
+++ b/Engine/src/Scene/GameObject.cs
@@ -151,6 +151,18 @@ public sealed class GameObject : IUpdate, IRender
}
}
+ ///
+ /// Performs post-update operations for all components.
+ ///
+ /// The time delta since the last update.
+ public void PostUpdate(double parDeltaTime)
+ {
+ foreach (var component in _components)
+ {
+ component.PostUpdate(parDeltaTime);
+ }
+ }
+
///
public void Render()
{
@@ -181,9 +193,9 @@ public sealed class GameObject : IUpdate, IRender
///
/// The type of the component to retrieve.
/// The component if found, otherwise null.
- public T? GetComponent() where T : Component.Component
+ public T? GetComponent() where T : class
{
- if (!HasComponent())
+ if (!typeof(T).IsInterface && !HasComponent())
{
return null;
}
@@ -204,7 +216,7 @@ public sealed class GameObject : IUpdate, IRender
///
/// The type of the component to retrieve.
/// The component if found, otherwise null.
- public T? GetComponentAny() where T : Component.Component
+ public T? GetComponentAny() where T : class
{
var component = GetComponent();
if (component != null)
@@ -221,7 +233,7 @@ public sealed class GameObject : IUpdate, IRender
///
/// The type of the component to retrieve.
/// The component if found, otherwise null.
- public T? GetComponentInChildren() where T : Component.Component
+ public T? GetComponentInChildren() where T : class
{
var children = Scene!.Hierarchy.GetChildren(this);
@@ -334,7 +346,7 @@ public sealed class GameObject : IUpdate, IRender
///
/// The type of the component to check for.
/// True if the component exists, otherwise false.
- public bool HasComponent() where T : Component.Component
+ public bool HasComponent()
{
var baseType = typeof(T).GetComponentBaseType();
return _addedComponentTypes.Contains(baseType);
diff --git a/Engine/src/Scene/Scene.cs b/Engine/src/Scene/Scene.cs
index 3c0bd19..7b79b32 100644
--- a/Engine/src/Scene/Scene.cs
+++ b/Engine/src/Scene/Scene.cs
@@ -61,6 +61,11 @@ public class Scene : IUpdate, IRender
{
gameObject.Update(parDeltaTime * TimeScale);
}
+
+ foreach (var gameObject in hierarchyObjects)
+ {
+ gameObject.PostUpdate(parDeltaTime * TimeScale);
+ }
}
///
diff --git a/Engine/src/Util/Math.cs b/Engine/src/Util/MathUtil.cs
similarity index 96%
rename from Engine/src/Util/Math.cs
rename to Engine/src/Util/MathUtil.cs
index 6c32f38..300e9ac 100644
--- a/Engine/src/Util/Math.cs
+++ b/Engine/src/Util/MathUtil.cs
@@ -5,7 +5,7 @@ namespace Engine.Util;
///
/// Contains mathematical utility methods.
///
-public static class Math
+public static class MathUtil
{
///
/// Multiplies a by a and performs projective division.
diff --git a/PresenterConsole/src/ConsolePresenter.cs b/PresenterConsole/src/ConsolePresenter.cs
index ea0f6aa..3e0d61f 100644
--- a/PresenterConsole/src/ConsolePresenter.cs
+++ b/PresenterConsole/src/ConsolePresenter.cs
@@ -14,10 +14,16 @@ namespace PresenterConsole;
public class ConsolePresenter : IPresenter
{
+ ///
public event Action? OnResize;
+ ///
public int Width { get; private set; } = 2;
+
+ ///
public int Height { get; private set; } = 1;
+
+ ///
public bool IsExiting { get; private set; }
private static readonly char[] LIGHTMAP = " .,:;=*#%@".Reverse().ToArray();
@@ -27,8 +33,8 @@ public class ConsolePresenter : IPresenter
private readonly Engine.Graphics.Shader.Program _asciiProgram;
private readonly Framebuffer _framebuffer;
private readonly IndexBuffer _indexBuffer;
- private readonly VertexArray _vertexArray;
private readonly VertexBuffer _vertexBuffer;
+ private readonly VertexArray _vertexArray;
private Image? _asciiImage;
@@ -62,8 +68,6 @@ public class ConsolePresenter : IPresenter
{
var openglTexture = (Texture)parTexture;
- // GL.Viewport(0, 0, Width / 2, Height);
-
_framebuffer.Bind();
openglTexture.BindUnit();
diff --git a/PresenterConsole/src/WindowsFFI.cs b/PresenterConsole/src/WindowsFFI.cs
index 2c7e2e6..d169418 100644
--- a/PresenterConsole/src/WindowsFFI.cs
+++ b/PresenterConsole/src/WindowsFFI.cs
@@ -8,38 +8,101 @@ using Microsoft.Win32.SafeHandles;
namespace PresenterConsole;
+///
+/// Provides Windows FFI (Foreign Function Interface) functionality to interact with the Windows API
+/// for various operations such as file handling, console operations, keyboard state management, and window handling.
+///
public static partial class WindowsFFI
{
+ ///
+ /// Represents a coordinate with X and Y values, typically used for positioning or grid-like structures.
+ ///
[StructLayout(LayoutKind.Sequential)]
public struct Coord(short parX, short parY)
{
+ ///
+ /// The X coordinate.
+ ///
public short X = parX;
+
+ ///
+ /// The Y coordinate.
+ ///
public short Y = parY;
}
+ ///
+ /// A union structure that can hold either a Unicode or an ASCII character at the same memory location.
+ ///
[StructLayout(LayoutKind.Explicit)]
public struct CharUnion
{
+ ///
+ /// The Unicode character value.
+ ///
[FieldOffset(0)] public char UnicodeChar;
+
+ ///
+ /// The ASCII character value.
+ ///
[FieldOffset(0)] public byte AsciiChar;
}
+ ///
+ /// Represents a character and its associated attributes in the console output, including the character's color.
+ ///
[StructLayout(LayoutKind.Explicit)]
public struct CharInfo
{
+ ///
+ /// The character.
+ ///
[FieldOffset(0)] public CharUnion Char;
+
+ ///
+ /// The attributes associated with the character (e.g., color).
+ ///
[FieldOffset(2)] public short Attributes;
}
+ ///
+ /// Represents a rectangle in terms of its left, top, right, and bottom coordinates, used for defining the bounds of a console screen area.
+ ///
[StructLayout(LayoutKind.Sequential)]
public struct SmallRect
{
+ ///
+ /// The left coordinate of the rectangle.
+ ///
public short Left;
+
+ ///
+ /// The top coordinate of the rectangle.
+ ///
public short Top;
+
+ ///
+ /// The right coordinate of the rectangle.
+ ///
public short Right;
+
+ ///
+ /// The bottom coordinate of the rectangle.
+ ///
public short Bottom;
}
+ ///
+ /// Uses the kernel32.dll's CreateFileW function to open or create a file with the specified parameters.
+ ///
+ /// The name of the file to open or create.
+ /// The requested access to the file.
+ /// The sharing mode for the file.
+ /// Security attributes for the file.
+ /// Action to take when opening the file.
+ /// File-specific flags.
+ /// An optional template file.
+ /// A handle to the opened or created file.
[LibraryImport("kernel32.dll", SetLastError = true, EntryPoint = "CreateFileW")]
public static partial SafeFileHandle CreateFile(
[MarshalAs(UnmanagedType.LPWStr)] string parFileName,
@@ -51,6 +114,15 @@ public static partial class WindowsFFI
IntPtr parTemplate
);
+ ///
+ /// Uses the kernel32.dll's WriteConsoleOutputW function to write characters to the console output at the specified coordinates.
+ ///
+ /// A handle to the console output.
+ /// The buffer containing the characters and their attributes to be written.
+ /// The size of the buffer.
+ /// The coordinates of the starting position in the console buffer.
+ /// The region of the console buffer to write to.
+ /// True if the operation was successful, otherwise false.
[LibraryImport("kernel32.dll", SetLastError = true, EntryPoint = "WriteConsoleOutputW")]
[return: MarshalAs(UnmanagedType.Bool)]
public static partial bool WriteConsoleOutput(
@@ -62,32 +134,61 @@ public static partial class WindowsFFI
ref SmallRect parLpWriteRegion
);
+ ///
+ /// Uses the user32.dll's GetKeyboardState function to retrieve the state of the keyboard keys.
+ ///
+ /// An array to receive the current state of the keyboard keys.
+ /// True if the operation was successful, otherwise false.
[LibraryImport("user32.dll", SetLastError = true, EntryPoint = "GetKeyboardState")]
[return: MarshalAs(UnmanagedType.Bool)]
public static partial bool GetKeyboardState(byte[] parKeyboardState);
+ ///
+ /// Uses the user32.dll's GetAsyncKeyState function to retrieve the state of a specific key.
+ ///
+ /// The key code for the key whose state is to be retrieved.
+ /// A short value representing the key's state.
[LibraryImport("user32.dll", SetLastError = true, EntryPoint = "GetAsyncKeyState")]
public static partial short GetAsyncKeyState(int parKeyCode);
+ ///
+ /// Uses the user32.dll's GetForegroundWindow function to retrieve the handle of the foreground window.
+ ///
+ /// The handle of the foreground window.
[LibraryImport("user32.dll", SetLastError = true, EntryPoint = "GetForegroundWindow")]
public static partial IntPtr GetForegroundWindow();
+ ///
+ /// Uses the user32.dll's GetWindowThreadProcessId function to retrieve the process ID of the thread that owns a specified window.
+ ///
+ /// The handle to the window.
+ /// An optional pointer to receive the process ID of the window's thread.
+ /// The thread ID of the window.
[LibraryImport("user32.dll", SetLastError = true, EntryPoint = "GetWindowThreadProcessId")]
public static partial uint GetWindowThreadProcessId(IntPtr parHwnd, IntPtr parLpdwProcessId);
+ ///
+ /// Uses the user32.dll's GetKeyboardLayout function to retrieve the input locale identifier for the current thread.
+ ///
+ /// The ID of the thread for which to retrieve the keyboard layout.
+ /// The handle to the keyboard layout for the thread.
[LibraryImport("user32.dll", SetLastError = true, EntryPoint = "GetKeyboardLayout")]
public static partial IntPtr GetKeyboardLayout(uint parThreadId);
+ ///
+ /// Retrieves the current keyboard layout for the foreground window's process. Assumes English (1033) if an error occurs.
+ ///
+ /// A object representing the current keyboard layout.
public static CultureInfo GetCurrentKeyboardLayout()
{
try
{
- IntPtr foregroundWindow = GetForegroundWindow();
- uint foregroundProcess = GetWindowThreadProcessId(foregroundWindow, IntPtr.Zero);
- int keyboardLayout = GetKeyboardLayout(foregroundProcess).ToInt32() & 0xFFFF;
+ var foregroundWindow = GetForegroundWindow();
+ var foregroundProcess = GetWindowThreadProcessId(foregroundWindow, IntPtr.Zero);
+ var keyboardLayout = GetKeyboardLayout(foregroundProcess).ToInt32() & 0xFFFF;
return new CultureInfo(keyboardLayout);
}
- catch (Exception _)
+ catch (Exception)
{
return new CultureInfo(1033); // Assume English if something went wrong.
}