.
This commit is contained in:
@@ -10,8 +10,4 @@
|
||||
<ProjectReference Include="..\Engine\Engine.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="src\Scene\Play\" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 47 KiB |
File diff suppressed because it is too large
Load Diff
101
DoomDeathmatch/asset/model/map.obj
Normal file
101
DoomDeathmatch/asset/model/map.obj
Normal file
@@ -0,0 +1,101 @@
|
||||
# Blender 4.2.3 LTS
|
||||
# www.blender.org
|
||||
o Plane
|
||||
v -14.316629 -4.684887 0.000000
|
||||
v 14.316629 -4.684887 0.000000
|
||||
v -14.316629 4.684887 0.000000
|
||||
v 14.316629 4.684887 0.000000
|
||||
v 6.822107 -4.684887 0.000000
|
||||
v 6.822107 4.684887 0.000000
|
||||
v 14.316629 33.607601 0.000000
|
||||
v 6.822107 33.607601 0.000000
|
||||
v 14.316629 25.280016 0.000000
|
||||
v 6.822107 25.280016 0.000000
|
||||
v -6.847844 33.607601 0.000000
|
||||
v -6.847844 25.280016 0.000000
|
||||
v -25.254845 24.277735 0.000000
|
||||
v -18.173466 20.114567 0.000000
|
||||
v -26.336294 7.837210 0.000000
|
||||
v -19.225933 10.395360 0.000000
|
||||
v -14.316629 -4.684887 3.000000
|
||||
v 14.316629 -4.684887 3.000000
|
||||
v 14.316629 4.684887 3.000000
|
||||
v 6.822107 -4.684887 3.000000
|
||||
v 14.316629 33.607601 3.000000
|
||||
v 6.822107 33.607601 3.000000
|
||||
v 14.316629 25.280016 3.000000
|
||||
v -6.847844 33.607601 3.000000
|
||||
v -25.254845 24.277735 3.000000
|
||||
v -26.336294 7.837210 3.000000
|
||||
v -14.316629 4.684887 3.000000
|
||||
v 6.822107 4.684887 3.000000
|
||||
v 6.822107 25.280016 3.000000
|
||||
v -6.847844 25.280016 3.000000
|
||||
v -18.173466 20.114567 3.000000
|
||||
v -19.225933 10.395360 3.000000
|
||||
vn -0.0000 -0.0000 1.0000
|
||||
vn -1.0000 -0.0000 -0.0000
|
||||
vn 0.7214 0.6925 -0.0000
|
||||
vn 0.9978 -0.0656 -0.0000
|
||||
vn 0.4521 -0.8920 -0.0000
|
||||
vn -0.0000 -1.0000 -0.0000
|
||||
vn -0.0000 1.0000 -0.0000
|
||||
vn -0.7583 -0.6519 -0.0000
|
||||
vn 1.0000 -0.0000 -0.0000
|
||||
vn -0.4150 0.9098 -0.0000
|
||||
vn -0.9942 0.1077 -0.0000
|
||||
vt 1.000000 0.000000
|
||||
vt 0.738258 1.000000
|
||||
vt 0.738258 0.000000
|
||||
vt 0.000000 1.000000
|
||||
vt 0.000000 0.000000
|
||||
vt 1.000000 1.000000
|
||||
s 0
|
||||
f 2/1/1 6/2/1 5/3/1
|
||||
f 5/3/1 3/4/1 1/5/1
|
||||
f 9/6/1 8/2/1 10/2/1
|
||||
f 4/6/1 10/2/1 6/2/1
|
||||
f 8/2/1 12/2/1 10/2/1
|
||||
f 11/2/1 14/2/1 12/2/1
|
||||
f 14/2/1 15/2/1 16/2/1
|
||||
f 3/4/1 15/2/1 1/5/1
|
||||
f 2/1/2 19/6/2 4/6/2
|
||||
f 15/2/3 17/5/3 1/5/3
|
||||
f 13/2/4 26/2/4 15/2/4
|
||||
f 4/6/2 23/6/2 9/6/2
|
||||
f 11/2/5 25/2/5 13/2/5
|
||||
f 7/6/6 22/2/6 8/2/6
|
||||
f 8/2/6 24/2/6 11/2/6
|
||||
f 1/5/7 20/3/7 5/3/7
|
||||
f 5/3/7 18/1/7 2/1/7
|
||||
f 9/6/2 21/6/2 7/6/2
|
||||
f 12/2/7 29/2/7 10/2/7
|
||||
f 3/4/8 32/2/8 16/2/8
|
||||
f 10/2/9 28/2/9 6/2/9
|
||||
f 14/2/10 30/2/10 12/2/10
|
||||
f 6/2/6 27/4/6 3/4/6
|
||||
f 16/2/11 31/2/11 14/2/11
|
||||
f 2/1/1 4/6/1 6/2/1
|
||||
f 5/3/1 6/2/1 3/4/1
|
||||
f 9/6/1 7/6/1 8/2/1
|
||||
f 4/6/1 9/6/1 10/2/1
|
||||
f 8/2/1 11/2/1 12/2/1
|
||||
f 11/2/1 13/2/1 14/2/1
|
||||
f 14/2/1 13/2/1 15/2/1
|
||||
f 3/4/1 16/2/1 15/2/1
|
||||
f 2/1/2 18/1/2 19/6/2
|
||||
f 15/2/3 26/2/3 17/5/3
|
||||
f 13/2/4 25/2/4 26/2/4
|
||||
f 4/6/2 19/6/2 23/6/2
|
||||
f 11/2/5 24/2/5 25/2/5
|
||||
f 7/6/6 21/6/6 22/2/6
|
||||
f 8/2/6 22/2/6 24/2/6
|
||||
f 1/5/7 17/5/7 20/3/7
|
||||
f 5/3/7 20/3/7 18/1/7
|
||||
f 9/6/2 23/6/2 21/6/2
|
||||
f 12/2/7 30/2/7 29/2/7
|
||||
f 3/4/8 27/4/8 32/2/8
|
||||
f 10/2/9 29/2/9 28/2/9
|
||||
f 14/2/10 31/2/10 30/2/10
|
||||
f 6/2/6 28/2/6 27/4/6
|
||||
f 16/2/11 32/2/11 31/2/11
|
||||
BIN
DoomDeathmatch/asset/texture/demon.png
Normal file
BIN
DoomDeathmatch/asset/texture/demon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 29 KiB |
BIN
DoomDeathmatch/asset/texture/imp.png
Normal file
BIN
DoomDeathmatch/asset/texture/imp.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 46 KiB |
BIN
DoomDeathmatch/asset/texture/pistol.png
Normal file
BIN
DoomDeathmatch/asset/texture/pistol.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 32 KiB |
BIN
DoomDeathmatch/asset/texture/shotgun.png
Normal file
BIN
DoomDeathmatch/asset/texture/shotgun.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
@@ -1,33 +0,0 @@
|
||||
namespace DoomDeathmatch.Component;
|
||||
|
||||
public class HealthComponent : Engine.Scene.Component.Component
|
||||
{
|
||||
public float MaxHealth { get; set; } = 100;
|
||||
public float Health { get; private set; } = 100;
|
||||
public event Action<HealthComponent>? HealthChanged;
|
||||
public event Action<HealthComponent>? Died;
|
||||
|
||||
public void TakeDamage(float parDamage)
|
||||
{
|
||||
Health -= parDamage;
|
||||
if (Health <= 0)
|
||||
{
|
||||
Died?.Invoke(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
HealthChanged?.Invoke(this);
|
||||
}
|
||||
}
|
||||
|
||||
public void Heal(float parHeal)
|
||||
{
|
||||
Health += parHeal;
|
||||
if (Health > MaxHealth)
|
||||
{
|
||||
Health = MaxHealth;
|
||||
}
|
||||
|
||||
HealthChanged?.Invoke(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using DoomDeathmatch.Component.MVC.Model;
|
||||
using DoomDeathmatch.Component.MVC.View;
|
||||
|
||||
namespace DoomDeathmatch.Component.MVC.Controller;
|
||||
|
||||
public class HealthController : Engine.Scene.Component.Component
|
||||
{
|
||||
private readonly HealthModel _healthModel = new(100);
|
||||
private HealthView? _healthView;
|
||||
|
||||
public override void Awake()
|
||||
{
|
||||
_healthView = GameObject.GetComponent<HealthView>();
|
||||
|
||||
if (_healthView != null)
|
||||
{
|
||||
_healthView.UpdateView(_healthModel);
|
||||
_healthModel.HealthChanged += _healthView.UpdateView;
|
||||
}
|
||||
}
|
||||
|
||||
public void TakeDamage(float parDamage)
|
||||
{
|
||||
_healthModel.Health -= parDamage;
|
||||
}
|
||||
|
||||
public void Heal(float parHeal)
|
||||
{
|
||||
_healthModel.Health += parHeal;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
using DoomDeathmatch.Component.MVC.Model;
|
||||
using Engine.Input;
|
||||
|
||||
namespace DoomDeathmatch.Component.MVC.Controller;
|
||||
|
||||
public class PlayerController : Engine.Scene.Component.Component
|
||||
{
|
||||
private readonly IInputHandler _inputHandler = Engine.Engine.Instance.InputHandler!;
|
||||
|
||||
private HealthController _healthController = null!;
|
||||
private WeaponController _weaponController = null!;
|
||||
private ScoreController _scoreController = null!;
|
||||
|
||||
public override void Awake()
|
||||
{
|
||||
_healthController = GameObject.GetComponent<HealthController>()!;
|
||||
_weaponController = GameObject.GetComponent<WeaponController>()!;
|
||||
_scoreController = GameObject.GetComponent<ScoreController>()!;
|
||||
|
||||
ArgumentNullException.ThrowIfNull(_healthController);
|
||||
ArgumentNullException.ThrowIfNull(_weaponController);
|
||||
ArgumentNullException.ThrowIfNull(_scoreController);
|
||||
}
|
||||
|
||||
public override void Update(double parDeltaTime)
|
||||
{
|
||||
if (_inputHandler.IsKeyJustPressed(KeyboardButtonCode.C))
|
||||
_weaponController.AddWeapon(WeaponData.Shotgun);
|
||||
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
if (KeyboardButtonCode.D1 + i > KeyboardButtonCode.D0)
|
||||
break;
|
||||
|
||||
if (!_inputHandler.IsKeyJustPressed(KeyboardButtonCode.D1 + i))
|
||||
continue;
|
||||
|
||||
_weaponController.SelectWeapon(i);
|
||||
break;
|
||||
}
|
||||
|
||||
if (_inputHandler.IsKeyJustPressed(KeyboardButtonCode.Space))
|
||||
_weaponController.TryShoot();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using DoomDeathmatch.Component.MVC.Model;
|
||||
using DoomDeathmatch.Component.MVC.View;
|
||||
|
||||
namespace DoomDeathmatch.Component.MVC.Controller;
|
||||
|
||||
public class ScoreController : Engine.Scene.Component.Component
|
||||
{
|
||||
private readonly ScoreModel _scoreModel = new();
|
||||
private ScoreView _scoreView = null!;
|
||||
|
||||
public override void Awake()
|
||||
{
|
||||
_scoreView = GameObject.GetComponent<ScoreView>()!;
|
||||
_scoreView.UpdateView(_scoreModel);
|
||||
_scoreModel.ScoreChanged += _scoreView.UpdateView;
|
||||
}
|
||||
|
||||
public void AddScore(int parScore)
|
||||
{
|
||||
_scoreModel.Score += parScore;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
using DoomDeathmatch.Component.MVC.Model;
|
||||
using DoomDeathmatch.Component.MVC.View;
|
||||
|
||||
namespace DoomDeathmatch.Component.MVC.Controller;
|
||||
|
||||
public class WeaponController : Engine.Scene.Component.Component
|
||||
{
|
||||
public event Action<WeaponData>? OnWeaponShot;
|
||||
|
||||
private readonly WeaponModel _weaponModel = new();
|
||||
private WeaponView _weaponView = null!;
|
||||
|
||||
public override void Awake()
|
||||
{
|
||||
_weaponView = GameObject.GetComponent<WeaponView>()!;
|
||||
_weaponView.UpdateView(_weaponModel.SelectedWeapon);
|
||||
|
||||
_weaponModel.OnWeaponSelected += WeaponSelected;
|
||||
WeaponSelected(null, _weaponModel.SelectedWeapon);
|
||||
}
|
||||
|
||||
public bool TryShoot()
|
||||
{
|
||||
if (_weaponModel.SelectedWeapon.Ammo <= 0)
|
||||
return false;
|
||||
|
||||
_weaponModel.SelectedWeapon.Ammo--;
|
||||
|
||||
OnWeaponShot?.Invoke(_weaponModel.SelectedWeapon);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Reload()
|
||||
{
|
||||
_weaponModel.SelectedWeapon.Ammo = _weaponModel.SelectedWeapon.MaxAmmo;
|
||||
}
|
||||
|
||||
public void AddWeapon(WeaponData parWeaponData)
|
||||
{
|
||||
if (_weaponModel.Weapons.Contains(parWeaponData))
|
||||
return;
|
||||
|
||||
_weaponModel.Weapons.Add(parWeaponData);
|
||||
}
|
||||
|
||||
public void RemoveWeapon(int parIndex)
|
||||
{
|
||||
if (parIndex <= 0 || parIndex >= _weaponModel.Weapons.Count)
|
||||
return;
|
||||
|
||||
var newSelectedIndex = parIndex >= _weaponModel.SelectedWeaponIndex ? _weaponModel.SelectedWeaponIndex : 0;
|
||||
|
||||
_weaponModel.SelectedWeaponIndex = newSelectedIndex;
|
||||
_weaponModel.Weapons.RemoveAt(parIndex);
|
||||
}
|
||||
|
||||
public void SelectWeapon(int parIndex)
|
||||
{
|
||||
if (parIndex >= _weaponModel.Weapons.Count)
|
||||
return;
|
||||
|
||||
_weaponModel.SelectedWeaponIndex = parIndex;
|
||||
}
|
||||
|
||||
private void WeaponSelected(WeaponData? parOldWeapon, WeaponData parNewWeapon)
|
||||
{
|
||||
if (parOldWeapon != null)
|
||||
parOldWeapon.OnAmmoChanged -= _weaponView.UpdateAmmoView;
|
||||
|
||||
parNewWeapon.OnAmmoChanged += _weaponView.UpdateAmmoView;
|
||||
_weaponView.UpdateView(parNewWeapon);
|
||||
}
|
||||
}
|
||||
35
DoomDeathmatch/src/Component/MVC/Model/HealthModel.cs
Normal file
35
DoomDeathmatch/src/Component/MVC/Model/HealthModel.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
namespace DoomDeathmatch.Component.MVC.Model;
|
||||
|
||||
public class HealthModel
|
||||
{
|
||||
public float MaxHealth
|
||||
{
|
||||
get => _maxHealth;
|
||||
set
|
||||
{
|
||||
_maxHealth = Math.Max(value, 1);
|
||||
HealthChanged?.Invoke(this);
|
||||
}
|
||||
}
|
||||
|
||||
public float Health
|
||||
{
|
||||
get => _health;
|
||||
set
|
||||
{
|
||||
_health = Math.Clamp(value, 0, MaxHealth);
|
||||
HealthChanged?.Invoke(this);
|
||||
}
|
||||
}
|
||||
|
||||
public event Action<HealthModel>? HealthChanged;
|
||||
|
||||
private float _health;
|
||||
private float _maxHealth;
|
||||
|
||||
public HealthModel(float parMaxHealth)
|
||||
{
|
||||
MaxHealth = parMaxHealth;
|
||||
Health = parMaxHealth;
|
||||
}
|
||||
}
|
||||
18
DoomDeathmatch/src/Component/MVC/Model/ScoreModel.cs
Normal file
18
DoomDeathmatch/src/Component/MVC/Model/ScoreModel.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
namespace DoomDeathmatch.Component.MVC.Model;
|
||||
|
||||
public class ScoreModel
|
||||
{
|
||||
public event Action<ScoreModel>? ScoreChanged;
|
||||
|
||||
public int Score
|
||||
{
|
||||
get => _score;
|
||||
set
|
||||
{
|
||||
_score = Math.Max(value, 0);
|
||||
ScoreChanged?.Invoke(this);
|
||||
}
|
||||
}
|
||||
|
||||
private int _score;
|
||||
}
|
||||
54
DoomDeathmatch/src/Component/MVC/Model/WeaponData.cs
Normal file
54
DoomDeathmatch/src/Component/MVC/Model/WeaponData.cs
Normal file
@@ -0,0 +1,54 @@
|
||||
namespace DoomDeathmatch.Component.MVC.Model;
|
||||
|
||||
public class WeaponData
|
||||
{
|
||||
public static WeaponData Pistol =>
|
||||
new(30) { Id = "pistol", Name = "Пистолет", Texture = "texture/pistol.png", Damage = 10 };
|
||||
|
||||
public static WeaponData Shotgun =>
|
||||
new(10) { Id = "shotgun", Name = "Дробовик", Texture = "texture/shotgun.png", Damage = 50 };
|
||||
|
||||
public string Id { get; private init; } = "";
|
||||
public string Name { get; private init; } = "";
|
||||
public string Texture { get; private init; } = "";
|
||||
public int Damage { get; private init; }
|
||||
public int MaxAmmo { get; }
|
||||
|
||||
public int Ammo
|
||||
{
|
||||
get => _ammo;
|
||||
set
|
||||
{
|
||||
if (value < 0)
|
||||
value = 0;
|
||||
if (value > MaxAmmo)
|
||||
value = MaxAmmo;
|
||||
|
||||
if (_ammo == value)
|
||||
return;
|
||||
|
||||
_ammo = value;
|
||||
OnAmmoChanged?.Invoke(this);
|
||||
}
|
||||
}
|
||||
|
||||
public event Action<WeaponData>? OnAmmoChanged;
|
||||
|
||||
private int _ammo;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
29
DoomDeathmatch/src/Component/MVC/Model/WeaponModel.cs
Normal file
29
DoomDeathmatch/src/Component/MVC/Model/WeaponModel.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
namespace DoomDeathmatch.Component.MVC.Model;
|
||||
|
||||
public class WeaponModel
|
||||
{
|
||||
public event Action<WeaponData, WeaponData>? OnWeaponSelected;
|
||||
|
||||
public IList<WeaponData> Weapons => _weapons;
|
||||
|
||||
public WeaponData SelectedWeapon => _weapons[_selectedWeaponIndex];
|
||||
|
||||
public int SelectedWeaponIndex
|
||||
{
|
||||
get => _selectedWeaponIndex;
|
||||
set
|
||||
{
|
||||
value = Math.Clamp(value, 0, _weapons.Count - 1);
|
||||
|
||||
if (_selectedWeaponIndex == value)
|
||||
return;
|
||||
|
||||
var oldSelectedWeapon = SelectedWeapon;
|
||||
_selectedWeaponIndex = value;
|
||||
OnWeaponSelected?.Invoke(oldSelectedWeapon, SelectedWeapon);
|
||||
}
|
||||
}
|
||||
|
||||
private readonly List<WeaponData> _weapons = [WeaponData.Pistol];
|
||||
private int _selectedWeaponIndex = 0;
|
||||
}
|
||||
23
DoomDeathmatch/src/Component/MVC/View/HealthView.cs
Normal file
23
DoomDeathmatch/src/Component/MVC/View/HealthView.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using DoomDeathmatch.Component.MVC.Model;
|
||||
using Engine.Scene.Component.BuiltIn.Renderer;
|
||||
|
||||
namespace DoomDeathmatch.Component.MVC.View;
|
||||
|
||||
public class HealthView : Engine.Scene.Component.Component
|
||||
{
|
||||
private readonly TextRenderer _healthTextRenderer;
|
||||
|
||||
public HealthView(TextRenderer parHealthTextRenderer)
|
||||
{
|
||||
_healthTextRenderer = parHealthTextRenderer;
|
||||
}
|
||||
|
||||
public void UpdateView(HealthModel parHealthModel)
|
||||
{
|
||||
var percentage = parHealthModel.Health / parHealthModel.MaxHealth * 100;
|
||||
if (parHealthModel.Health != 0)
|
||||
percentage = Math.Max(1, percentage);
|
||||
|
||||
_healthTextRenderer.Text = $"Здоровье: {percentage:000}";
|
||||
}
|
||||
}
|
||||
19
DoomDeathmatch/src/Component/MVC/View/ScoreView.cs
Normal file
19
DoomDeathmatch/src/Component/MVC/View/ScoreView.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using DoomDeathmatch.Component.MVC.Model;
|
||||
using Engine.Scene.Component.BuiltIn.Renderer;
|
||||
|
||||
namespace DoomDeathmatch.Component.MVC.View;
|
||||
|
||||
public class ScoreView : Engine.Scene.Component.Component
|
||||
{
|
||||
private readonly TextRenderer _scoreTextRenderer;
|
||||
|
||||
public ScoreView(TextRenderer parScoreTextRenderer)
|
||||
{
|
||||
_scoreTextRenderer = parScoreTextRenderer;
|
||||
}
|
||||
|
||||
public void UpdateView(ScoreModel parScoreModel)
|
||||
{
|
||||
_scoreTextRenderer.Text = $"Счет: {parScoreModel.Score:00000}";
|
||||
}
|
||||
}
|
||||
31
DoomDeathmatch/src/Component/MVC/View/WeaponView.cs
Normal file
31
DoomDeathmatch/src/Component/MVC/View/WeaponView.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using DoomDeathmatch.Component.MVC.Model;
|
||||
using Engine.Graphics.Texture;
|
||||
using Engine.Scene.Component.BuiltIn.Renderer;
|
||||
|
||||
namespace DoomDeathmatch.Component.MVC.View;
|
||||
|
||||
public class WeaponView : Engine.Scene.Component.Component
|
||||
{
|
||||
private readonly TextRenderer _weaponName;
|
||||
private readonly TextRenderer _weaponAmmo;
|
||||
private readonly Box2DRenderer _weaponSprite;
|
||||
|
||||
public WeaponView(TextRenderer parWeaponName, TextRenderer parWeaponAmmo, Box2DRenderer parWeaponSprite)
|
||||
{
|
||||
_weaponName = parWeaponName;
|
||||
_weaponAmmo = parWeaponAmmo;
|
||||
_weaponSprite = parWeaponSprite;
|
||||
}
|
||||
|
||||
public void UpdateView(WeaponData parWeaponData)
|
||||
{
|
||||
UpdateAmmoView(parWeaponData);
|
||||
_weaponName.Text = $"Оружие: {parWeaponData.Name}";
|
||||
_weaponSprite.Texture = Engine.Engine.Instance.AssetResourceManager.Load<Texture>(parWeaponData.Texture);
|
||||
}
|
||||
|
||||
public void UpdateAmmoView(WeaponData parWeaponData)
|
||||
{
|
||||
_weaponAmmo.Text = $"Патроны: {parWeaponData.Ammo}/{parWeaponData.MaxAmmo}";
|
||||
}
|
||||
}
|
||||
@@ -67,7 +67,7 @@ public class SelectorComponent : Engine.Scene.Component.Component
|
||||
var scale = transformMatrix.ExtractScale();
|
||||
|
||||
GameObject.Transform.Translation = translation;
|
||||
GameObject.Transform.Translation.X -= scale.X / 2 + 0.05f;
|
||||
GameObject.Transform.Translation.X -= scale.X / 2;
|
||||
|
||||
GameObject.Transform.Size.Y = scale.Y;
|
||||
}
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
using Engine.Input;
|
||||
using Engine.Scene.Component.BuiltIn;
|
||||
|
||||
namespace DoomDeathmatch.Component.UI;
|
||||
|
||||
public class TestComponent : Engine.Scene.Component.Component
|
||||
{
|
||||
private readonly IInputHandler _inputHandler = Engine.Engine.Instance.InputHandler!;
|
||||
public Camera? Camera { get; set; }
|
||||
|
||||
public override void Update(double parDeltaTime)
|
||||
{
|
||||
if (Camera == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
GameObject.Transform.Size.Xy = 2 * Camera.ScreenToWorld(_inputHandler.MousePosition).Xy;
|
||||
}
|
||||
}
|
||||
@@ -27,9 +27,7 @@ public class TextAlignComponent : Engine.Scene.Component.Component
|
||||
_cachedText = _textRenderer.Text;
|
||||
var font = _textRenderer.Font;
|
||||
var size = font.Measure(_textRenderer.Text);
|
||||
var scale = GameObject.Transform.FullTransformMatrix.ExtractScale();
|
||||
var offset = GetOffset(size) + new Vector2(0, font.Metadata.Metrics.LineHeight - font.Metadata.Metrics.Ascender) / 2;
|
||||
offset *= scale.Xy;
|
||||
var offset = GetOffset(size) + new Vector2(0, _textRenderer.Font.Metadata.Metrics.Descender / 4);
|
||||
|
||||
GameObject.Transform.Translation.Xy = offset;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ public class UiComponent : Engine.Scene.Component.Component
|
||||
public UiContainerComponent? Container { get; set; }
|
||||
public Anchor Anchor { get; set; } = Anchor.Center;
|
||||
public Vector2 Offset { get; set; } = Vector2.Zero;
|
||||
public Vector2 Center { get; set; } = Vector2.Zero;
|
||||
public Anchor Center { get; set; } = Anchor.Center;
|
||||
|
||||
public event Action<UiComponent>? OnClick;
|
||||
public event Action<UiComponent>? OnMouseOver;
|
||||
@@ -22,17 +22,17 @@ public class UiComponent : Engine.Scene.Component.Component
|
||||
return;
|
||||
}
|
||||
|
||||
GameObject.Transform.Translation.Xy = GetAnchorPosition(Container.GameObject.Transform.Size.Xy) + Offset;
|
||||
var size = GameObject.Transform.Size * GameObject.Transform.Scale;
|
||||
GameObject.Transform.Translation.Xy = GetAnchorPosition(Container.GameObject.Transform.Size.Xy, Anchor) + Offset -
|
||||
GetAnchorPosition(size.Xy, Center);
|
||||
|
||||
var transformMatrix = GameObject.Transform.FullTransformMatrix;
|
||||
var actualSize = transformMatrix.ExtractScale();
|
||||
var translation = transformMatrix.ExtractTranslation();
|
||||
var scale = transformMatrix.ExtractScale();
|
||||
|
||||
var relativeMousePosition = Container.MousePosition.Xy -
|
||||
(translation.Xy);
|
||||
var relativeMousePosition = Container.MousePosition.Xy - translation.Xy;
|
||||
|
||||
var objectSize = scale.Xy;
|
||||
|
||||
if (Math.Abs(relativeMousePosition.X) <= objectSize.X / 2 && Math.Abs(relativeMousePosition.Y) <= objectSize.Y / 2)
|
||||
if (Math.Abs(relativeMousePosition.X) <= actualSize.X / 2 && Math.Abs(relativeMousePosition.Y) <= actualSize.Y / 2)
|
||||
{
|
||||
OnMouseOver?.Invoke(this);
|
||||
|
||||
@@ -48,14 +48,14 @@ public class UiComponent : Engine.Scene.Component.Component
|
||||
OnClick?.Invoke(this);
|
||||
}
|
||||
|
||||
private Vector2 GetAnchorPosition(Vector2 parSize)
|
||||
private static Vector2 GetAnchorPosition(Vector2 parSize, Anchor parAnchor)
|
||||
{
|
||||
return parSize * GetAnchorRatio();
|
||||
return parSize * GetAnchorRatio(parAnchor);
|
||||
}
|
||||
|
||||
private Vector2 GetAnchorRatio()
|
||||
private static Vector2 GetAnchorRatio(Anchor parAnchor)
|
||||
{
|
||||
return Anchor switch
|
||||
return parAnchor switch
|
||||
{
|
||||
Anchor.TopLeft => new Vector2(-0.5f, 0.5f),
|
||||
Anchor.TopCenter => new Vector2(0, 0.5f),
|
||||
@@ -66,7 +66,7 @@ public class UiComponent : Engine.Scene.Component.Component
|
||||
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(Anchor), Anchor, null)
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(parAnchor), parAnchor, null)
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
using Engine.Scene.Component.BuiltIn;
|
||||
using OpenTK.Mathematics;
|
||||
|
||||
namespace DoomDeathmatch.Component;
|
||||
namespace DoomDeathmatch.Component.Util;
|
||||
|
||||
public class BillboardComponent : Engine.Scene.Component.Component
|
||||
{
|
||||
@@ -1,7 +1,7 @@
|
||||
using Engine.Input;
|
||||
using OpenTK.Mathematics;
|
||||
|
||||
namespace DoomDeathmatch.Component;
|
||||
namespace DoomDeathmatch.Component.Util;
|
||||
|
||||
public class ControllerComponent : Engine.Scene.Component.Component
|
||||
{
|
||||
25
DoomDeathmatch/src/Component/Util/CopySizeComponent.cs
Normal file
25
DoomDeathmatch/src/Component/Util/CopySizeComponent.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using Engine.Scene.Component.BuiltIn;
|
||||
using OpenTK.Mathematics;
|
||||
|
||||
namespace DoomDeathmatch.Component.Util;
|
||||
|
||||
public class CopySizeComponent : Engine.Scene.Component.Component
|
||||
{
|
||||
public Vector3 Coefficient { get; set; } = Vector3.One;
|
||||
public Transform? Target { get; set; }
|
||||
|
||||
public override void Update(double parDeltaTime)
|
||||
{
|
||||
if (Target == null)
|
||||
return;
|
||||
|
||||
if (Coefficient.X != 0)
|
||||
GameObject.Transform.Size.X = Target.Size.X * Coefficient.X;
|
||||
|
||||
if (Coefficient.Y != 0)
|
||||
GameObject.Transform.Size.Y = Target.Size.Y * Coefficient.Y;
|
||||
|
||||
if (Coefficient.Z != 0)
|
||||
GameObject.Transform.Size.Z = Target.Size.Z * Coefficient.Z;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
using OpenTK.Mathematics;
|
||||
|
||||
namespace DoomDeathmatch.Component;
|
||||
namespace DoomDeathmatch.Component.Util;
|
||||
|
||||
public class DragComponent : Engine.Scene.Component.Component
|
||||
{
|
||||
@@ -1,6 +1,6 @@
|
||||
using OpenTK.Mathematics;
|
||||
|
||||
namespace DoomDeathmatch.Component;
|
||||
namespace DoomDeathmatch.Component.Util;
|
||||
|
||||
public class GravityComponent : Engine.Scene.Component.Component
|
||||
{
|
||||
@@ -1,6 +1,6 @@
|
||||
using OpenTK.Mathematics;
|
||||
|
||||
namespace DoomDeathmatch.Component;
|
||||
namespace DoomDeathmatch.Component.Util;
|
||||
|
||||
public class RigidbodyComponent : Engine.Scene.Component.Component
|
||||
{
|
||||
@@ -1,7 +1,7 @@
|
||||
using Engine.Input;
|
||||
using OpenTK.Mathematics;
|
||||
|
||||
namespace DoomDeathmatch.Component;
|
||||
namespace DoomDeathmatch.Component.Util;
|
||||
|
||||
public class RotateComponent : Engine.Scene.Component.Component
|
||||
{
|
||||
@@ -21,70 +21,6 @@ public static class DoomDeathmatch
|
||||
{
|
||||
public static void Initialize(Engine.Engine parEngine)
|
||||
{
|
||||
parEngine.SceneManager.TransitionTo(MainScene.Create(parEngine));
|
||||
parEngine.SceneManager.TransitionTo(() => MainScene.Create(parEngine));
|
||||
}
|
||||
|
||||
// private static Scene MainScene(Engine.Engine parEngine)
|
||||
// {
|
||||
// var playerObject = new GameObject();
|
||||
// playerObject.AddComponent<RigidbodyComponent>();
|
||||
// playerObject.AddComponent(new ControllerComponent { Speed = 5f });
|
||||
// playerObject.AddComponent(new DragComponent { Drag = 5f, Coefficient = new Vector3(1, 1, 0) });
|
||||
// playerObject.AddComponent(new TestComponent());
|
||||
//
|
||||
// var cameraObject = new GameObject();
|
||||
// cameraObject.Transform.Translation.Z = 2;
|
||||
// cameraObject.AddComponent<PerspectiveCamera>();
|
||||
//
|
||||
// var testObject = new GameObject { Transform = { Translation = new Vector3(0, 6, 0), Rotation = Quaternion.FromAxisAngle(Vector3.UnitX, (float)Math.PI / 2) } };
|
||||
// testObject.AddComponent(new Box2DRenderer { Color = new Vector4(1, 0, 0, 1) });
|
||||
//
|
||||
// var mesh = parEngine.AssetResourceManager.Load<Mesh>("model/untitled.obj");
|
||||
// var texture = parEngine.AssetResourceManager.Load<Texture>("TestImage.png");
|
||||
// var font = parEngine.AssetResourceManager.Load<Font>("font/test");
|
||||
//
|
||||
// var box2dRenderer = new GameObject
|
||||
// {
|
||||
// Transform = { Scale = new Vector3(1), Rotation = Quaternion.FromAxisAngle(Vector3.UnitX, (float)Math.PI / 2) }
|
||||
// };
|
||||
// // box2dRenderer.AddComponent(new MeshRenderer { Mesh = mesh, Albedo = texture });
|
||||
// box2dRenderer.AddComponent(new TextRenderer { Font = font, Text = "A", RenderLayer = RenderLayer.HUD });
|
||||
// // box2dRenderer.AddComponent(new BillboardComponent { Target = cameraObject.Transform });
|
||||
//
|
||||
// var xAxis = new GameObject();
|
||||
// xAxis.Transform.Translation.X = 5;
|
||||
// xAxis.Transform.Scale.X = 10;
|
||||
// xAxis.AddComponent(new Box2DRenderer { Color = new Vector4(1, 0, 0, 1) });
|
||||
//
|
||||
// var yAxis = new GameObject();
|
||||
// yAxis.Transform.Translation.Y = 5;
|
||||
// yAxis.Transform.Scale.X = 10;
|
||||
// yAxis.Transform.Rotation *= Quaternion.FromAxisAngle(Vector3.UnitZ, (float)Math.PI / 2);
|
||||
// yAxis.AddComponent(new Box2DRenderer { Color = new Vector4(0, 1, 0, 1) });
|
||||
//
|
||||
// var zAxis = new GameObject();
|
||||
// zAxis.Transform.Translation.Z = 5;
|
||||
// zAxis.Transform.Scale.Y = 10;
|
||||
// zAxis.Transform.Scale.X = 10;
|
||||
// zAxis.Transform.Rotation *= Quaternion.FromAxisAngle(Vector3.UnitX, (float)Math.PI / 2);
|
||||
// zAxis.AddComponent(new Box2DRenderer
|
||||
// {
|
||||
// Color = new Vector4(0, 0, 1, 1), Texture = parEngine.AssetResourceManager.Load<Texture>("test.jpeg")
|
||||
// });
|
||||
//
|
||||
// var scene = new Scene();
|
||||
// scene.Add(cameraObject);
|
||||
// scene.AddChild(cameraObject, testObject);
|
||||
// scene.Add(playerObject);
|
||||
// scene.SetChild(playerObject, cameraObject);
|
||||
//
|
||||
// scene.Add(box2dRenderer);
|
||||
// // scene.AddChild(box2dRenderer, testChild);
|
||||
//
|
||||
// scene.Add(xAxis);
|
||||
// // scene.Add(yAxis);
|
||||
// // scene.Add(zAxis);
|
||||
//
|
||||
// return scene;
|
||||
// }
|
||||
}
|
||||
35
DoomDeathmatch/src/GameObjectUtil.cs
Normal file
35
DoomDeathmatch/src/GameObjectUtil.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using Engine.Scene;
|
||||
using Engine.Scene.Component.BuiltIn;
|
||||
|
||||
namespace DoomDeathmatch;
|
||||
|
||||
public static class GameObjectUtil
|
||||
{
|
||||
public static GameObject CreateGameObject(Engine.Scene.Scene parScene,
|
||||
List<Engine.Scene.Component.Component> parComponents)
|
||||
{
|
||||
var gameObject = new GameObject();
|
||||
foreach (var component in parComponents)
|
||||
{
|
||||
gameObject.AddComponent(component);
|
||||
}
|
||||
|
||||
parScene.Add(gameObject);
|
||||
|
||||
return gameObject;
|
||||
}
|
||||
|
||||
public static GameObject CreateGameObject(Engine.Scene.Scene parScene, Transform parTransform,
|
||||
List<Engine.Scene.Component.Component> parComponents)
|
||||
{
|
||||
var gameObject = new GameObject(parTransform);
|
||||
foreach (var component in parComponents)
|
||||
{
|
||||
gameObject.AddComponent(component);
|
||||
}
|
||||
|
||||
parScene.Add(gameObject);
|
||||
|
||||
return gameObject;
|
||||
}
|
||||
}
|
||||
@@ -16,36 +16,25 @@ public static class LeadersScene
|
||||
|
||||
var (cameraObject, camera) = UiUtil.CreateOrthographicCamera(scene);
|
||||
|
||||
var (uiContainerObject, uiContainer) = UiUtil.CreateBackgroundUi(scene, camera);
|
||||
var (uiContainerObject, uiContainer) = UiUtil.CreateBackgroundUi(scene, new UiContainerComponent { Camera = camera });
|
||||
|
||||
var (logoObject, logoUi) = UiUtil.CreateLogoUi(parEngine, scene, uiContainer);
|
||||
logoUi.Offset = new Vector2(0, 3f);
|
||||
|
||||
var (backUiObject, backUi) = UiUtil.CreateTextUi(scene, uiContainer,
|
||||
var (backUiObject, backUi, _) = UiUtil.CreateTextUi(scene, uiContainer,
|
||||
UiUtil.GetDoomFont(parEngine), "Назад");
|
||||
backUi.OnClick += _ => parEngine.SceneManager.TransitionTo(MainScene.Create(parEngine));
|
||||
backUi.OnClick += _ => parEngine.SceneManager.TransitionTo(() => MainScene.Create(parEngine));
|
||||
|
||||
var (stackObject, stack) = UiUtil.CreateStackUi(scene, uiContainer,
|
||||
[backUi]);
|
||||
stack.Offset = new Vector2(0, -1f);
|
||||
stackObject.Transform.Size = new Vector3(1f, 6f, 1f);
|
||||
var (stackObject, stack) = UiUtil.CreateStackUi(scene,
|
||||
new StackComponent { Offset = new Vector2(0, -1f), Container = uiContainer, Children = { backUi } });
|
||||
stackObject.Transform.Size.Xy = new Vector2(1f, 6f);
|
||||
|
||||
var selectorObject = new GameObject
|
||||
{
|
||||
Transform = { Translation = new Vector3(0, 0, -1), Size = new Vector3(0.5f, 1f, 1f) }
|
||||
};
|
||||
selectorObject.AddComponent(new SelectorComponent
|
||||
{
|
||||
Children = { backUi },
|
||||
SelectKey = KeyboardButtonCode.Space,
|
||||
NextKey = KeyboardButtonCode.Down,
|
||||
PrevKey = KeyboardButtonCode.Up,
|
||||
});
|
||||
selectorObject.AddComponent(new Box2DRenderer { Color = new Vector4(1, 0, 0, 1) });
|
||||
var (selectorObject, selector) = UiUtil.CreateSelectorUi(scene, new SelectorComponent { Children = { backUi } });
|
||||
|
||||
scene.AddChild(uiContainerObject, selectorObject);
|
||||
scene.SetChild(uiContainerObject, logoObject);
|
||||
scene.SetChild(uiContainerObject, stackObject);
|
||||
scene.SetChild(stackObject, backUiObject);
|
||||
scene.AddChild(uiContainerObject, logoObject);
|
||||
scene.AddChild(uiContainerObject, stackObject);
|
||||
scene.AddChild(stackObject, backUiObject);
|
||||
|
||||
return scene;
|
||||
}
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
using DoomDeathmatch.Component.UI;
|
||||
using DoomDeathmatch.Scene.Leaders;
|
||||
using DoomDeathmatch.Scene.Play;
|
||||
using DoomDeathmatch.Scene.Rules;
|
||||
using Engine.Asset.Font;
|
||||
using Engine.Input;
|
||||
using Engine.Scene;
|
||||
using Engine.Scene.Component.BuiltIn;
|
||||
using Engine.Scene.Component.BuiltIn.Renderer;
|
||||
using OpenTK.Mathematics;
|
||||
|
||||
namespace DoomDeathmatch.Scene.Main;
|
||||
@@ -18,60 +15,49 @@ public static class MainScene
|
||||
|
||||
var (cameraObject, camera) = UiUtil.CreateOrthographicCamera(scene);
|
||||
|
||||
AddMainUi(parEngine, scene, camera);
|
||||
var (uiContainerObject, uiContainer) =
|
||||
UiUtil.CreateBackgroundUi(scene, new UiContainerComponent { Camera = camera });
|
||||
|
||||
var (playUiObject, playUi, _) =
|
||||
UiUtil.CreateTextUi(scene, uiContainer, UiUtil.GetDoomFont(parEngine), "Играть");
|
||||
|
||||
var (leadersUiObject, leadersUi, _) =
|
||||
UiUtil.CreateTextUi(scene, uiContainer, UiUtil.GetDoomFont(parEngine), "Лидеры");
|
||||
|
||||
var (rulesUiObject, rulesUi, _) =
|
||||
UiUtil.CreateTextUi(scene, uiContainer, UiUtil.GetDoomFont(parEngine), "Правила");
|
||||
|
||||
var (exitUiObject, exitUi, _) =
|
||||
UiUtil.CreateTextUi(scene, uiContainer, UiUtil.GetDoomFont(parEngine), "Выход");
|
||||
|
||||
var (stackObject, stack) = UiUtil.CreateStackUi(scene,
|
||||
new StackComponent
|
||||
{
|
||||
Offset = new Vector2(0, -1f), Container = uiContainer, Children = { playUi, leadersUi, rulesUi, exitUi }
|
||||
});
|
||||
stackObject.Transform.Size.Xy = new Vector2(1f, 6f);
|
||||
|
||||
playUi.OnClick += _ => parEngine.SceneManager.TransitionTo(() => PlayScene.Create(parEngine));
|
||||
leadersUi.OnClick += _ => parEngine.SceneManager.TransitionTo(() => LeadersScene.Create(parEngine));
|
||||
rulesUi.OnClick += _ => parEngine.SceneManager.TransitionTo(() => RulesScene.Create(parEngine));
|
||||
exitUi.OnClick += _ => parEngine.Close();
|
||||
|
||||
var (logoObject, logoUi) = UiUtil.CreateLogoUi(parEngine, scene, uiContainer);
|
||||
logoUi.Offset = new Vector2(0, 3f);
|
||||
|
||||
var (selectorObject, selector) = UiUtil.CreateSelectorUi(scene,
|
||||
new SelectorComponent { Children = { playUi, leadersUi, rulesUi, exitUi } });
|
||||
|
||||
scene.AddChild(uiContainerObject, selectorObject);
|
||||
|
||||
scene.AddChild(uiContainerObject, stackObject);
|
||||
scene.AddChild(uiContainerObject, logoObject);
|
||||
|
||||
scene.AddChild(stackObject, playUiObject);
|
||||
scene.AddChild(stackObject, leadersUiObject);
|
||||
scene.AddChild(stackObject, rulesUiObject);
|
||||
scene.AddChild(stackObject, exitUiObject);
|
||||
|
||||
return scene;
|
||||
}
|
||||
|
||||
private static void AddMainUi(Engine.Engine parEngine, Engine.Scene.Scene parScene, Camera parCamera)
|
||||
{
|
||||
var (uiContainerObject, uiContainer) = UiUtil.CreateBackgroundUi(parScene, parCamera);
|
||||
|
||||
var (playUiObject, playUi) =
|
||||
UiUtil.CreateTextUi(parScene, uiContainer, UiUtil.GetDoomFont(parEngine), "Играть");
|
||||
|
||||
var (leadersUiObject, leadersUi) =
|
||||
UiUtil.CreateTextUi(parScene, uiContainer, UiUtil.GetDoomFont(parEngine), "Лидеры");
|
||||
|
||||
var (rulesUiObject, rulesUi) =
|
||||
UiUtil.CreateTextUi(parScene, uiContainer, UiUtil.GetDoomFont(parEngine), "Правила");
|
||||
|
||||
var (exitUiObject, exitUi) =
|
||||
UiUtil.CreateTextUi(parScene, uiContainer, UiUtil.GetDoomFont(parEngine), "Выход");
|
||||
|
||||
var (stackObject, stack) = UiUtil.CreateStackUi(parScene, uiContainer,
|
||||
[playUi, leadersUi, rulesUi, exitUi]);
|
||||
stack.Offset = new Vector2(0, -1f);
|
||||
stackObject.Transform.Size = new Vector3(2f, 5f, 1f);
|
||||
|
||||
playUi.OnClick += _ => Console.WriteLine("Play");
|
||||
leadersUi.OnClick += _ => parEngine.SceneManager.TransitionTo(LeadersScene.Create(parEngine));
|
||||
rulesUi.OnClick += _ => parEngine.SceneManager.TransitionTo(RulesScene.Create(parEngine));
|
||||
exitUi.OnClick += _ => parEngine.Close();
|
||||
|
||||
var (logoObject, logoUi) = UiUtil.CreateLogoUi(parEngine, parScene, uiContainer);
|
||||
|
||||
var selectorObject = new GameObject
|
||||
{
|
||||
Transform = { Translation = new Vector3(0, 0, -1), Size = new Vector3(0.5f, 1f, 1f) }
|
||||
};
|
||||
selectorObject.AddComponent(new SelectorComponent
|
||||
{
|
||||
Children = { playUi, leadersUi, rulesUi, exitUi },
|
||||
SelectKey = KeyboardButtonCode.Space,
|
||||
NextKey = KeyboardButtonCode.Down,
|
||||
PrevKey = KeyboardButtonCode.Up,
|
||||
});
|
||||
selectorObject.AddComponent(new Box2DRenderer { Color = new Vector4(1, 0, 0, 1) });
|
||||
|
||||
parScene.AddChild(uiContainerObject, selectorObject);
|
||||
|
||||
parScene.SetChild(uiContainerObject, stackObject);
|
||||
parScene.SetChild(uiContainerObject, logoObject);
|
||||
|
||||
parScene.SetChild(stackObject, playUiObject);
|
||||
parScene.SetChild(stackObject, leadersUiObject);
|
||||
parScene.SetChild(stackObject, rulesUiObject);
|
||||
parScene.SetChild(stackObject, exitUiObject);
|
||||
}
|
||||
}
|
||||
136
DoomDeathmatch/src/Scene/Play/PlayScene.cs
Normal file
136
DoomDeathmatch/src/Scene/Play/PlayScene.cs
Normal file
@@ -0,0 +1,136 @@
|
||||
using DoomDeathmatch.Component;
|
||||
using DoomDeathmatch.Component.MVC.Controller;
|
||||
using DoomDeathmatch.Component.MVC.View;
|
||||
using DoomDeathmatch.Component.UI;
|
||||
using DoomDeathmatch.Component.Util;
|
||||
using Engine.Asset.Mesh;
|
||||
using Engine.Graphics.Pipeline;
|
||||
using Engine.Graphics.Texture;
|
||||
using Engine.Scene;
|
||||
using Engine.Scene.Component.BuiltIn;
|
||||
using Engine.Scene.Component.BuiltIn.Renderer;
|
||||
using OpenTK.Mathematics;
|
||||
|
||||
namespace DoomDeathmatch.Scene.Play;
|
||||
|
||||
public static class PlayScene
|
||||
{
|
||||
public static Engine.Scene.Scene Create(Engine.Engine parEngine)
|
||||
{
|
||||
var scene = new Engine.Scene.Scene();
|
||||
|
||||
var (hudCameraObject, hudCamera) = UiUtil.CreateOrthographicCamera(scene, RenderLayer.HUD);
|
||||
var (uiContainerObject, uiContainer) =
|
||||
UiUtil.CreateContainerUi(scene, new UiContainerComponent { Camera = hudCamera });
|
||||
|
||||
var (bottomContainerObject, bottomContainer) =
|
||||
UiUtil.CreateContainerUi(scene, new UiContainerComponent { Container = uiContainer });
|
||||
bottomContainer.Anchor = Anchor.BottomCenter;
|
||||
bottomContainer.Center = Anchor.BottomCenter;
|
||||
bottomContainerObject.AddComponent(new Box2DRenderer
|
||||
{
|
||||
Color = new Vector4(1, 0, 0, 1), RenderLayer = RenderLayer.HUD
|
||||
});
|
||||
bottomContainerObject.AddComponent(new CopySizeComponent
|
||||
{
|
||||
Target = uiContainerObject.Transform, Coefficient = new Vector3(1, 0, 1)
|
||||
});
|
||||
bottomContainerObject.Transform.Size.Y = 1.5f;
|
||||
scene.AddChild(uiContainerObject, bottomContainerObject);
|
||||
|
||||
var (gunObject, (gunUi, gunSprite)) = UiUtil.CreateSpriteUi(scene, bottomContainer,
|
||||
parEngine.AssetResourceManager.Load<Texture>("texture/pistol.png"), RenderLayer.HUD);
|
||||
gunObject.Transform.Scale = new Vector3(5);
|
||||
gunUi.Anchor = Anchor.TopCenter;
|
||||
gunUi.Center = Anchor.BottomCenter;
|
||||
scene.AddChild(bottomContainerObject, gunObject);
|
||||
|
||||
var (healthObject, healthUi, (_, healthTextRenderer)) =
|
||||
UiUtil.CreateTextUi(scene, bottomContainer, UiUtil.GetDoomFont(parEngine), "Здоровье: 000",
|
||||
TextAlignComponent.Align.Center,
|
||||
RenderLayer.HUD);
|
||||
healthObject.Transform.Scale = new Vector3(0.75f);
|
||||
healthUi.Anchor = Anchor.CenterLeft;
|
||||
healthUi.Center = Anchor.CenterLeft;
|
||||
scene.AddChild(bottomContainerObject, healthObject);
|
||||
|
||||
var (ammoObject, ammoUi, (_, ammoTextRenderer)) =
|
||||
UiUtil.CreateTextUi(scene, bottomContainer, UiUtil.GetDoomFont(parEngine), "Патроны: 00/00",
|
||||
TextAlignComponent.Align.Center,
|
||||
RenderLayer.HUD);
|
||||
ammoObject.Transform.Scale = new Vector3(0.75f);
|
||||
ammoUi.Anchor = Anchor.TopRight;
|
||||
ammoUi.Center = Anchor.TopRight;
|
||||
scene.AddChild(bottomContainerObject, ammoObject);
|
||||
|
||||
var (weaponObject, weaponUi, (_, weaponTextRenderer)) =
|
||||
UiUtil.CreateTextUi(scene, bottomContainer, UiUtil.GetDoomFont(parEngine), "Оружие: ОРУЖИЕОР",
|
||||
TextAlignComponent.Align.Center,
|
||||
RenderLayer.HUD);
|
||||
weaponObject.Transform.Scale = new Vector3(0.75f);
|
||||
weaponUi.Anchor = Anchor.BottomRight;
|
||||
weaponUi.Center = Anchor.BottomRight;
|
||||
scene.AddChild(bottomContainerObject, weaponObject);
|
||||
|
||||
var (topContainerObject, topContainer) =
|
||||
UiUtil.CreateContainerUi(scene, new UiContainerComponent { Container = uiContainer });
|
||||
topContainer.Anchor = Anchor.TopCenter;
|
||||
topContainer.Center = Anchor.TopCenter;
|
||||
topContainerObject.AddComponent(
|
||||
new Box2DRenderer { Color = new Vector4(1, 0, 0, 1), RenderLayer = RenderLayer.HUD });
|
||||
topContainerObject.AddComponent(new CopySizeComponent
|
||||
{
|
||||
Target = uiContainerObject.Transform, Coefficient = new Vector3(1, 0, 1)
|
||||
});
|
||||
topContainerObject.Transform.Size.Y = 1f;
|
||||
scene.AddChild(uiContainerObject, topContainerObject);
|
||||
|
||||
var (timerObject, timerUi, _) =
|
||||
UiUtil.CreateTextUi(scene, topContainer, UiUtil.GetDoomFont(parEngine), "Время: 00:00",
|
||||
parRenderLayer: RenderLayer.HUD);
|
||||
timerUi.Anchor = Anchor.CenterLeft;
|
||||
timerUi.Center = Anchor.CenterLeft;
|
||||
scene.AddChild(topContainerObject, timerObject);
|
||||
|
||||
var (scoreObject, scoreUi, (_, scoreTextRenderer)) =
|
||||
UiUtil.CreateTextUi(scene, topContainer, UiUtil.GetDoomFont(parEngine), "Счет: 00000",
|
||||
parRenderLayer: RenderLayer.HUD);
|
||||
scoreUi.Anchor = Anchor.CenterRight;
|
||||
scoreUi.Center = Anchor.CenterRight;
|
||||
scene.AddChild(topContainerObject, scoreObject);
|
||||
|
||||
var playerObject = GameObjectUtil.CreateGameObject(scene, [
|
||||
new RigidbodyComponent(),
|
||||
new ControllerComponent { Speed = 5f },
|
||||
new DragComponent { Drag = 5f, Coefficient = new Vector3(1, 1, 0) },
|
||||
|
||||
new PlayerController(),
|
||||
|
||||
new WeaponController(),
|
||||
new WeaponView(weaponTextRenderer, ammoTextRenderer, gunSprite),
|
||||
|
||||
new HealthController(),
|
||||
new HealthView(healthTextRenderer),
|
||||
|
||||
new ScoreController(),
|
||||
new ScoreView(scoreTextRenderer),
|
||||
]);
|
||||
|
||||
var (perspectiveCameraObject, perspectiveCamera) = UiUtil.CreatePerspectiveCamera(scene);
|
||||
perspectiveCameraObject.Transform.Translation.Z = 2;
|
||||
|
||||
var mapObject = GameObjectUtil.CreateGameObject(scene, [
|
||||
new MeshRenderer { Mesh = parEngine.AssetResourceManager.Load<Mesh>("model/map.obj") },
|
||||
]);
|
||||
|
||||
var impObject = GameObjectUtil.CreateGameObject(scene,
|
||||
new Transform { Translation = new Vector3(0, 0, 1), Scale = new Vector3(1, 2, 1), }, [
|
||||
new Box2DRenderer { Texture = parEngine.AssetResourceManager.Load<Texture>("texture/imp.png") },
|
||||
new BillboardComponent { Target = perspectiveCameraObject.Transform }
|
||||
]);
|
||||
|
||||
scene.AddChild(playerObject, perspectiveCameraObject);
|
||||
|
||||
return scene;
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,5 @@
|
||||
using DoomDeathmatch.Component.UI;
|
||||
using DoomDeathmatch.Scene.Main;
|
||||
using Engine.Asset.Font;
|
||||
using Engine.Input;
|
||||
using Engine.Scene;
|
||||
using Engine.Scene.Component.BuiltIn.Renderer;
|
||||
using OpenTK.Mathematics;
|
||||
|
||||
namespace DoomDeathmatch.Scene.Rules;
|
||||
@@ -16,42 +12,31 @@ public static class RulesScene
|
||||
|
||||
var (cameraObject, camera) = UiUtil.CreateOrthographicCamera(scene);
|
||||
|
||||
var (uiContainerObject, uiContainer) = UiUtil.CreateBackgroundUi(scene, camera);
|
||||
var (uiContainerObject, uiContainer) = UiUtil.CreateBackgroundUi(scene, new UiContainerComponent { Camera = camera });
|
||||
|
||||
var (logoObject, logoUi) = UiUtil.CreateLogoUi(parEngine, scene, uiContainer);
|
||||
logoUi.Offset = new Vector2(0, 3f);
|
||||
|
||||
var (backUiObject, backUi) = UiUtil.CreateTextUi(scene, uiContainer,
|
||||
parEngine.AssetResourceManager.Load<Font>("font/test"), "Назад");
|
||||
backUi.OnClick += _ => parEngine.SceneManager.TransitionTo(MainScene.Create(parEngine));
|
||||
var (backUiObject, backUi, _) = UiUtil.CreateTextUi(scene, uiContainer,
|
||||
UiUtil.GetDoomFont(parEngine), "Назад");
|
||||
backUi.OnClick += _ => parEngine.SceneManager.TransitionTo(() => MainScene.Create(parEngine));
|
||||
|
||||
var (rulesObject, rulesUi) = UiUtil.CreateTextUi(scene, uiContainer,
|
||||
parEngine.AssetResourceManager.Load<Font>("font/test"), "Правила");
|
||||
var (rulesObject, rulesUi, _) = UiUtil.CreateTextUi(scene, uiContainer,
|
||||
UiUtil.GetDoomFont(parEngine), "Правила");
|
||||
|
||||
var (stackObject, stack) = UiUtil.CreateStackUi(scene, uiContainer,
|
||||
[rulesUi, backUi]);
|
||||
stack.Offset = new Vector2(0, -1f);
|
||||
stackObject.Transform.Size = new Vector3(1f, 6f, 1f);
|
||||
var (stackObject, stack) = UiUtil.CreateStackUi(scene,
|
||||
new StackComponent { Offset = new Vector2(0, -1f), Container = uiContainer, Children = { rulesUi, backUi } });
|
||||
stackObject.Transform.Size.Xy = new Vector2(1f, 6f);
|
||||
|
||||
var selectorObject = new GameObject
|
||||
{
|
||||
Transform = { Translation = new Vector3(0, 0, -1), Size = new Vector3(0.5f, 1f, 1f) }
|
||||
};
|
||||
selectorObject.AddComponent(new SelectorComponent
|
||||
{
|
||||
Children = { backUi },
|
||||
SelectKey = KeyboardButtonCode.Space,
|
||||
NextKey = KeyboardButtonCode.Down,
|
||||
PrevKey = KeyboardButtonCode.Up,
|
||||
});
|
||||
selectorObject.AddComponent(new Box2DRenderer { Color = new Vector4(1, 0, 0, 1) });
|
||||
var (selectorObject, selector) = UiUtil.CreateSelectorUi(scene, new SelectorComponent { Children = { backUi } });
|
||||
|
||||
scene.AddChild(uiContainerObject, selectorObject);
|
||||
|
||||
scene.SetChild(uiContainerObject, logoObject);
|
||||
scene.SetChild(uiContainerObject, stackObject);
|
||||
scene.AddChild(uiContainerObject, logoObject);
|
||||
scene.AddChild(uiContainerObject, stackObject);
|
||||
|
||||
scene.SetChild(stackObject, rulesObject);
|
||||
scene.SetChild(stackObject, backUiObject);
|
||||
scene.AddChild(stackObject, rulesObject);
|
||||
scene.AddChild(stackObject, backUiObject);
|
||||
|
||||
return scene;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
using DoomDeathmatch.Component.UI;
|
||||
using Engine.Asset.Font;
|
||||
using Engine.Graphics.Pipeline;
|
||||
using Engine.Graphics.Texture;
|
||||
using Engine.Input;
|
||||
using Engine.Scene;
|
||||
using Engine.Scene.Component.BuiltIn;
|
||||
using Engine.Scene.Component.BuiltIn.Renderer;
|
||||
@@ -15,102 +17,154 @@ public static class UiUtil
|
||||
return parEngine.AssetResourceManager.Load<Font>("font/doom");
|
||||
}
|
||||
|
||||
public static (GameObject, OrthographicCamera) CreateOrthographicCamera(Engine.Scene.Scene parScene)
|
||||
public static (GameObject, OrthographicCamera) CreateOrthographicCamera(Engine.Scene.Scene parScene,
|
||||
RenderLayer? parRenderLayer = null)
|
||||
{
|
||||
var cameraObject = new GameObject();
|
||||
var camera = new OrthographicCamera();
|
||||
cameraObject.AddComponent(camera);
|
||||
|
||||
parScene.Add(cameraObject);
|
||||
OrthographicCamera camera;
|
||||
var cameraObject = GameObjectUtil.CreateGameObject(parScene, [
|
||||
camera = new OrthographicCamera { RenderLayer = parRenderLayer ?? RenderLayer.DEFAULT }
|
||||
]);
|
||||
|
||||
return (cameraObject, camera);
|
||||
}
|
||||
|
||||
public static (GameObject, UiComponent) CreateTextUi(Engine.Scene.Scene parScene, UiContainerComponent parContainer,
|
||||
Font parFont, string parText)
|
||||
public static (GameObject, PerspectiveCamera) CreatePerspectiveCamera(Engine.Scene.Scene parScene,
|
||||
RenderLayer? parRenderLayer = null)
|
||||
{
|
||||
PerspectiveCamera camera;
|
||||
var cameraObject = GameObjectUtil.CreateGameObject(parScene, [
|
||||
camera = new PerspectiveCamera { RenderLayer = parRenderLayer ?? RenderLayer.DEFAULT }
|
||||
]);
|
||||
|
||||
return (cameraObject, camera);
|
||||
}
|
||||
|
||||
public static (GameObject, UiContainerComponent, (GameObject, TextRenderer)) CreateTextUi(Engine.Scene.Scene parScene,
|
||||
UiContainerComponent parContainer,
|
||||
Font parFont, string parText, TextAlignComponent.Align parAlign = TextAlignComponent.Align.Center,
|
||||
RenderLayer? parRenderLayer = null)
|
||||
{
|
||||
var size = parFont.Measure(parText);
|
||||
var outerObject = new GameObject
|
||||
{
|
||||
Transform = { Size = new Vector3(size.X, size.Y, 1f), Translation = new Vector3(0, 0, -1) }
|
||||
};
|
||||
var uiComponent = new UiComponent { Container = parContainer, Anchor = Anchor.Center };
|
||||
var uiComponent = new UiContainerComponent { Container = parContainer };
|
||||
outerObject.AddComponent(uiComponent);
|
||||
outerObject.AddComponent(new Box2DRenderer { Color = new Vector4(0, 0, 1, 1) });
|
||||
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) } };
|
||||
innerObject.AddComponent(new TextRenderer { Font = parFont, Text = parText });
|
||||
innerObject.AddComponent(new TextAlignComponent { Alignment = TextAlignComponent.Align.Center });
|
||||
// var innerUiComponent = new UiComponent { Container = uiComponent };
|
||||
// innerObject.AddComponent(innerUiComponent);
|
||||
var innerTextRenderer = new TextRenderer
|
||||
{
|
||||
Font = parFont, Text = parText, RenderLayer = parRenderLayer ?? RenderLayer.DEFAULT
|
||||
};
|
||||
innerObject.AddComponent(innerTextRenderer);
|
||||
innerObject.AddComponent(new TextAlignComponent { Alignment = parAlign });
|
||||
|
||||
parScene.Add(outerObject);
|
||||
parScene.AddChild(outerObject, innerObject);
|
||||
|
||||
return (outerObject, uiComponent);
|
||||
return (outerObject, uiComponent, (innerObject, innerTextRenderer));
|
||||
}
|
||||
|
||||
public static (GameObject, UiContainerComponent) CreateBackgroundUi(Engine.Scene.Scene parScene, Camera parCamera)
|
||||
public static (GameObject, UiContainerComponent) CreateContainerUi(Engine.Scene.Scene parScene,
|
||||
UiContainerComponent parUiContainerComponent)
|
||||
{
|
||||
var uiContainerObject = new GameObject();
|
||||
var uiContainer = new UiContainerComponent { Camera = parCamera };
|
||||
uiContainerObject.AddComponent(uiContainer);
|
||||
uiContainerObject.AddComponent(new Box2DRenderer { Color = new Vector4(0.1f, 0.1f, 0.1f, 1) });
|
||||
uiContainerObject.AddComponent(parUiContainerComponent);
|
||||
|
||||
parScene.Add(uiContainerObject);
|
||||
|
||||
return (uiContainerObject, parUiContainerComponent);
|
||||
}
|
||||
|
||||
public static (GameObject, UiContainerComponent) CreateBackgroundUi(Engine.Scene.Scene parScene,
|
||||
UiContainerComponent parUiContainerComponent, Vector4? parColor = null,
|
||||
RenderLayer? parRenderLayer = null)
|
||||
{
|
||||
var (uiContainerObject, uiContainer) = CreateContainerUi(parScene, parUiContainerComponent);
|
||||
uiContainerObject.AddComponent(new Box2DRenderer
|
||||
{
|
||||
Color = parColor ?? new Vector4(0.1f, 0.1f, 0.1f, 1), RenderLayer = parRenderLayer ?? RenderLayer.DEFAULT
|
||||
});
|
||||
|
||||
return (uiContainerObject, uiContainer);
|
||||
}
|
||||
|
||||
public static (GameObject, UiComponent) CreateLogoUi(Engine.Engine parEngine, Engine.Scene.Scene parScene,
|
||||
UiContainerComponent parContainer)
|
||||
UiContainerComponent parContainer, RenderLayer? parRenderLayer = null)
|
||||
{
|
||||
var logoObject = new GameObject
|
||||
{
|
||||
Transform =
|
||||
UiComponent uiComponent;
|
||||
var logoObject = GameObjectUtil.CreateGameObject(parScene,
|
||||
new Transform
|
||||
{
|
||||
Translation = new Vector3(0, 0, -10), Scale = new Vector3(3), Size = new Vector3(1.6385869565f, 1f, 1f)
|
||||
}
|
||||
};
|
||||
logoObject.AddComponent(new Box2DRenderer
|
||||
{
|
||||
Texture = parEngine.AssetResourceManager.Load<Texture>("texture/doom_logo.png")
|
||||
});
|
||||
|
||||
var uiComponent = new UiComponent { Container = null, Anchor = Anchor.Center };
|
||||
|
||||
logoObject.AddComponent(new UiComponent
|
||||
{
|
||||
Container = parContainer, Anchor = Anchor.Center, Offset = new Vector2(0, 3f)
|
||||
});
|
||||
|
||||
parScene.Add(logoObject);
|
||||
}, [
|
||||
new Box2DRenderer
|
||||
{
|
||||
Texture = parEngine.AssetResourceManager.Load<Texture>("texture/doom_logo.png"),
|
||||
RenderLayer = parRenderLayer ?? RenderLayer.DEFAULT
|
||||
},
|
||||
uiComponent = new UiComponent { Container = parContainer, Anchor = Anchor.Center }
|
||||
]
|
||||
);
|
||||
|
||||
return (logoObject, uiComponent);
|
||||
}
|
||||
|
||||
public static (GameObject, StackComponent) CreateStackUi(Engine.Scene.Scene parScene,
|
||||
UiContainerComponent parContainer, List<UiComponent> parChildren, Orientation parOrientation = Orientation.Vertical)
|
||||
public static (GameObject, (UiComponent, Box2DRenderer)) CreateSpriteUi(Engine.Scene.Scene parScene,
|
||||
UiContainerComponent parContainer,
|
||||
Texture? parTexture, RenderLayer? parRenderLayer = null)
|
||||
{
|
||||
var stack = new StackComponent
|
||||
var spriteObject = new GameObject();
|
||||
var spriteComponent = new Box2DRenderer
|
||||
{
|
||||
Container = parContainer,
|
||||
Anchor = Anchor.Center
|
||||
Texture = parTexture, RenderLayer = parRenderLayer ?? RenderLayer.DEFAULT
|
||||
};
|
||||
spriteObject.AddComponent(spriteComponent);
|
||||
var uiComponent = new UiContainerComponent { Container = parContainer };
|
||||
spriteObject.AddComponent(uiComponent);
|
||||
|
||||
stack.Children.AddRange(parChildren);
|
||||
foreach (var child in parChildren)
|
||||
{
|
||||
child.Container = stack;
|
||||
}
|
||||
return (spriteObject, (uiComponent, spriteComponent));
|
||||
}
|
||||
|
||||
var stackObject = new GameObject
|
||||
{
|
||||
Transform = { Translation = new Vector3(0, 0, -1) }
|
||||
};
|
||||
stackObject.AddComponent(stack);
|
||||
stackObject.AddComponent(new Box2DRenderer { Color = new Vector4(1, 0, 0, 1) });
|
||||
public static (GameObject, StackComponent) CreateStackUi(Engine.Scene.Scene parScene,
|
||||
StackComponent parStackComponent, RenderLayer? parRenderLayer = null)
|
||||
{
|
||||
foreach (var child in parStackComponent.Children)
|
||||
child.Container = parStackComponent;
|
||||
|
||||
var stackObject = new GameObject { Transform = { Translation = new Vector3(0, 0, -1) } };
|
||||
stackObject.AddComponent(parStackComponent);
|
||||
// stackObject.AddComponent(new Box2DRenderer { Color = new Vector4(1, 0, 0, 1), RenderLayer = parRenderLayer ?? RenderLayer.DEFAULT });
|
||||
|
||||
parScene.Add(stackObject);
|
||||
|
||||
return (stackObject, stack);
|
||||
return (stackObject, parStackComponent);
|
||||
}
|
||||
|
||||
public static (GameObject, SelectorComponent) CreateSelectorUi(Engine.Scene.Scene parScene,
|
||||
SelectorComponent parSelectorComponent, RenderLayer? parRenderLayer = null)
|
||||
{
|
||||
var selectorObject = new GameObject { Transform = { Translation = new Vector3(0, 0, -1) } };
|
||||
selectorObject.AddComponent(parSelectorComponent);
|
||||
var innerSelectorObject = new GameObject
|
||||
{
|
||||
Transform = { Translation = new Vector3(-0.5f, 0, 0), Size = new Vector3(0.25f, 0.5f, 1f) }
|
||||
};
|
||||
innerSelectorObject.AddComponent(new Box2DRenderer
|
||||
{
|
||||
Color = new Vector4(1, 1, 1, 1), RenderLayer = parRenderLayer ?? RenderLayer.DEFAULT
|
||||
});
|
||||
|
||||
parScene.Add(selectorObject);
|
||||
parScene.AddChild(selectorObject, innerSelectorObject);
|
||||
|
||||
return (selectorObject, parSelectorComponent);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user