This commit is contained in:
2025-01-02 05:15:16 +03:00
parent 3c66a65b40
commit ac00eb18a9
96 changed files with 384134 additions and 230 deletions

View File

@@ -10,4 +10,8 @@
<ProjectReference Include="..\Engine\Engine.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="src\Scene\Play\" />
</ItemGroup>
</Project>

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,44 @@
# Blender 4.2.3 LTS
# www.blender.org
o Cube
v -1.000000 -1.000000 1.000000
v -1.000000 1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v -1.000000 1.000000 -1.000000
v 1.000000 -1.000000 1.000000
v 1.000000 1.000000 1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 1.000000 -1.000000
vn -1.0000 -0.0000 -0.0000
vn -0.0000 -0.0000 -1.0000
vn 1.0000 -0.0000 -0.0000
vn -0.0000 -0.0000 1.0000
vn -0.0000 -1.0000 -0.0000
vn -0.0000 1.0000 -0.0000
vt 0.625000 0.000000
vt 0.375000 0.250000
vt 0.375000 0.000000
vt 0.625000 0.250000
vt 0.375000 0.500000
vt 0.625000 0.500000
vt 0.375000 0.750000
vt 0.625000 0.750000
vt 0.375000 1.000000
vt 0.125000 0.750000
vt 0.125000 0.500000
vt 0.875000 0.500000
vt 0.625000 1.000000
vt 0.875000 0.750000
s 0
f 2/1/1 3/2/1 1/3/1
f 4/4/2 7/5/2 3/2/2
f 8/6/3 5/7/3 7/5/3
f 6/8/4 1/9/4 5/7/4
f 7/5/5 1/10/5 3/11/5
f 4/12/6 6/8/6 8/6/6
f 2/1/1 4/4/1 3/2/1
f 4/4/2 8/6/2 7/5/2
f 8/6/3 6/8/3 5/7/3
f 6/8/4 2/13/4 1/9/4
f 7/5/5 5/7/5 1/10/5
f 4/12/6 2/14/6 6/8/6

View File

@@ -0,0 +1,38 @@
# Blender 4.2.3 LTS
# www.blender.org
o Cube
v -1.000000 -1.000000 1.000000
v -1.000000 1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v -1.000000 1.000000 -1.000000
v 1.000000 -1.000000 1.000000
v 1.000000 1.000000 1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 1.000000 -1.000000
vt 0.625000 0.000000
vt 0.375000 0.250000
vt 0.375000 0.000000
vt 0.625000 0.250000
vt 0.375000 0.500000
vt 0.625000 0.500000
vt 0.375000 0.750000
vt 0.625000 0.750000
vt 0.375000 1.000000
vt 0.125000 0.750000
vt 0.125000 0.500000
vt 0.875000 0.500000
vt 0.625000 1.000000
vt 0.875000 0.750000
s 0
f 2/1 3/2 1/3
f 4/4 7/5 3/2
f 8/6 5/7 7/5
f 6/8 1/9 5/7
f 7/5 1/10 3/11
f 4/12 6/8 8/6
f 2/1 4/4 3/2
f 4/4 8/6 7/5
f 8/6 6/8 5/7
f 6/8 2/13 1/9
f 7/5 5/7 1/10
f 4/12 2/14 6/8

View File

@@ -0,0 +1,24 @@
# Blender 4.2.3 LTS
# www.blender.org
o Cube
v -1.000000 -1.000000 1.000000
v -1.000000 1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v -1.000000 1.000000 -1.000000
v 1.000000 -1.000000 1.000000
v 1.000000 1.000000 1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 1.000000 -1.000000
s 0
f 2 3 1
f 4 7 3
f 8 5 7
f 6 1 5
f 7 1 3
f 4 6 8
f 2 4 3
f 4 8 7
f 8 6 5
f 6 2 1
f 7 5 1
f 4 2 6

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

View File

