This commit is contained in:
2025-01-07 23:28:49 +03:00
parent 10231492a6
commit 0cd2d8ea96
12 changed files with 202 additions and 107 deletions

View File

@@ -32,7 +32,7 @@ public class HealthController : Engine.Scene.Component.Component
/// Initializes a new instance of the <see cref="HealthController"/> class with an optional starting health value.
/// </summary>
/// <param name="parHealth">Initial health value. Defaults to 100.</param>
public HealthController(float parHealth = 100)
public HealthController(float parHealth)
{
_healthModel = new HealthModel(parHealth);
}

View File

@@ -0,0 +1,80 @@
namespace DoomDeathmatch.Scene;
public static class GameConstants
{
#region Enemies
#region Demon
public const int DEMON_BASE_SCORE = 50;
public const float DEMON_BASE_HEALTH = 150;
public const float DEMON_BASE_SPEED = 8;
public const float DEMON_FOLLOW_RADIUS = 1.5f;
public const float DEMON_CLOSE_COOLDOWN_ATTACK_RADIUS = 1.75f;
public const float DEMON_CLOSE_COOLDOWN_ATTACK_COOLDOWN = 1.75f;
public const float DEMON_CLOSE_COOLDOWN_ATTACK_DAMAGE = 10f;
public const int IMP_BASE_SCORE = 200;
public const float IMP_BASE_HEALTH = 300;
public const float IMP_BASE_SPEED = 7;
public const float IMP_FOLLOW_RADIUS = 10f;
#endregion
#region Imp
public const float IMP_CLOSE_CONTINUOUS_ATTACK_RADIUS = 1.75f;
public const float IMP_CLOSE_CONTINUOUS_ATTACK_DAMAGE = 10f;
public const float IMP_FIREBALL_ATTACK_COOLDOWN = 4f;
public const float IMP_FIREBALL_ATTACK_DAMAGE = 35f;
public const float IMP_FIREBALL_ATTACK_SPEED = 25f;
public const float IMP_FIREBALL_ATTACK_SIZE = 0.5f;
#endregion
public const int ENEMY_DEMON_SPAWN_WEIGHT = 6;
public const int ENEMY_IMP_SPAWN_WEIGHT = 4;
public const float ENEMY_SPAWN_RATE_SECONDS = 2f;
#endregion
#region Weapons
#region Pistol
public const int PISTOL_MAX_AMMO = 30;
public const int PISTOL_BASE_DAMAGE = 30;
#endregion
#region Shotgun
public const int SHOTGUN_MAX_AMMO = 10;
public const int SHOTGUN_BASE_DAMAGE = 5;
public const float SHOTGUN_SHOOT_PATTERN_ANGLE_DEGREES = 10f;
public const uint SHOTGUN_SHOOT_PATTERN_COUNT = 40;
#endregion
#endregion
#region Player
public const float PLAYER_BASE_HEALTH = 100;
public const float PLAYER_BASE_SPEED = 10;
#endregion
#region Consumables
public const int CONSUMABLE_HEALTH_PACK_SPAWN_WEIGHT = 2;
public const int CONSUMABLE_WEAPON_PISTOL_SPAWN_WEIGHT = 4;
public const int CONSUMABLE_WEAPON_SHOTGUN_SPAWN_WEIGHT = 3;
public const float CONSUMABLE_SPAWN_RATE_SECONDS = 5f;
public const float HEALTH_PACK_BASE_HEALING = 75f;
#endregion
}

View File

