diff --git a/DoomDeathmatch/src/Component/ConsumableComponent.cs b/DoomDeathmatch/src/Component/ConsumableComponent.cs
index 867abf2..a8bf358 100644
--- a/DoomDeathmatch/src/Component/ConsumableComponent.cs
+++ b/DoomDeathmatch/src/Component/ConsumableComponent.cs
@@ -36,7 +36,7 @@ public class ConsumableComponent : Engine.Scene.Component.Component
///
/// Controls the movement of the consumable object.
///
- private MovementController _movementController = null!;
+ private MovementComponent _movementComponent = null!;
///
/// Initializes a new instance of the class.
@@ -57,9 +57,9 @@ public class ConsumableComponent : Engine.Scene.Component.Component
_collider.OnCollision += OnCollision;
_box2DRenderer.Texture = EngineUtil.AssetResourceManager.Load(_consumable.Icon);
- _movementController = GameObject.GetComponent()!;
+ _movementComponent = GameObject.GetComponent()!;
- ArgumentNullException.ThrowIfNull(_movementController);
+ ArgumentNullException.ThrowIfNull(_movementComponent);
}
///
@@ -113,7 +113,7 @@ public class ConsumableComponent : Engine.Scene.Component.Component
direction.Normalize();
}
- _movementController.ApplyMovement(direction);
+ _movementComponent.ApplyMovement(direction);
}
///
diff --git a/DoomDeathmatch/src/Component/MVC/Enemy/EnemyController.cs b/DoomDeathmatch/src/Component/MVC/Enemy/EnemyController.cs
index 93d459c..0275391 100644
--- a/DoomDeathmatch/src/Component/MVC/Enemy/EnemyController.cs
+++ b/DoomDeathmatch/src/Component/MVC/Enemy/EnemyController.cs
@@ -30,7 +30,7 @@ public class EnemyController : Engine.Scene.Component.Component
///
/// Controls the movement of the enemy.
///
- private MovementController _movementController = null!;
+ private MovementComponent _movementComponent = null!;
///
/// Handles the enemy's attack behavior.
@@ -56,19 +56,19 @@ public class EnemyController : Engine.Scene.Component.Component
_gameController = EngineUtil.SceneManager.CurrentScene!.FindFirstComponent()!;
HealthController = GameObject.GetComponent()!;
_enemyView = GameObject.GetComponent>()!;
- _movementController = GameObject.GetComponent()!;
+ _movementComponent = GameObject.GetComponent()!;
ArgumentNullException.ThrowIfNull(_gameController);
ArgumentNullException.ThrowIfNull(HealthController);
ArgumentNullException.ThrowIfNull(_enemyView);
- ArgumentNullException.ThrowIfNull(_movementController);
+ ArgumentNullException.ThrowIfNull(_movementComponent);
_attackBehavior = _enemyData.AttackBehaviorCreator.Create(this, _gameController.PlayerController.HealthController);
HealthController.SetMaxHealth(_enemyData.BaseHealth);
HealthController.OnDeath += OnDeath;
_enemyView.UpdateView(_enemyData);
- _movementController.Speed = _enemyData.BaseSpeed;
+ _movementComponent.Speed = _enemyData.BaseSpeed;
}
public override void Start()
@@ -92,7 +92,7 @@ public class EnemyController : Engine.Scene.Component.Component
if (enemyPosition != nextPosition)
{
var direction = (nextPosition - enemyPosition).Normalized();
- _movementController.ApplyMovement(direction);
+ _movementComponent.ApplyMovement(direction);
}
_attackBehavior.Attack(parDeltaTime);
diff --git a/DoomDeathmatch/src/Component/MVC/MovementController.cs b/DoomDeathmatch/src/Component/MVC/MovementComponent.cs
similarity index 94%
rename from DoomDeathmatch/src/Component/MVC/MovementController.cs
rename to DoomDeathmatch/src/Component/MVC/MovementComponent.cs
index 2ee7ac5..60484f4 100644
--- a/DoomDeathmatch/src/Component/MVC/MovementController.cs
+++ b/DoomDeathmatch/src/Component/MVC/MovementComponent.cs
@@ -6,7 +6,7 @@ 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
+public class MovementComponent : Engine.Scene.Component.Component
{
///
/// The movement speed.
diff --git a/DoomDeathmatch/src/Component/MVC/PlayerController.cs b/DoomDeathmatch/src/Component/MVC/PlayerController.cs
index b4af6b1..6019941 100644
--- a/DoomDeathmatch/src/Component/MVC/PlayerController.cs
+++ b/DoomDeathmatch/src/Component/MVC/PlayerController.cs
@@ -1,7 +1,6 @@
using DoomDeathmatch.Component.MVC.Enemy;
using DoomDeathmatch.Component.MVC.Health;
using DoomDeathmatch.Component.MVC.Weapon;
-using DoomDeathmatch.Component.Physics.Collision;
using Engine.Input;
using Engine.Scene.Component.BuiltIn;
using Engine.Util;
@@ -71,6 +70,34 @@ public class PlayerController : Engine.Scene.Component.Component
return;
}
+ ExecuteWeaponSelection();
+
+ ExecuteWeaponShooting();
+ }
+
+ ///
+ /// Handles weapon shooting.
+ ///
+ private void ExecuteWeaponShooting()
+ {
+ if (!_inputHandler.IsKeyJustPressed(KeyboardButtonCode.Space))
+ {
+ return;
+ }
+
+ if (!WeaponController.TryShoot())
+ {
+ return;
+ }
+
+ ShootSelectedWeapon();
+ }
+
+ ///
+ /// Handles weapon selection.
+ ///
+ private void ExecuteWeaponSelection()
+ {
for (var i = 0; i < 10; i++)
{
if (KeyboardButtonCode.D1 + i > KeyboardButtonCode.D0)
@@ -86,38 +113,20 @@ public class PlayerController : Engine.Scene.Component.Component
WeaponController.SelectWeapon(i);
break;
}
-
- if (_inputHandler.IsKeyJustPressed(KeyboardButtonCode.Space))
- {
- if (!WeaponController.TryShoot())
- {
- return;
- }
-
- HandleShootingRaycast();
- }
}
///
- /// Handles the shooting raycast for the player.
+ /// Shoots the selected weapon.
///
- private void HandleShootingRaycast()
+ private void ShootSelectedWeapon()
{
var position = Camera.GameObject.Transform.GetFullTranslation();
var forward = (Camera.Forward - position).Normalized();
- var right = Vector3.Cross(forward, Vector3.UnitZ).Normalized();
+ var up = Vector3.UnitZ;
+ var groups = new HashSet { "enemy", "wall" };
- var collisionManager = EngineUtil.SceneManager.CurrentScene!.FindFirstComponent();
-
- var offsets = WeaponController.WeaponData.ShootPattern.GetShootPattern(forward, Vector3.UnitZ, right);
- foreach (var offset in offsets)
+ foreach (var result in WeaponController.RaycastWeaponShooting(position, forward, up, groups))
{
- 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);
}
diff --git a/DoomDeathmatch/src/Component/MVC/Weapon/WeaponController.cs b/DoomDeathmatch/src/Component/MVC/Weapon/WeaponController.cs
index b50f0b8..090d5e3 100644
--- a/DoomDeathmatch/src/Component/MVC/Weapon/WeaponController.cs
+++ b/DoomDeathmatch/src/Component/MVC/Weapon/WeaponController.cs
@@ -1,5 +1,9 @@
-using DoomDeathmatch.Script.Model;
+using DoomDeathmatch.Component.Physics.Collision;
+using DoomDeathmatch.Script.Collision;
+using DoomDeathmatch.Script.Model;
using DoomDeathmatch.Script.Model.Weapon;
+using Engine.Util;
+using OpenTK.Mathematics;
namespace DoomDeathmatch.Component.MVC.Weapon;
@@ -21,21 +25,25 @@ public class WeaponController : Engine.Scene.Component.Component
///
/// The internal weapon model containing weapon-related data.
///
- private readonly WeaponModel _weaponModel = new();
+ private readonly WeaponModel _weaponModel;
///
/// View responsible for displaying weapon information and animations.
///
private IWeaponView _weaponView = null!;
+ ///
+ /// Initializes a new instance of the class with an initial weapon.
+ ///
+ /// The initial weapon.
+ public WeaponController(WeaponData parInitialWeapon)
+ {
+ _weaponModel = new WeaponModel(parInitialWeapon);
+ }
+
public override void Awake()
{
_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);
@@ -129,6 +137,34 @@ public class WeaponController : Engine.Scene.Component.Component
_weaponModel.SelectedWeaponIndex = parIndex;
}
+ ///
+ /// Raycasts for the shooting pattern of the selected weapon.
+ ///
+ /// The position of the player or entity.
+ /// The forward direction of the player or entity.
+ /// The up direction of the player or entity.
+ /// The collider groups to consider for the raycast.
+ /// The raycast results.
+ public IEnumerable RaycastWeaponShooting(Vector3 parPosition, Vector3 parForward, Vector3 parUp,
+ HashSet parGroups)
+ {
+ var right = Vector3.Cross(parForward, parUp).Normalized();
+
+ var collisionManager = EngineUtil.SceneManager.CurrentScene!.FindFirstComponent();
+
+ var offsets = WeaponData.ShootPattern.GetShootPattern(parForward, parUp, right);
+ foreach (var offset in offsets)
+ {
+ var direction = parForward + offset;
+ if (!collisionManager!.Raycast(parPosition, direction, parGroups, out var result))
+ {
+ continue;
+ }
+
+ yield return result;
+ }
+ }
+
///
/// Updates the view when the selected weapon changes.
///
@@ -143,8 +179,13 @@ public class WeaponController : Engine.Scene.Component.Component
parNewWeapon.OnAmmoChanged += AmmoChanged;
_weaponView.UpdateView(parNewWeapon);
+ AmmoChanged(parNewWeapon);
}
+ ///
+ /// Updates the ammo view when the selected weapon's ammo changes.
+ ///
+ /// The updated weapon.
private void AmmoChanged(WeaponData parWeapon)
{
var ammoData = new AmmoData { Ammo = parWeapon.Ammo, MaxAmmo = parWeapon.MaxAmmo };
diff --git a/DoomDeathmatch/src/Component/UI/SelectorComponent.cs b/DoomDeathmatch/src/Component/UI/SelectorComponent.cs
index 2ca50d3..5f18515 100644
--- a/DoomDeathmatch/src/Component/UI/SelectorComponent.cs
+++ b/DoomDeathmatch/src/Component/UI/SelectorComponent.cs
@@ -31,7 +31,7 @@ public class SelectorComponent : Engine.Scene.Component.Component
///
/// The key used to select the currently selected item.
///
- public KeyboardButtonCode SelectKey { get; set; } = KeyboardButtonCode.Space;
+ public KeyboardButtonCode SelectKey { get; set; } = KeyboardButtonCode.Enter;
///
/// The input handler used to check for keyboard input.
diff --git a/DoomDeathmatch/src/Component/Util/PlayerMovementComponent.cs b/DoomDeathmatch/src/Component/Util/PlayerMovementComponent.cs
index 100c107..646bf2b 100644
--- a/DoomDeathmatch/src/Component/Util/PlayerMovementComponent.cs
+++ b/DoomDeathmatch/src/Component/Util/PlayerMovementComponent.cs
@@ -11,7 +11,7 @@ namespace DoomDeathmatch.Component.Util;
public class PlayerMovementComponent : Engine.Scene.Component.Component
{
///
- /// The speed at which the player rotates.
+ /// The speed at which the player rotates in degrees per second.
///
public float RotationSpeed { get; set; } = 110.0f;
@@ -23,13 +23,13 @@ public class PlayerMovementComponent : Engine.Scene.Component.Component
///
/// Controls the movement logic of the player.
///
- private MovementController _movementController = null!;
+ private MovementComponent _movementComponent = null!;
public override void Awake()
{
- _movementController = GameObject.GetComponent()!;
+ _movementComponent = GameObject.GetComponent()!;
- ArgumentNullException.ThrowIfNull(_movementController);
+ ArgumentNullException.ThrowIfNull(_movementComponent);
}
public override void Update(double parDeltaTime)
@@ -72,7 +72,7 @@ public class PlayerMovementComponent : Engine.Scene.Component.Component
movement.Normalize();
movement = GameObject.Transform.Rotation * movement;
- _movementController.ApplyMovement(movement);
+ _movementComponent.ApplyMovement(movement);
}
GameObject.Transform.Rotation *= Quaternion.FromAxisAngle(Vector3.UnitZ, MathHelper.DegreesToRadians(rotation) *
diff --git a/DoomDeathmatch/src/Scene/GameConstants.cs b/DoomDeathmatch/src/Scene/GameConstants.cs
index 1616d06..ccfb74a 100644
--- a/DoomDeathmatch/src/Scene/GameConstants.cs
+++ b/DoomDeathmatch/src/Scene/GameConstants.cs
@@ -64,6 +64,7 @@ public static class GameConstants
public const float PLAYER_BASE_HEALTH = 100;
public const float PLAYER_BASE_SPEED = 10;
+ public const float PLAYER_BASE_ROTATION_SPEED = 110;
#endregion
diff --git a/DoomDeathmatch/src/Scene/Play/PlayScene.cs b/DoomDeathmatch/src/Scene/Play/PlayScene.cs
index 0105776..3ee5d59 100644
--- a/DoomDeathmatch/src/Scene/Play/PlayScene.cs
+++ b/DoomDeathmatch/src/Scene/Play/PlayScene.cs
@@ -314,6 +314,10 @@ public static class PlayScene
logoUi.Offset = new Vector2(0, 3f);
parScene.AddChild(parentObject, logoObject);
+ var (pauseUiObject, pauseUi, _) = UiPrefabs.CreateTextUi(parScene, backgroundUiContainer,
+ UiPrefabs.GetDoomFont(), "Пауза",
+ parRenderLayer: RenderLayer.HUD, parScale: 1.5f);
+
var (backUiObject, backUi, _) = UiPrefabs.CreateTextUi(parScene, backgroundUiContainer,
UiPrefabs.GetDoomFont(), "Назад",
parRenderLayer: RenderLayer.HUD);
@@ -328,7 +332,7 @@ public static class PlayScene
var (stackObject, stack) = UiPrefabs.CreateStackUi(parScene,
new StackComponent
{
- Offset = new Vector2(0, -1f), Container = backgroundUiContainer, Children = { backUi, exitUi }
+ Offset = new Vector2(0, -1f), Container = backgroundUiContainer, Children = { pauseUi, backUi, exitUi }
});
stackObject.Transform.Size.Xy = new Vector2(1f, 6f);
@@ -337,6 +341,8 @@ public static class PlayScene
parScene.AddChild(parentObject, selectorObject);
parScene.AddChild(parentObject, stackObject);
+
+ parScene.AddChild(stackObject, pauseUiObject);
parScene.AddChild(stackObject, backUiObject);
parScene.AddChild(stackObject, exitUiObject);
diff --git a/DoomDeathmatch/src/Scene/Play/Prefab/ConsumablePrefab.cs b/DoomDeathmatch/src/Scene/Play/Prefab/ConsumablePrefab.cs
index dbdb086..5a259a4 100644
--- a/DoomDeathmatch/src/Scene/Play/Prefab/ConsumablePrefab.cs
+++ b/DoomDeathmatch/src/Scene/Play/Prefab/ConsumablePrefab.cs
@@ -32,7 +32,7 @@ public static class ConsumablePrefab
new RigidbodyComponent(),
new DragComponent { Drag = 10f, Multiplier = new Vector3(1, 1, 0) },
- new MovementController { Speed = 10f },
+ new MovementComponent { Speed = 10f },
collider
]
);
diff --git a/DoomDeathmatch/src/Scene/Play/Prefab/EnemyPrefab.cs b/DoomDeathmatch/src/Scene/Play/Prefab/EnemyPrefab.cs
index dc7c556..9fa4422 100644
--- a/DoomDeathmatch/src/Scene/Play/Prefab/EnemyPrefab.cs
+++ b/DoomDeathmatch/src/Scene/Play/Prefab/EnemyPrefab.cs
@@ -32,7 +32,7 @@ public static class EnemyPrefab
new HealthController(parEnemyData.BaseHealth),
new EnemyHealthView(enemyHealthTextRenderer),
- new MovementController(),
+ new MovementComponent(),
new RigidbodyComponent(),
new DragComponent { Drag = 5f, Multiplier = new Vector3(1, 1, 0) },
diff --git a/DoomDeathmatch/src/Scene/Play/Prefab/PlayerPrefab.cs b/DoomDeathmatch/src/Scene/Play/Prefab/PlayerPrefab.cs
index 0201034..845645c 100644
--- a/DoomDeathmatch/src/Scene/Play/Prefab/PlayerPrefab.cs
+++ b/DoomDeathmatch/src/Scene/Play/Prefab/PlayerPrefab.cs
@@ -5,6 +5,7 @@ using DoomDeathmatch.Component.Physics;
using DoomDeathmatch.Component.Physics.Collision;
using DoomDeathmatch.Component.Util;
using DoomDeathmatch.Script.Collision;
+using DoomDeathmatch.Script.Model.Weapon;
using Engine.Scene;
using OpenTK.Mathematics;
@@ -17,9 +18,6 @@ public static class PlayerPrefab
var (perspectiveCameraObject, perspectiveCamera) = UiPrefabs.CreatePerspectiveCamera(parScene);
perspectiveCameraObject.Transform.Translation.Z = 2;
var playerObject = GameObjectUtil.CreateGameObject(parScene, [
- new PlayerMovementComponent(),
-
- new MovementController { Speed = GameConstants.PLAYER_BASE_SPEED },
new RigidbodyComponent(),
new DragComponent { Drag = 10f, Multiplier = new Vector3(1, 1, 0) },
@@ -31,9 +29,12 @@ public static class PlayerPrefab
ExcludeColliderCollideGroups = { "player" }
},
+ new MovementComponent { Speed = GameConstants.PLAYER_BASE_SPEED },
+ new PlayerMovementComponent { RotationSpeed = GameConstants.PLAYER_BASE_ROTATION_SPEED },
+
new PlayerController(perspectiveCamera),
- new WeaponController(),
+ new WeaponController(WeaponData.Pistol),
parWeaponView,
new HealthController(GameConstants.PLAYER_BASE_HEALTH),
diff --git a/DoomDeathmatch/src/Scene/UiPrefabs.cs b/DoomDeathmatch/src/Scene/UiPrefabs.cs
index 0946a9f..b69face 100644
--- a/DoomDeathmatch/src/Scene/UiPrefabs.cs
+++ b/DoomDeathmatch/src/Scene/UiPrefabs.cs
@@ -43,12 +43,15 @@ public static class UiPrefabs
public static (GameObject, UiContainerComponent, (GameObject, TextRenderer)) CreateTextUi(Engine.Scene.Scene parScene,
UiContainerComponent parContainer,
Font parFont, string parText, Align parAlign = Align.Center,
- RenderLayer? parRenderLayer = null)
+ RenderLayer? parRenderLayer = null, float parScale = 1)
{
var size = parFont.Measure(parText);
var outerObject = new GameObject
{
- Transform = { Size = new Vector3(size.X, size.Y, 1f), Translation = new Vector3(0, 0, -1) }
+ Transform =
+ {
+ Size = new Vector3(size.X, size.Y, 1f), Translation = new Vector3(0, 0, -1), Scale = new Vector3(parScale)
+ }
};
var uiComponent = new UiContainerComponent { Container = parContainer };
outerObject.AddComponent(uiComponent);
diff --git a/DoomDeathmatch/src/Script/Model/WeaponModel.cs b/DoomDeathmatch/src/Script/Model/WeaponModel.cs
index 9726e2e..b8132de 100644
--- a/DoomDeathmatch/src/Script/Model/WeaponModel.cs
+++ b/DoomDeathmatch/src/Script/Model/WeaponModel.cs
@@ -48,10 +48,19 @@ public class WeaponModel
///
/// The list of available weapons for the player or entity.
///
- private readonly List _weapons = [WeaponData.Pistol];
+ private readonly List _weapons;
///
/// The index of the currently selected weapon in the weapons list.
///
private int _selectedWeaponIndex;
+
+ ///
+ /// Initializes a new instance of the class with an initial weapon.
+ ///
+ /// The initial weapon.
+ public WeaponModel(WeaponData parInitialWeapon)
+ {
+ _weapons = [parInitialWeapon];
+ }
}
\ No newline at end of file
diff --git a/PresenterConsole/assets/shader/ascii.shader b/PresenterConsole/assets/shader/ascii.shader
index c58eef7..6e79aac 100644
--- a/PresenterConsole/assets/shader/ascii.shader
+++ b/PresenterConsole/assets/shader/ascii.shader
@@ -81,36 +81,36 @@ float perceptualColorDistance(vec3 color1, vec3 color2) {
return dot(delta, delta);
}
-int findMostPerceptuallyAccurateColor(vec3 color) {
- int bestMatchIndex = 0;
- float minDistance = perceptualColorDistance(color, ConsoleColorVec3[0]);
-
- for (int i = 1; i < 16; i++) {
- float currentDistance = perceptualColorDistance(color, ConsoleColorVec3[i]);
- if (currentDistance < minDistance) {
- minDistance = currentDistance;
- bestMatchIndex = i;
- }
- }
-
- return bestMatchIndex;
-}
-
//int findMostPerceptuallyAccurateColor(vec3 color) {
-// int closestIndex = 0;
-// float minDistance = distance(color, ConsoleColorVec3[0]);
+// int bestMatchIndex = 0;
+// float minDistance = perceptualColorDistance(color, ConsoleColorVec3[0]);
//
// for (int i = 1; i < 16; i++) {
-// float dist = distance(color, ConsoleColorVec3[i]);
-// if (dist < minDistance) {
-// minDistance = dist;
-// closestIndex = i;
+// float currentDistance = perceptualColorDistance(color, ConsoleColorVec3[i]);
+// if (currentDistance < minDistance) {
+// minDistance = currentDistance;
+// bestMatchIndex = i;
// }
// }
//
-// return closestIndex;
+// return bestMatchIndex;
//}
+int findMostPerceptuallyAccurateColor(vec3 color) {
+ int closestIndex = 0;
+ float minDistance = distance(color, ConsoleColorVec3[0]);
+
+ for (int i = 1; i < 16; i++) {
+ float dist = distance(color, ConsoleColorVec3[i]);
+ if (dist < minDistance) {
+ minDistance = dist;
+ closestIndex = i;
+ }
+ }
+
+ return closestIndex;
+}
+
// Enhanced luminosity calculation considering human perception
float calculatePerceptualLuminance(vec3 color) {
// BT.709 luminance coefficients with slight adjustment