@@ -0,0 +1,41 @@
using Engine.Scene.Component.BuiltIn;
using OpenTK.Mathematics;
namespace DoomDeathmatch.Component;
public class BillboardComponent : Engine.Scene.Component.Component
{
public Transform? Target { get; set; }
public Vector3 Up { get; set; } = Vector3.UnitZ;
public override void Update(double parDeltaTime)
{
if (Target == null)
{
return;
}
var targetPosition = Target.TransformMatrix.ExtractTranslation();
var currentPosition = GameObject.Transform.Translation;
var forward = targetPosition - currentPosition;
if (forward.LengthSquared > 0)
forward.Normalize();
var right = Vector3.Cross(Up, forward);
if (right.LengthSquared > 0)
right.Normalize();
var recalculatedUp = Vector3.Cross(forward, right);
var rotationMatrix = new Matrix3(
right.X, recalculatedUp.X, forward.X,
right.Y, recalculatedUp.Y, forward.Y,
right.Z, recalculatedUp.Z, forward.Z
);
var rotation = Quaternion.FromMatrix(rotationMatrix);
GameObject.Transform.Rotation = rotation;
}
}

View File

@@ -6,28 +6,51 @@ namespace DoomDeathmatch.Component;
public class ControllerComponent : Engine.Scene.Component.Component
{
public float Speed { get; set; } = 10.0f;
public float RotationSpeed { get; set; } = 70.0f;
private readonly IInputHandler _inputHandler = Engine.Engine.Instance.InputHandler!;
private RigidbodyComponent _rigidbody;
public override void Awake()
{
_rigidbody = GameObject.GetComponent<RigidbodyComponent>()!;
}
public override void Update(double parDeltaTime)
{
var movement = Vector3.Zero;
var rotation = 0.0f;
if (_inputHandler.IsKeyPressed(KeyboardButtonCode.W))
movement.Z += 1;
movement.Y += 1;
if (_inputHandler.IsKeyPressed(KeyboardButtonCode.S))
movement.Z -= 1;
if (_inputHandler.IsKeyPressed(KeyboardButtonCode.A))
movement.X -= 1;
movement.Y -= 1;
if (_inputHandler.IsKeyPressed(KeyboardButtonCode.D))
movement.X += 1;
if (_inputHandler.IsKeyPressed(KeyboardButtonCode.Space))
movement.Y += 1;
if (_inputHandler.IsKeyPressed(KeyboardButtonCode.Shift))
movement.Y -= 1;
if (_inputHandler.IsKeyPressed(KeyboardButtonCode.A))
movement.X -= 1;
if (_inputHandler.IsKeyPressed(KeyboardButtonCode.Q))
rotation += RotationSpeed;
if (_inputHandler.IsKeyPressed(KeyboardButtonCode.E))
rotation -= RotationSpeed;
if (movement.LengthSquared > 0)
{
movement.Normalize();
movement = GameObject.Transform.Rotation * movement;
GameObject.Transform.Translation += movement * Speed * (float)parDeltaTime;
_rigidbody.AddVelocity(Speed * movement);
}
var velocityXy = _rigidbody.Velocity.Xy;
if (velocityXy.LengthSquared > Speed * Speed)
{
var length = velocityXy.Length;
_rigidbody.AddVelocity(new Vector3(-(length - Speed) / length * velocityXy));
}
GameObject.Transform.Rotation *= Quaternion.FromAxisAngle(Vector3.UnitZ, MathHelper.DegreesToRadians(rotation) *
(float)parDeltaTime);
}
}

View File

@@ -0,0 +1,21 @@
using OpenTK.Mathematics;
namespace DoomDeathmatch.Component;
public class DragComponent : Engine.Scene.Component.Component
{
public float Drag { get; set; } = 1f;
public Vector3 Coefficient { get; set; } = Vector3.One;
private RigidbodyComponent _rigidbody;
public override void Awake()
{
_rigidbody = GameObject.GetComponent<RigidbodyComponent>()!;
}
public override void Update(double parDeltaTime)
{
_rigidbody.AddForce(-Drag * (_rigidbody.Velocity * Coefficient));
}
}

View File

