implemented ECS

This commit is contained in:
2026-06-25 22:10:44 +05:00
parent a153e90c16
commit 3c662a1cbe
6 changed files with 164 additions and 22 deletions
+11
View File
@@ -0,0 +1,11 @@
namespace Kamni.Engine;
public class Component
{
public Entity E { get; internal init; } = null!;
public virtual void Update(FrameInfo frame)
{
}
}
+48
View File
@@ -0,0 +1,48 @@
using Raylib_cs;
namespace Kamni.Engine;
public class Entity
{
public readonly long Id;
public Vector2 Position;
public Vector2 Scale;
public float Rotation;
private readonly Dictionary<Type, Component> _components = new();
internal Entity(long id)
{
Id = id;
}
internal void InvokeUpdate(FrameInfo frame)
{
foreach (var (type, component) in _components)
{
component.Update(frame);
}
}
public T AddComponent<T>() where T : Component, new()
{
var component = new T() { E = this };
_components.Add(typeof(T), component);
return component;
}
public T? TryGetComponent<T>() where T : Component
{
if (_components.TryGetValue(typeof(T), out var component))
return (T)component;
return null;
}
public T GetComponent<T>() where T : Component
{
var component = TryGetComponent<T>();
if (component is null)
throw new Exception($"Component '{typeof(T).AssemblyQualifiedName}' not found in entity {Id}");
return component;
}
}
+3
View File
@@ -0,0 +1,3 @@
namespace Kamni.Engine;
public record struct FrameInfo(long Number, float deltaT);
+31
View File
@@ -0,0 +1,31 @@
namespace Kamni.Engine;
public class Scene
{
// TODO: Replace List with some structure with fast Remove(id)
private readonly List<Entity?> _entities = new();
public IReadOnlyList<Entity?> Entities => _entities;
public Entity CreateEntity()
{
Entity e = new Entity(_entities.Count);
_entities.Add(e);
return e;
}
public void RemoveEntity(Entity e)
{
// waste 8 bytes in the list to store null at index e.Id
// TODO: remove memory leak
_entities[(int)e.Id] = null;
}
internal void InvokeUpdate(FrameInfo frame)
{
foreach (var entity in _entities)
{
entity?.InvokeUpdate(frame);
}
}
}
+8
View File
@@ -0,0 +1,8 @@
using Raylib_cs;
namespace Kamni.Engine;
public class Sprite
{
public Texture2D Texture;
}
+63 -22
View File
@@ -1,14 +1,16 @@
global using System;
global using System.Numerics;
global using System.Collections.Generic;
global using DTLib.Logging;
global using DTLib.Filesystem;
global using File = DTLib.Filesystem.File;
global using Directory = DTLib.Filesystem.Directory;
global using Path = DTLib.Filesystem.Path;
global using static Raylib_cs.Raylib;
using System.Linq;
using System.Runtime.InteropServices;
using Kamni.Engine;
using Raylib_cs;
using static Raylib_cs.Raylib;
namespace Kamni;
@@ -17,6 +19,9 @@ public static class Program
public static readonly Version GameVersion = new(0, 1, 0);
public static Settings Settings { get; private set; } = null!;
public static ILogger Logger { get; private set; } = null!;
public static Camera2D Camera = new(new Vector2(), new Vector2(), 0, 1);
public static int Main(string[] args)
{
@@ -52,43 +57,79 @@ public static class Program
SetWindowMinSize(480, 360);
InitWindow(Settings.WindowMode == WindowMode.Window ? 720 : 0 , Settings.WindowMode == WindowMode.Window ? 480 : 0, $"Kamni v{GameVersion}");
var scene = new Scene();
var octagon0 = scene.CreateEntity().AddComponent<PolygonalSprite>();
var octagon1 = scene.CreateEntity().AddComponent<PolygonalSprite>();
var octagon2 = scene.CreateEntity().AddComponent<PolygonalSprite>();
var octagon3 = scene.CreateEntity().AddComponent<PolygonalSprite>();
var octagon4 = scene.CreateEntity().AddComponent<PolygonalSprite>();
var octagon5 = scene.CreateEntity().AddComponent<PolygonalSprite>();
var octagon6 = scene.CreateEntity().AddComponent<PolygonalSprite>();
octagon0.Color = Color.Red;
octagon0.E.Position = new(0, -100);
octagon1.Color = Color.Pink;
octagon1.E.Position = new(-100, -50);
octagon2.Color = Color.Orange;
octagon2.E.Position = new(100, -50);
octagon3.Color = Color.Purple;
octagon3.E.Position = new(-150, 25);
octagon4.Color = Color.Yellow;
octagon4.E.Position = new(150, 25);
octagon5.Color = Color.SkyBlue;
octagon5.E.Position = new(-60, 75);
octagon6.Color = Color.Green;
octagon6.E.Position = new(60, 75);
FrameInfo frameInfo = new FrameInfo();
while (!WindowShouldClose())
{
BeginDrawing();
DrawFrame();
frameInfo.Number++;
frameInfo.deltaT = GetFrameTime();
Vector2 center = new(GetRenderWidth() / 2f, GetRenderHeight() / 2f);
Camera.Offset = center;
ClearBackground(Color.DarkBlue);
BeginMode2D(Camera);
scene.InvokeUpdate(frameInfo);
EndMode2D();
DrawFPS(5, 5);
EndDrawing();
}
CloseWindow();
return 0;
}
static float[] randomRotations = [];
static float sumT = 999999;
static void DrawFrame()
class PolygonalSprite : Component
{
public Color Color = Color.White;
public int Sides = 5;
public int Radius = 32;
Vector2 center = new(GetRenderWidth() / 2f, GetRenderHeight() / 2f);
float deltaT = GetFrameTime();
sumT += deltaT;
if (sumT > 0.5)
static float sumT = 999999;
public override void Update(FrameInfo frame)
{
sumT = 0;
randomRotations = Enumerable.Range(0, 7).Select(_ => (float)Random.Shared.Next(-30, 30)).ToArray();
DrawPoly(E.Position, Sides, Radius, E.Rotation, Color);
sumT += frame.deltaT;
if (sumT > 0.5)
{
sumT = 0;
E.Rotation = Random.Shared.Next(-30, 30);
}
}
ClearBackground(Color.DarkBlue);
DrawPoly(new(center.X, center.Y - 100), 5, 32, randomRotations[0], Color.Red);
DrawPoly(new(center.X - 100, center.Y - 50), 5, 32, randomRotations[1], Color.Pink);
DrawPoly(new(center.X + 100, center.Y - 50), 5, 32, randomRotations[2], Color.Orange);
DrawPoly(new(center.X - 150, center.Y + 25), 5, 32, randomRotations[3], Color.Purple);
DrawPoly(new(center.X + 150, center.Y + 25), 5, 32, randomRotations[4], Color.Yellow);
DrawPoly(new(center.X - 60, center.Y + 75), 5, 32, randomRotations[3], Color.SkyBlue);
DrawPoly(new(center.X + 60, center.Y + 75), 5, 32, randomRotations[4], Color.Green);
// DrawPoly(new (center.X + 75, center.Y + 25), 5, 32, 0, Color.Orange);
DrawFPS(5, 5);
}
[UnmanagedCallersOnly(CallConvs = [typeof(System.Runtime.CompilerServices.CallConvCdecl)])]
private static unsafe void RaylibLogHandler(int logLevel_, sbyte* text_, sbyte* args_)
{