@@ -14,20 +14,20 @@ public static class GameOverScene
{
var scene = new Engine.Scene.Scene();
var (cameraObject, camera) = UiUtil.CreateOrthographicCamera(scene);
var (cameraObject, camera) = UiPrefabs.CreateOrthographicCamera(scene);
var (uiContainerObject, uiContainer) =
UiUtil.CreateBackgroundUi(scene, new UiContainerComponent { Camera = camera });
UiPrefabs.CreateBackgroundUi(scene, new UiContainerComponent { Camera = camera });
var (logoObject, logoUi) = UiUtil.CreateLogoUi(scene, uiContainer);
var (logoObject, logoUi) = UiPrefabs.CreateLogoUi(scene, uiContainer);
logoUi.Offset = new Vector2(0, 3f);
scene.AddChild(uiContainerObject, logoObject);
var (resultUiObject, resultUi, _) =
UiUtil.CreateTextUi(scene, uiContainer, UiUtil.GetDoomFont(), $"Ваш результат: {parScore}");
UiPrefabs.CreateTextUi(scene, uiContainer, UiPrefabs.GetDoomFont(), $"Ваш результат: {parScore}");
var (nameUiObject, nameUi, (_, nameTextRenderer)) =
UiUtil.CreateTextUi(scene, uiContainer, UiUtil.GetDoomFont(), "Имя: ");
UiPrefabs.CreateTextUi(scene, uiContainer, UiPrefabs.GetDoomFont(), "Имя: ");
var nameInputComponent = new TextInputComponent { IsActive = true };
nameInputComponent.OnInput += parName =>
@@ -37,7 +37,7 @@ public static class GameOverScene
nameUiObject.AddComponent(nameInputComponent);
var (nextUiObject, nextUi, _) =
UiUtil.CreateTextUi(scene, uiContainer, UiUtil.GetDoomFont(), "Далее");
UiPrefabs.CreateTextUi(scene, uiContainer, UiPrefabs.GetDoomFont(), "Далее");
nextUi.OnClick += _ =>
{
if (string.IsNullOrEmpty(nameInputComponent.Input))
@@ -49,10 +49,10 @@ public static class GameOverScene
EngineUtil.SceneManager.TransitionTo(MainScene.Create);
};
var (selectorObject, selector) = UiUtil.CreateSelectorUi(scene,
var (selectorObject, selector) = UiPrefabs.CreateSelectorUi(scene,
new SelectorComponent { Children = { nextUi }, SelectKey = KeyboardButtonCode.Enter }, RenderLayer.HUD);
var (stackObject, stack) = UiUtil.CreateStackUi(scene,
var (stackObject, stack) = UiPrefabs.CreateStackUi(scene,
new StackComponent { Offset = new Vector2(0, -1f), Container = uiContainer, Children = { resultUi, nextUi } });
stackObject.Transform.Size.Xy = new Vector2(1f, 6f);

View File

@@ -15,12 +15,12 @@ public static class MainScene
{
var scene = new Engine.Scene.Scene();
var (cameraObject, camera) = UiUtil.CreateOrthographicCamera(scene);
var (cameraObject, camera) = UiPrefabs.CreateOrthographicCamera(scene);
var (uiContainerObject, uiContainer) =
UiUtil.CreateBackgroundUi(scene, new UiContainerComponent { Camera = camera });
UiPrefabs.CreateBackgroundUi(scene, new UiContainerComponent { Camera = camera });
var (logoObject, logoUi) = UiUtil.CreateLogoUi(scene, uiContainer);
var (logoObject, logoUi) = UiPrefabs.CreateLogoUi(scene, uiContainer);
logoUi.Offset = new Vector2(0, 3f);
scene.AddChild(uiContainerObject, logoObject);
@@ -53,18 +53,18 @@ public static class MainScene
var parentObject = GameObjectUtil.CreateGameObject(parScene);
var (playUiObject, playUi, _) =
UiUtil.CreateTextUi(parScene, parUiContainer, UiUtil.GetDoomFont(), "Играть");
UiPrefabs.CreateTextUi(parScene, parUiContainer, UiPrefabs.GetDoomFont(), "Играть");
var (leadersUiObject, leadersUi, _) =
UiUtil.CreateTextUi(parScene, parUiContainer, UiUtil.GetDoomFont(), "Лидеры");
UiPrefabs.CreateTextUi(parScene, parUiContainer, UiPrefabs.GetDoomFont(), "Лидеры");
var (rulesUiObject, rulesUi, _) =
UiUtil.CreateTextUi(parScene, parUiContainer, UiUtil.GetDoomFont(), "Правила");
UiPrefabs.CreateTextUi(parScene, parUiContainer, UiPrefabs.GetDoomFont(), "Правила");
var (exitUiObject, exitUi, _) =
UiUtil.CreateTextUi(parScene, parUiContainer, UiUtil.GetDoomFont(), "Выход");
UiPrefabs.CreateTextUi(parScene, parUiContainer, UiPrefabs.GetDoomFont(), "Выход");
var (stackObject, stack) = UiUtil.CreateStackUi(parScene,
var (stackObject, stack) = UiPrefabs.CreateStackUi(parScene,
new StackComponent
{
Offset = new Vector2(0, -1f), Container = parUiContainer, Children = { playUi, leadersUi, rulesUi, exitUi }
@@ -76,7 +76,7 @@ public static class MainScene
rulesUi.OnClick += _ => parMenuController.SelectMenuItem("rules");
exitUi.OnClick += _ => EngineUtil.Close();
var (selectorObject, selector) = UiUtil.CreateSelectorUi(parScene,
var (selectorObject, selector) = UiPrefabs.CreateSelectorUi(parScene,
new SelectorComponent { Children = { playUi, leadersUi, rulesUi, exitUi } });
parScene.AddChild(parentObject, selectorObject);
@@ -95,11 +95,11 @@ public static class MainScene
{
var parentObject = GameObjectUtil.CreateGameObject(parScene);
var (backUiObject, backUi, _) = UiUtil.CreateTextUi(parScene, parUiContainer,
UiUtil.GetDoomFont(), "Назад");
var (backUiObject, backUi, _) = UiPrefabs.CreateTextUi(parScene, parUiContainer,
UiPrefabs.GetDoomFont(), "Назад");
backUi.OnClick += _ => parMenuController.SelectMenuItem("main");
var (stackObject, stack) = UiUtil.CreateStackUi(parScene,
var (stackObject, stack) = UiPrefabs.CreateStackUi(parScene,
new StackComponent { Offset = new Vector2(0, -1.5f), Container = parUiContainer });
stackObject.Transform.Size.Xy = new Vector2(1f, 6f);
@@ -112,7 +112,7 @@ public static class MainScene
stack.Children.Add(backUi);
var (selectorObject, selector) = UiUtil.CreateSelectorUi(parScene, new SelectorComponent { Children = { backUi } });
var (selectorObject, selector) = UiPrefabs.CreateSelectorUi(parScene, new SelectorComponent { Children = { backUi } });
parScene.AddChild(parentObject, selectorObject);
parScene.AddChild(parentObject, stackObject);
@@ -153,12 +153,12 @@ public static class MainScene
]);
var (nameUiObject, nameUi, _) =
UiUtil.CreateTextUi(parScene, uiComponent, UiUtil.GetDoomFont(), parName);
UiPrefabs.CreateTextUi(parScene, uiComponent, UiPrefabs.GetDoomFont(), parName);
nameUi.Anchor = Anchor.CenterLeft;
nameUi.Center = Anchor.Center;
var (scoreUiObject, scoreUi, _) =
UiUtil.CreateTextUi(parScene, uiComponent, UiUtil.GetDoomFont(), parScore);
UiPrefabs.CreateTextUi(parScene, uiComponent, UiPrefabs.GetDoomFont(), parScore);
scoreUi.Anchor = Anchor.CenterRight;
scoreUi.Center = Anchor.Center;
@@ -173,18 +173,18 @@ public static class MainScene
{
var parentObject = GameObjectUtil.CreateGameObject(parScene);
var (backUiObject, backUi, _) = UiUtil.CreateTextUi(parScene, parUiContainer,
UiUtil.GetDoomFont(), "Назад");
var (backUiObject, backUi, _) = UiPrefabs.CreateTextUi(parScene, parUiContainer,
UiPrefabs.GetDoomFont(), "Назад");
backUi.OnClick += _ => parMenuController.SelectMenuItem("main");
var (rulesObject, rulesUi, _) = UiUtil.CreateTextUi(parScene, parUiContainer,
UiUtil.GetDoomFont(), "Правила");
var (rulesObject, rulesUi, _) = UiPrefabs.CreateTextUi(parScene, parUiContainer,
UiPrefabs.GetDoomFont(), "Правила");
var (stackObject, stack) = UiUtil.CreateStackUi(parScene,
var (stackObject, stack) = UiPrefabs.CreateStackUi(parScene,
new StackComponent { Offset = new Vector2(0, -1f), Container = parUiContainer, Children = { rulesUi, backUi } });
stackObject.Transform.Size.Xy = new Vector2(1f, 6f);
var (selectorObject, selector) = UiUtil.CreateSelectorUi(parScene, new SelectorComponent { Children = { backUi } });
var (selectorObject, selector) = UiPrefabs.CreateSelectorUi(parScene, new SelectorComponent { Children = { backUi } });
parScene.AddChild(parentObject, selectorObject);

View File

@@ -33,9 +33,9 @@ public static class PlayScene
{
var scene = new Engine.Scene.Scene();
var (hudCameraObject, hudCamera) = UiUtil.CreateOrthographicCamera(scene, RenderLayer.HUD);
var (hudCameraObject, hudCamera) = UiPrefabs.CreateOrthographicCamera(scene, RenderLayer.HUD);
var (uiContainerObject, uiContainer) =
UiUtil.CreateContainerUi(scene, new UiContainerComponent { Camera = hudCamera });
UiPrefabs.CreateContainerUi(scene, new UiContainerComponent { Camera = hudCamera });
var menuController = new MenuControllerComponent();
var menuControllerObject = GameObjectUtil.CreateGameObject(scene, [
@@ -100,14 +100,14 @@ public static class PlayScene
new ObjectSpawner(new WeightedRandomValueProvider<GameObject>(
new List<(int, IValueProvider<GameObject>)>
{
(6, GeneratorValueProvider<GameObject>.Create(() =>
(GameConstants.ENEMY_DEMON_SPAWN_WEIGHT, GeneratorValueProvider<GameObject>.Create(() =>
EnemyPrefab.Create(EngineUtil.SceneManager.CurrentScene!, EnemyData.Demon))),
(4,
(GameConstants.ENEMY_IMP_SPAWN_WEIGHT,
GeneratorValueProvider<GameObject>.Create(() =>
EnemyPrefab.Create(EngineUtil.SceneManager.CurrentScene!, EnemyData.Imp)))
}),
monsterVector3ValueProvider,
new TickableTimerCondition(2f)))
new TickableTimerCondition(GameConstants.ENEMY_SPAWN_RATE_SECONDS)))
]
);
@@ -127,16 +127,16 @@ public static class PlayScene
new ObjectSpawner(new WeightedRandomValueProvider<GameObject>(
new List<(int, IValueProvider<GameObject>)>
{
(2, GeneratorValueProvider<GameObject>.Create(() =>
(GameConstants.CONSUMABLE_HEALTH_PACK_SPAWN_WEIGHT, GeneratorValueProvider<GameObject>.Create(() =>
{
var gameController = EngineUtil.SceneManager.CurrentScene!.FindFirstComponent<GameController>()!;
return ConsumablePrefab.Create(EngineUtil.SceneManager.CurrentScene,
new HealthPackConsumable(75),
new HealthPackConsumable(GameConstants.HEALTH_PACK_BASE_HEALING),
gameController.PlayerController.Camera.GameObject.Transform
);
})),
(4, GeneratorValueProvider<GameObject>.Create(() =>
(GameConstants.CONSUMABLE_WEAPON_PISTOL_SPAWN_WEIGHT, GeneratorValueProvider<GameObject>.Create(() =>
{
var gameController = EngineUtil.SceneManager.CurrentScene!.FindFirstComponent<GameController>()!;
@@ -145,7 +145,7 @@ public static class PlayScene
gameController.PlayerController.Camera.GameObject.Transform
);
})),
(3, GeneratorValueProvider<GameObject>.Create(() =>
(GameConstants.CONSUMABLE_WEAPON_SHOTGUN_SPAWN_WEIGHT, GeneratorValueProvider<GameObject>.Create(() =>
{
var gameController = EngineUtil.SceneManager.CurrentScene!.FindFirstComponent<GameController>()!;
@@ -156,7 +156,7 @@ public static class PlayScene
}))
}),
consumableVector3ValueProvider,
new TickableTimerCondition(5f)))
new TickableTimerCondition(GameConstants.CONSUMABLE_SPAWN_RATE_SECONDS)))
]
);
@@ -216,7 +216,7 @@ public static class PlayScene
var parentObject = GameObjectUtil.CreateGameObject(parScene);
var (bottomContainerObject, bottomContainer) =
UiUtil.CreateContainerUi(parScene, new UiContainerComponent { Container = parUiContainer });
UiPrefabs.CreateContainerUi(parScene, new UiContainerComponent { Container = parUiContainer });
bottomContainer.Anchor = Anchor.BottomCenter;
bottomContainer.Center = Anchor.BottomCenter;
bottomContainerObject.AddComponent(new Box2DRenderer
@@ -230,7 +230,7 @@ public static class PlayScene
bottomContainerObject.Transform.Size.Y = 1.5f;
parScene.AddChild(parentObject, bottomContainerObject);
var (gunObject, (gunUi, gunSprite)) = UiUtil.CreateSpriteUi(parScene, bottomContainer,
var (gunObject, (gunUi, gunSprite)) = UiPrefabs.CreateSpriteUi(parScene, bottomContainer,
null, RenderLayer.HUD);
gunObject.Transform.Scale = new Vector3(5);
gunUi.Anchor = Anchor.TopCenter;
@@ -239,7 +239,7 @@ public static class PlayScene
parScene.AddChild(bottomContainerObject, gunObject);
var (healthObject, healthUi, (_, healthTextRenderer)) =
UiUtil.CreateTextUi(parScene, bottomContainer, UiUtil.GetDoomFont(), "Здоровье: 000",
UiPrefabs.CreateTextUi(parScene, bottomContainer, UiPrefabs.GetDoomFont(), "Здоровье: 000",
Align.Center,
RenderLayer.HUD);
healthObject.Transform.Scale = new Vector3(0.75f);
@@ -248,7 +248,7 @@ public static class PlayScene
parScene.AddChild(bottomContainerObject, healthObject);
var (ammoObject, ammoUi, (_, ammoTextRenderer)) =
UiUtil.CreateTextUi(parScene, bottomContainer, UiUtil.GetDoomFont(), "Патроны: 00/00",
UiPrefabs.CreateTextUi(parScene, bottomContainer, UiPrefabs.GetDoomFont(), "Патроны: 00/00",
Align.Center,
RenderLayer.HUD);
ammoObject.Transform.Scale = new Vector3(0.75f);
@@ -257,7 +257,7 @@ public static class PlayScene
parScene.AddChild(bottomContainerObject, ammoObject);
var (weaponObject, weaponUi, (_, weaponTextRenderer)) =
UiUtil.CreateTextUi(parScene, bottomContainer, UiUtil.GetDoomFont(), "Оружие: ОРУЖИЕОР",
UiPrefabs.CreateTextUi(parScene, bottomContainer, UiPrefabs.GetDoomFont(), "Оружие: ОРУЖИЕОР",
Align.Center,
RenderLayer.HUD);
weaponObject.Transform.Scale = new Vector3(0.75f);
@@ -266,7 +266,7 @@ public static class PlayScene
parScene.AddChild(bottomContainerObject, weaponObject);
var (topContainerObject, topContainer) =
UiUtil.CreateContainerUi(parScene, new UiContainerComponent { Container = parUiContainer });
UiPrefabs.CreateContainerUi(parScene, new UiContainerComponent { Container = parUiContainer });
topContainer.Anchor = Anchor.TopCenter;
topContainer.Center = Anchor.TopCenter;
topContainerObject.AddComponent(
@@ -279,14 +279,14 @@ public static class PlayScene
parScene.AddChild(parentObject, topContainerObject);
var (timerObject, timerUi, (_, timerTextRenderer)) =
UiUtil.CreateTextUi(parScene, topContainer, UiUtil.GetDoomFont(), "Время: 00:00",
UiPrefabs.CreateTextUi(parScene, topContainer, UiPrefabs.GetDoomFont(), "Время: 00:00",
parRenderLayer: RenderLayer.HUD);
timerUi.Anchor = Anchor.CenterLeft;
timerUi.Center = Anchor.CenterLeft;
parScene.AddChild(topContainerObject, timerObject);
var (scoreObject, scoreUi, (_, scoreTextRenderer)) =
UiUtil.CreateTextUi(parScene, topContainer, UiUtil.GetDoomFont(), "Счет: 00000",
UiPrefabs.CreateTextUi(parScene, topContainer, UiPrefabs.GetDoomFont(), "Счет: 00000",
parRenderLayer: RenderLayer.HUD);
scoreUi.Anchor = Anchor.CenterRight;
scoreUi.Center = Anchor.CenterRight;
@@ -305,34 +305,34 @@ public static class PlayScene
{
var parentObject = GameObjectUtil.CreateGameObject(parScene);
var (backgroundObject, backgroundUiContainer) = UiUtil.CreateBackgroundUi(parScene,
var (backgroundObject, backgroundUiContainer) = UiPrefabs.CreateBackgroundUi(parScene,
new UiContainerComponent { Container = parUiContainer }, new Vector4(0, 0, 0, 0.9f), RenderLayer.HUD);
backgroundObject.AddComponent(new CopySizeComponent { Target = parUiContainer.GameObject.Transform });
parScene.AddChild(parentObject, backgroundObject);
var (logoObject, logoUi) = UiUtil.CreateLogoUi(parScene, backgroundUiContainer, RenderLayer.HUD);
var (logoObject, logoUi) = UiPrefabs.CreateLogoUi(parScene, backgroundUiContainer, RenderLayer.HUD);
logoUi.Offset = new Vector2(0, 3f);
parScene.AddChild(parentObject, logoObject);
var (backUiObject, backUi, _) = UiUtil.CreateTextUi(parScene, backgroundUiContainer,
UiUtil.GetDoomFont(), "Назад",
var (backUiObject, backUi, _) = UiPrefabs.CreateTextUi(parScene, backgroundUiContainer,
UiPrefabs.GetDoomFont(), "Назад",
parRenderLayer: RenderLayer.HUD);
backUi.OnClick += _ =>
EngineUtil.SceneManager.CurrentScene!.FindFirstComponent<GameController>()!.Unpause();
var (exitUiObject, exitUi, _) = UiUtil.CreateTextUi(parScene, backgroundUiContainer,
UiUtil.GetDoomFont(), "Выход",
var (exitUiObject, exitUi, _) = UiPrefabs.CreateTextUi(parScene, backgroundUiContainer,
UiPrefabs.GetDoomFont(), "Выход",
parRenderLayer: RenderLayer.HUD);
exitUi.OnClick += _ => EngineUtil.SceneManager.TransitionTo(MainScene.Create);
var (stackObject, stack) = UiUtil.CreateStackUi(parScene,
var (stackObject, stack) = UiPrefabs.CreateStackUi(parScene,
new StackComponent
{
Offset = new Vector2(0, -1f), Container = backgroundUiContainer, Children = { backUi, exitUi }
});
stackObject.Transform.Size.Xy = new Vector2(1f, 6f);
var (selectorObject, selector) = UiUtil.CreateSelectorUi(parScene,
var (selectorObject, selector) = UiPrefabs.CreateSelectorUi(parScene,
new SelectorComponent { Children = { backUi, exitUi } }, RenderLayer.HUD);
parScene.AddChild(parentObject, selectorObject);

View File

@@ -21,7 +21,7 @@ public static class EnemyPrefab
{
public static GameObject Create(Engine.Scene.Scene parScene, EnemyData parEnemyData)
{
var enemyHealthTextRenderer = new TextRenderer { Font = UiUtil.GetDoomFont(), Text = "Здоровье: 000" };
var enemyHealthTextRenderer = new TextRenderer { Font = UiPrefabs.GetDoomFont(), Text = "Здоровье: 000" };
var enemyBox2DRenderer = new Box2DRenderer();
var enemyObject = GameObjectUtil.CreateGameObject(parScene,
@@ -69,13 +69,13 @@ public static class EnemyPrefab
}
public static GameObject CreateFireball(Engine.Scene.Scene parScene, Vector3 parPosition,
Vector3 parVelocity, float parDamage, Transform? parBillboardTarget = null)
Vector3 parVelocity, float parSize, float parDamage, Transform? parBillboardTarget = null)
{
var rigidbodyComponent = new RigidbodyComponent();
rigidbodyComponent.Velocity += parVelocity;
var fireballObject = GameObjectUtil.CreateGameObject(parScene,
new Transform { Translation = parPosition, Size = new Vector3(0.5f) },
new Transform { Translation = parPosition, Size = new Vector3(parSize) },
[
rigidbodyComponent,
new Box2DRenderer { Texture = EngineUtil.AssetResourceManager.Load<Texture>("texture/fireball.png") },
@@ -83,7 +83,7 @@ public static class EnemyPrefab
new FireballComponent { Damage = parDamage },
new AABBColliderComponent
{
Collider = new AABBCollider { Size = new Vector3(0.25f) },
Collider = new AABBCollider { Size = new Vector3(parSize) },
ColliderGroups = { "fireball" },
ExcludeColliderCollideGroups = { "enemy", "fireball", "consumable" }
}

View File

@@ -14,12 +14,12 @@ public static class PlayerPrefab
{
public static GameObject Create(Engine.Scene.Scene parScene, WeaponView parWeaponView, HealthView parHealthView)
{
var (perspectiveCameraObject, perspectiveCamera) = UiUtil.CreatePerspectiveCamera(parScene);
var (perspectiveCameraObject, perspectiveCamera) = UiPrefabs.CreatePerspectiveCamera(parScene);
perspectiveCameraObject.Transform.Translation.Z = 2;
var playerObject = GameObjectUtil.CreateGameObject(parScene, [
new PlayerMovementComponent(),
new MovementController { Speed = 10f },
new MovementController { Speed = GameConstants.PLAYER_BASE_SPEED },
new RigidbodyComponent(),
new DragComponent { Drag = 10f, Multiplier = new Vector3(1, 1, 0) },
@@ -36,7 +36,7 @@ public static class PlayerPrefab
new WeaponController(),
parWeaponView,
new HealthController(),
new HealthController(GameConstants.PLAYER_BASE_HEALTH),
parHealthView
]);

View File

@@ -9,9 +9,9 @@ using Engine.Scene.Component.BuiltIn.Renderer;
using Engine.Util;
using OpenTK.Mathematics;
namespace DoomDeathmatch;
namespace DoomDeathmatch.Scene;
public static class UiUtil
public static class UiPrefabs
{
public static Font GetDoomFont()
{
@@ -52,10 +52,10 @@ public static class UiUtil
};
var uiComponent = new UiContainerComponent { Container = parContainer };
outerObject.AddComponent(uiComponent);
outerObject.AddComponent(new Box2DRenderer
{
Color = new Vector4(0, 0, 1, 1), RenderLayer = parRenderLayer ?? RenderLayer.DEFAULT
});
// outerObject.AddComponent(new Box2DRenderer
// {
// Color = new Vector4(0, 0, 1, 1), RenderLayer = parRenderLayer ?? RenderLayer.DEFAULT
// });
var innerObject = new GameObject { Transform = { Translation = new Vector3(0, 0, -1) } };
// var innerUiComponent = new UiComponent { Container = uiComponent };

View File

@@ -1,5 +1,6 @@
using DoomDeathmatch.Component.MVC.Enemy;
using DoomDeathmatch.Component.MVC.Health;
using DoomDeathmatch.Script.Provider;
using Engine.Scene;
using Engine.Util;
@@ -13,7 +14,7 @@ public class ObjectSpawnAttackBehavior : CooldownAttackBehavior
/// <summary>
/// The function used to spawn an object based on the enemy and target controllers.
/// </summary>
private readonly Func<EnemyController, HealthController, GameObject> _objectSpawnFunc;
private readonly IValueProvider<GameObject> _objectValueProvider;
/// <summary>
/// Initializes a new instance of the <see cref="ObjectSpawnAttackBehavior"/> class.
@@ -21,14 +22,14 @@ public class ObjectSpawnAttackBehavior : CooldownAttackBehavior
/// <param name="parEnemyController">The enemy controller.</param>
/// <param name="parHealthController">The health controller of the target.</param>
/// <param name="parCooldown">The cooldown duration between spawns.</param>
/// <param name="parObjectSpawnFunc">The function used to create the spawned object.</param>
/// <param name="parObjectValueProvider">The function used to create the spawned object.</param>
public ObjectSpawnAttackBehavior(EnemyController parEnemyController,
HealthController parHealthController,
float parCooldown,
Func<EnemyController, HealthController, GameObject> parObjectSpawnFunc) : base(parEnemyController,
IValueProvider<GameObject> parObjectValueProvider) : base(parEnemyController,
parHealthController, parCooldown)
{
_objectSpawnFunc = parObjectSpawnFunc;
_objectValueProvider = parObjectValueProvider;
}
/// <inheritdoc />
@@ -40,7 +41,7 @@ public class ObjectSpawnAttackBehavior : CooldownAttackBehavior
/// <inheritdoc />
protected override bool ActivateAttack()
{
var enemyObject = _objectSpawnFunc(_enemyController, _healthController);
var enemyObject = _objectValueProvider.GetValue();
EngineUtil.SceneManager.CurrentScene!.Add(enemyObject);
return true;

View File

@@ -1,6 +1,9 @@
using DoomDeathmatch.Scene.Play.Prefab;
using DoomDeathmatch.Scene;
using DoomDeathmatch.Scene.Play.Prefab;
using DoomDeathmatch.Script.Model.Enemy.Attack;
using DoomDeathmatch.Script.Model.Enemy.Movement;
using DoomDeathmatch.Script.Provider;
using Engine.Scene;
using Engine.Util;
using OpenTK.Mathematics;
@@ -20,13 +23,16 @@ public class EnemyData
Id = "demon",
Name = "Демон",
Texture = "texture/demon.png",
BaseHealth = 150,
BaseScore = 50,
BaseSpeed = 8,
MovementBehavior = new FollowPlayerMovementBehavior(1.5f),
BaseScore = GameConstants.DEMON_BASE_SCORE,
BaseHealth = GameConstants.DEMON_BASE_HEALTH,
BaseSpeed = GameConstants.DEMON_BASE_SPEED,
MovementBehavior = new FollowPlayerMovementBehavior(GameConstants.DEMON_FOLLOW_RADIUS),
AttackBehaviorCreator = new FuncAttackBehaviorCreator(
(parEnemyController, parHealthController) =>
new CloseCooldownAttackBehavior(parEnemyController, parHealthController, 1.75f, 2.5f, 10)
new CloseCooldownAttackBehavior(parEnemyController, parHealthController,
GameConstants.DEMON_CLOSE_COOLDOWN_ATTACK_RADIUS,
GameConstants.DEMON_CLOSE_COOLDOWN_ATTACK_COOLDOWN,
GameConstants.DEMON_CLOSE_COOLDOWN_ATTACK_DAMAGE)
)
};
@@ -39,31 +45,36 @@ public class EnemyData
Id = "imp",
Name = "Имп",
Texture = "texture/imp.png",
BaseHealth = 300,
BaseScore = 200,
BaseSpeed = 7,
MovementBehavior = new FollowPlayerMovementBehavior(10f),
BaseScore = GameConstants.IMP_BASE_SCORE,
BaseHealth = GameConstants.IMP_BASE_HEALTH,
BaseSpeed = GameConstants.IMP_BASE_SPEED,
MovementBehavior = new FollowPlayerMovementBehavior(GameConstants.IMP_FOLLOW_RADIUS),
AttackBehaviorCreator = new FuncAttackBehaviorCreator(
(parEnemyController, parHealthController) =>
new CompositeAttackBehavior(parEnemyController, parHealthController,
[
new CloseContinuousAttackBehavior(parEnemyController, parHealthController, 1.75f, 10f),
new ObjectSpawnAttackBehavior(parEnemyController, parHealthController, 4f,
(parEnemyController, parHealthController) =>
new CloseContinuousAttackBehavior(parEnemyController, parHealthController,
GameConstants.IMP_CLOSE_CONTINUOUS_ATTACK_RADIUS,
GameConstants.IMP_CLOSE_CONTINUOUS_ATTACK_DAMAGE),
new ObjectSpawnAttackBehavior(parEnemyController, parHealthController,
GameConstants.IMP_FIREBALL_ATTACK_COOLDOWN,
GeneratorValueProvider<GameObject>.Create(() =>
{
var direction =
(parHealthController.GameObject.Transform.Translation -
parEnemyController.GameObject.Transform.Translation).Normalized();
var fireballObject = EnemyPrefab.CreateFireball(EngineUtil.SceneManager.CurrentScene!,
var fireballObject = EnemyPrefab.CreateFireball(
EngineUtil.SceneManager.CurrentScene!,
parEnemyController.GameObject.Transform.Translation + new Vector3(0, 0f, 1.75f),
direction * 25,
35,
GameConstants.IMP_FIREBALL_ATTACK_SPEED * direction,
GameConstants.IMP_FIREBALL_ATTACK_SIZE,
GameConstants.IMP_FIREBALL_ATTACK_DAMAGE,
parHealthController.GameObject.Transform
);
return fireballObject;
}
})
)
]
)
@@ -85,16 +96,16 @@ public class EnemyData
/// </summary>
public string Texture { get; private init; } = "";
/// <summary>
/// The base health of the enemy.
/// </summary>
public float BaseHealth { get; private init; }
/// <summary>
/// The base score awarded for defeating this enemy.
/// </summary>
public int BaseScore { get; private init; }
/// <summary>
/// The base health of the enemy.
/// </summary>
public float BaseHealth { get; private init; }
/// <summary>
/// The base speed of the enemy.
/// </summary>

View File

@@ -1,4 +1,5 @@
using OpenTK.Mathematics;
using DoomDeathmatch.Scene;
using OpenTK.Mathematics;
namespace DoomDeathmatch.Script.Model.Weapon;
@@ -11,17 +12,20 @@ public class WeaponData
/// Data for the "Pistol" weapon.
/// </summary>
public static WeaponData Pistol =>
new(30)
new(GameConstants.PISTOL_MAX_AMMO)
{
Id = "pistol",
Name = "Пистолет",
Damage = GameConstants.PISTOL_BASE_DAMAGE,
IdleTexture = "texture/pistol/idle.png",
FireAnimationDuration = 0.25f,
FireAnimation =
{
"texture/pistol/fire1.png", "texture/pistol/fire2.png", "texture/pistol/fire3.png", "texture/pistol/fire4.png"
"texture/pistol/fire1.png",
"texture/pistol/fire2.png",
"texture/pistol/fire3.png",
"texture/pistol/fire4.png"
},
Damage = 30,
ShootPattern = new LineShootPattern()
};
@@ -29,15 +33,18 @@ public class WeaponData
/// Data for the "Shotgun" weapon.
/// </summary>
public static WeaponData Shotgun =>
new(10)
new(GameConstants.SHOTGUN_MAX_AMMO)
{
Id = "shotgun",
Name = "Дробовик",
Damage = GameConstants.SHOTGUN_BASE_DAMAGE,
IdleTexture = "texture/shotgun/idle.png",
FireAnimationDuration = 0.1f,
FireAnimation = { "texture/shotgun/fire1.png", "texture/shotgun/fire2.png" },
Damage = 5,
ShootPattern = new RandomFlatSpreadShootPattern(MathHelper.DegreesToRadians(10), 40)
ShootPattern =
new RandomFlatSpreadShootPattern(
MathHelper.DegreesToRadians(GameConstants.SHOTGUN_SHOOT_PATTERN_ANGLE_DEGREES),
GameConstants.SHOTGUN_SHOOT_PATTERN_COUNT)
};
/// <summary>

View File

@@ -46,10 +46,6 @@ public class ObjectSpawner : IUpdate
_condition.OnTrue += Spawn;
}
/// <summary>
/// Updates the state of the spawner, evaluating the condition to determine if a new object should spawn.
/// </summary>
/// <param name="parDeltaTime">The time elapsed since the last update, in seconds.</param>
public void Update(double parDeltaTime)
{
_condition.Update(parDeltaTime);