@@ -0,0 +1,44 @@
using OpenTK.Mathematics;
namespace DoomDeathmatch.Component;
public class GravityComponent : Engine.Scene.Component.Component
{
public float Strength { get; set; } = 10.0f;
public Vector3 Direction
{
get => _direction;
set => _direction = value.Normalized();
}
public float Floor { get; set; } = 5.0f;
public bool IsInAir { get; private set; } = false;
private RigidbodyComponent _rigidbody;
private Vector3 _direction = -Vector3.UnitZ;
public override void Awake()
{
_rigidbody = GameObject.GetComponent<RigidbodyComponent>()!;
}
public override void Update(double parDeltaTime)
{
var heightAlongDirection = Vector3.Dot(GameObject.Transform.Translation, Direction);
if (heightAlongDirection > Floor)
{
IsInAir = false;
var velocityAlongDirection = Vector3.Dot(_rigidbody.Velocity, Direction);
if (velocityAlongDirection > 0)
_rigidbody.AddVelocity(-velocityAlongDirection * Direction);
return;
}
IsInAir = true;
var gravity = Strength * Direction;
_rigidbody.AddForce(gravity);
}
}

View File

@@ -0,0 +1,33 @@
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);
}
}

View File

@@ -0,0 +1,39 @@
using OpenTK.Mathematics;
namespace DoomDeathmatch.Component;
public class RigidbodyComponent : Engine.Scene.Component.Component
{
public Vector3 Velocity { get; private set; } = Vector3.Zero;
public Vector3 Acceleration { get; private set; } = Vector3.Zero;
public Vector3 Force { get; private set; } = Vector3.Zero;
public float Mass { get; set; } = 1.0f;
public bool IsStatic { get; set; } = false;
public void AddForce(Vector3 parForce)
{
if (IsStatic)
return;
Force += parForce;
}
public void AddVelocity(Vector3 parVelocity)
{
if (IsStatic)
return;
Velocity += parVelocity;
}
public override void Update(double parDeltaTime)
{
if (IsStatic)
return;
Acceleration = Force / Mass;
Velocity += Acceleration * (float)parDeltaTime;
GameObject.Transform.Translation += Velocity * (float)parDeltaTime;
Force = Vector3.Zero;
}
}

View File

@@ -0,0 +1,14 @@
namespace DoomDeathmatch.Component.UI;
public enum Anchor
{
TopLeft,
TopCenter,
TopRight,
CenterLeft,
Center,
CenterRight,
BottomLeft,
BottomCenter,
BottomRight
}

View File

@@ -0,0 +1,7 @@
namespace DoomDeathmatch.Component.UI;
public enum Orientation
{
Horizontal,
Vertical
}

View File

@@ -0,0 +1,88 @@
using Engine.Input;
namespace DoomDeathmatch.Component.UI;
public class SelectorComponent : Engine.Scene.Component.Component
{
public List<UiComponent> Children => _children;
public KeyboardButtonCode SelectKey { get; set; } = KeyboardButtonCode.Space;
public KeyboardButtonCode NextKey { get; set; } = KeyboardButtonCode.Down;
public KeyboardButtonCode PrevKey { get; set; } = KeyboardButtonCode.Up;
public event Action<UiComponent>? OnSelect;
private readonly IInputHandler _inputHandler = Engine.Engine.Instance.InputHandler!;
private readonly List<UiComponent> _children = [];
private int _selectedIndex = 0;
public override void Start()
{
foreach (var child in Children)
{
child.OnMouseOver += Select;
}
SelectionChanged();
}
public override void Update(double parDeltaTime)
{
if (_inputHandler.IsKeyJustPressed(SelectKey))
_children[_selectedIndex].InvokeClick();
if (_inputHandler.IsKeyJustPressed(NextKey))
{
_selectedIndex++;
if (_selectedIndex >= Children.Count)
_selectedIndex = 0;
SelectionChanged();
}
if (_inputHandler.IsKeyJustPressed(PrevKey))
{
_selectedIndex--;
if (_selectedIndex < 0)
_selectedIndex = Children.Count - 1;
SelectionChanged();
}
UpdatePosition();
}
private void SelectionChanged()
{
OnSelect?.Invoke(Children[_selectedIndex]);
}
private void UpdatePosition()
{
var child = Children[_selectedIndex];
var transformMatrix = child.GameObject.Transform.FullTransformMatrix;
var translation = transformMatrix.ExtractTranslation();
var scale = transformMatrix.ExtractScale();
GameObject.Transform.Translation = translation;
GameObject.Transform.Translation.X -= scale.X / 2 + 0.05f;
GameObject.Transform.Size.Y = scale.Y;
}
private void Select(UiComponent parComponent)
{
var index = Children.IndexOf(parComponent);
if (index < 0)
index = 0;
if (index == _selectedIndex)
return;
_selectedIndex = index;
SelectionChanged();
}
}

View File

@@ -0,0 +1,32 @@
using Engine.Scene;
using OpenTK.Mathematics;
namespace DoomDeathmatch.Component.UI;
public class StackComponent : UiContainerComponent
{
public List<UiComponent> Children => _children;
public Orientation Orientation { get; set; } = Orientation.Vertical;
private readonly List<UiComponent> _children = [];
public override void Update(double parDeltaTime)
{
base.Update(parDeltaTime);
var size = GameObject.Transform.Size.Xy;
var count = _children.Count;
size *= Orientation == Orientation.Horizontal ? new Vector2(1, 0) : new Vector2(0, 1);
var offset = new Vector2(-size.X / 2 + size.X / count / 2, -size.Y / 2 + size.Y / count / 2);
for (var i = count - 1; i >= 0; i--)
{
var child = _children[i];
child.Offset = offset;
offset += size / count;
}
}
}

View File

@@ -0,0 +1,20 @@
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;
}
}

View File

@@ -0,0 +1,54 @@
using Engine.Scene.Component.BuiltIn.Renderer;
using OpenTK.Mathematics;
namespace DoomDeathmatch.Component.UI;
public class TextAlignComponent : Engine.Scene.Component.Component
{
public Align Alignment { get; set; } = Align.Left;
private TextRenderer _textRenderer = null!;
private string? _cachedText;
public override void Awake()
{
_textRenderer = GameObject.GetComponent<TextRenderer>()!;
}
public override void Update(double parDeltaTime)
{
if (_textRenderer.Text == null)
return;
if (_cachedText == _textRenderer.Text)
return;
_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;
GameObject.Transform.Translation.Xy = offset;
}
public Vector2 GetOffset(Vector2 parSize)
{
return Alignment switch
{
Align.Left => new Vector2(0, -parSize.Y / 2),
Align.Center => new Vector2(-parSize.X / 2, -parSize.Y / 2),
Align.Right => new Vector2(-parSize.X, -parSize.Y / 2),
_ => throw new ArgumentOutOfRangeException(nameof(Alignment), Alignment, null)
};
}
public enum Align
{
Left,
Center,
Right
}
}

View File

@@ -0,0 +1,72 @@
using Engine.Input;
using OpenTK.Mathematics;
namespace DoomDeathmatch.Component.UI;
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 event Action<UiComponent>? OnClick;
public event Action<UiComponent>? OnMouseOver;
private readonly IInputHandler _inputHandler = Engine.Engine.Instance.InputHandler!;
public override void Update(double parDeltaTime)
{
if (Container == null)
{
return;
}
GameObject.Transform.Translation.Xy = GetAnchorPosition(Container.GameObject.Transform.Size.Xy) + Offset;
var transformMatrix = GameObject.Transform.FullTransformMatrix;
var translation = transformMatrix.ExtractTranslation();
var scale = transformMatrix.ExtractScale();
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)
{
OnMouseOver?.Invoke(this);
if (_inputHandler.IsMouseButtonJustPressed(MouseButtonCode.Left))
{
OnClick?.Invoke(this);
}
}
}
public void InvokeClick()
{
OnClick?.Invoke(this);
}
private Vector2 GetAnchorPosition(Vector2 parSize)
{
return parSize * GetAnchorRatio();
}
private Vector2 GetAnchorRatio()
{
return Anchor switch
{
Anchor.TopLeft => new Vector2(-0.5f, 0.5f),
Anchor.TopCenter => new Vector2(0, 0.5f),
Anchor.TopRight => new Vector2(0.5f, 0.5f),
Anchor.CenterLeft => new Vector2(-0.5f, 0),
Anchor.Center => new Vector2(0, 0),
Anchor.CenterRight => new Vector2(0.5f, 0),
Anchor.BottomLeft => new Vector2(-0.5f, -0.5f),
Anchor.BottomCenter => new Vector2(0, -0.5f),
Anchor.BottomRight => new Vector2(0.5f, -0.5f),
_ => throw new ArgumentOutOfRangeException(nameof(Anchor), Anchor, null)
};
}
}

View File

@@ -0,0 +1,28 @@
using Engine.Input;
using Engine.Scene.Component.BuiltIn;
using OpenTK.Mathematics;
namespace DoomDeathmatch.Component.UI;
public class UiContainerComponent : UiComponent
{
private readonly IInputHandler _inputHandler = Engine.Engine.Instance.InputHandler!;
public Camera? Camera { get; set; }
public Vector3 MousePosition { get; private set; }
public override void Update(double parDeltaTime)
{
base.Update(parDeltaTime);
if (Camera != null)
{
GameObject.Transform.Size.Xy = Camera.GameObject.Transform.Size.Xy;
MousePosition = Camera.ScreenToWorld(_inputHandler.MousePosition);
}
else if (Container != null)
{
MousePosition = Container.MousePosition;
}
}
}

View File

@@ -1,5 +1,15 @@
using DoomDeathmatch.Component;
using System.Text.Json;
using DoomDeathmatch.Component;
using DoomDeathmatch.Component.UI;
using DoomDeathmatch.Scene.Main;
using DoomDeathmatch.Scene.Rules;
using Engine.Asset.Font;
using Engine.Asset.Font.Metadata;
using Engine.Asset.Mesh;
using Engine.Asset.Mesh.Loader;
using Engine.Graphics.Camera;
using Engine.Graphics.Pipeline;
using Engine.Graphics.Texture;
using Engine.Scene;
using Engine.Scene.Component.BuiltIn;
using Engine.Scene.Component.BuiltIn.Renderer;
@@ -11,32 +21,70 @@ public static class DoomDeathmatch
{
public static void Initialize(Engine.Engine parEngine)
{
parEngine.SceneManager.TransitionTo(MainScene());
parEngine.SceneManager.TransitionTo(MainScene.Create(parEngine));
}
private static Scene MainScene()
{
var cameraObject = new GameObject();
cameraObject.Transform.Translation.Z = -6;
cameraObject.AddComponent<PerspectiveCamera>();
cameraObject.AddComponent<ControllerComponent>();
using var reader = new StreamReader("../DoomDeathmatch/asset/model/test2.obj");
var mesh = ObjMeshLoader.Load(reader);
var box2dRenderer = new GameObject();
box2dRenderer.AddComponent(new MeshRenderer { Mesh = mesh });
box2dRenderer.AddComponent<RotateComponent>();
var testChild = new GameObject();
testChild.Transform.Scale /= 4;
testChild.AddComponent(new MeshRenderer { Mesh = mesh });
var scene = new Scene();
scene.Add(cameraObject);
scene.Add(box2dRenderer);
scene.AddChild(box2dRenderer, testChild);
return scene;
}
// 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;
// }
}

View File

@@ -0,0 +1,52 @@
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.Leaders;
public static class LeadersScene
{
public static Engine.Scene.Scene Create(Engine.Engine parEngine)
{
var scene = new Engine.Scene.Scene();
var (cameraObject, camera) = UiUtil.CreateOrthographicCamera(scene);
var (uiContainerObject, uiContainer) = UiUtil.CreateBackgroundUi(scene, camera);
var (logoObject, logoUi) = UiUtil.CreateLogoUi(parEngine, scene, uiContainer);
var (backUiObject, backUi) = UiUtil.CreateTextUi(scene, uiContainer,
UiUtil.GetDoomFont(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 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) });
scene.AddChild(uiContainerObject, selectorObject);
scene.SetChild(uiContainerObject, logoObject);
scene.SetChild(uiContainerObject, stackObject);
scene.SetChild(stackObject, backUiObject);
return scene;
}
}

View File

@@ -0,0 +1,77 @@
using DoomDeathmatch.Component.UI;
using DoomDeathmatch.Scene.Leaders;
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;
public static class MainScene
{
public static Engine.Scene.Scene Create(Engine.Engine parEngine)
{
var scene = new Engine.Scene.Scene();
var (cameraObject, camera) = UiUtil.CreateOrthographicCamera(scene);
AddMainUi(parEngine, scene, camera);
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);
}
}

View File

@@ -0,0 +1,58 @@
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;
public static class RulesScene
{
public static Engine.Scene.Scene Create(Engine.Engine parEngine)
{
var scene = new Engine.Scene.Scene();
var (cameraObject, camera) = UiUtil.CreateOrthographicCamera(scene);
var (uiContainerObject, uiContainer) = UiUtil.CreateBackgroundUi(scene, camera);
var (logoObject, logoUi) = UiUtil.CreateLogoUi(parEngine, scene, uiContainer);
var (backUiObject, backUi) = UiUtil.CreateTextUi(scene, uiContainer,
parEngine.AssetResourceManager.Load<Font>("font/test"), "Назад");
backUi.OnClick += _ => parEngine.SceneManager.TransitionTo(MainScene.Create(parEngine));
var (rulesObject, rulesUi) = UiUtil.CreateTextUi(scene, uiContainer,
parEngine.AssetResourceManager.Load<Font>("font/test"), "Правила");
var (stackObject, stack) = UiUtil.CreateStackUi(scene, uiContainer,
[rulesUi, backUi]);
stack.Offset = new Vector2(0, -1f);
stackObject.Transform.Size = new Vector3(1f, 6f, 1f);
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) });
scene.AddChild(uiContainerObject, selectorObject);
scene.SetChild(uiContainerObject, logoObject);
scene.SetChild(uiContainerObject, stackObject);
scene.SetChild(stackObject, rulesObject);
scene.SetChild(stackObject, backUiObject);
return scene;
}
}

View File

@@ -0,0 +1,116 @@
using DoomDeathmatch.Component.UI;
using Engine.Asset.Font;
using Engine.Graphics.Texture;
using Engine.Scene;
using Engine.Scene.Component.BuiltIn;
using Engine.Scene.Component.BuiltIn.Renderer;
using OpenTK.Mathematics;
namespace DoomDeathmatch;
public static class UiUtil
{
public static Font GetDoomFont(Engine.Engine parEngine)
{
return parEngine.AssetResourceManager.Load<Font>("font/doom");
}
public static (GameObject, OrthographicCamera) CreateOrthographicCamera(Engine.Scene.Scene parScene)
{
var cameraObject = new GameObject();
var camera = new OrthographicCamera();
cameraObject.AddComponent(camera);
parScene.Add(cameraObject);
return (cameraObject, camera);
}
public static (GameObject, UiComponent) CreateTextUi(Engine.Scene.Scene parScene, UiContainerComponent parContainer,
Font parFont, string parText)
{
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 };
outerObject.AddComponent(uiComponent);
outerObject.AddComponent(new Box2DRenderer { Color = new Vector4(0, 0, 1, 1) });
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 });
parScene.Add(outerObject);
parScene.AddChild(outerObject, innerObject);
return (outerObject, uiComponent);
}
public static (GameObject, UiContainerComponent) CreateBackgroundUi(Engine.Scene.Scene parScene, Camera parCamera)
{
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) });
parScene.Add(uiContainerObject);
return (uiContainerObject, uiContainer);
}
public static (GameObject, UiComponent) CreateLogoUi(Engine.Engine parEngine, Engine.Scene.Scene parScene,
UiContainerComponent parContainer)
{
var logoObject = new GameObject
{
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);
return (logoObject, uiComponent);
}
public static (GameObject, StackComponent) CreateStackUi(Engine.Scene.Scene parScene,
UiContainerComponent parContainer, List<UiComponent> parChildren, Orientation parOrientation = Orientation.Vertical)
{
var stack = new StackComponent
{
Container = parContainer,
Anchor = Anchor.Center
};
stack.Children.AddRange(parChildren);
foreach (var child in parChildren)
{
child.Container = stack;
}
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) });
parScene.Add(stackObject);
return (stackObject, stack);
}
}