Add attribute system with core stats and gameplay components

This commit is contained in:
2025-10-13 12:10:45 +02:00
commit ce3596efaa
55 changed files with 1161 additions and 0 deletions

View File

@@ -0,0 +1,8 @@
using GameCore.ECS.Interfaces;
namespace GameCore.Movement;
public class CharacterStateComponent : IComponent
{
public bool IsOnFloor { get; set; }
}

View File

@@ -0,0 +1,23 @@
using GameCore.ECS;
using GameCore.ECS.Interfaces;
using GameCore.Physics;
namespace GameCore.Movement;
public class GravitySystem : ISystem
{
public void Update(World world, float deltaTime)
{
var entities = world.GetEntitiesWith<VelocityComponent>();
foreach (var entity in entities)
{
var velocity = world.GetComponent<VelocityComponent>(entity);
var characterState = world.GetComponent<CharacterStateComponent>(entity);
if (velocity == null || characterState == null)
continue;
if (!characterState.IsOnFloor) velocity.DesiredVelocity.Y -= world.Config.GravityStrength * deltaTime;
}
}
}

View File

@@ -0,0 +1,61 @@
using GameCore.Attributes;
using GameCore.ECS;
using GameCore.ECS.Interfaces;
using GameCore.Input;
using GameCore.Math;
using GameCore.Physics;
using Attribute = GameCore.Attributes.Attribute;
namespace GameCore.Movement;
public class GroundMovementSystem : ISystem
{
public void Update(World world, float deltaTime)
{
var entities = world.GetEntitiesWith<InputStateComponent>();
foreach (var entity in entities)
{
var input = world.GetComponent<InputStateComponent>(entity);
var velocity = world.GetComponent<VelocityComponent>(entity);
var attributes = world.GetComponent<AttributeComponent>(entity);
var rotation = world.GetComponent<RotationComponent>(entity);
if (input == null || velocity == null || attributes == null || rotation == null)
continue;
var moveSpeed = attributes.GetValue(Attribute.MoveSpeed);
var acceleration = attributes.GetValue(Attribute.Acceleration);
var friction = attributes.GetValue(Attribute.Friction);
var yaw = rotation.Rotation.Y;
var rotatedDir = world.WorldQuery.RotateVectorByYaw(input.MoveDirection, yaw);
var targetVelocity = new Vector3(
rotatedDir.X * moveSpeed,
velocity.DesiredVelocity.Y,
rotatedDir.Z * moveSpeed
);
if (rotatedDir.Length() >= 0.1f)
{
velocity.DesiredVelocity =
MoveToward(velocity.DesiredVelocity, targetVelocity, acceleration * deltaTime);
}
else
{
var frictionVec = new Vector3(velocity.DesiredVelocity.X, 0f, velocity.DesiredVelocity.Z);
frictionVec = MoveToward(frictionVec, Vector3.Zero, friction * deltaTime);
velocity.DesiredVelocity.X = frictionVec.X;
velocity.DesiredVelocity.Z = frictionVec.Z;
}
}
}
private Vector3 MoveToward(Vector3 from, Vector3 to, float delta)
{
var diff = to - from;
if (diff.Length() <= delta)
return to;
return from + diff.Normalize() * delta;
}
}

View File

@@ -0,0 +1,32 @@
using GameCore.Attributes;
using GameCore.ECS;
using GameCore.ECS.Interfaces;
using GameCore.Input;
using GameCore.Physics;
using Attribute = GameCore.Attributes.Attribute;
namespace GameCore.Movement;
public class JumpSystem : ISystem
{
public void Update(World world, float deltaTime)
{
var entities = world.GetEntitiesWith<InputStateComponent>();
foreach (var entity in entities)
{
var input = world.GetComponent<InputStateComponent>(entity);
var velocity = world.GetComponent<VelocityComponent>(entity);
var attributes = world.GetComponent<AttributeComponent>(entity);
var characterState = world.GetComponent<CharacterStateComponent>(entity);
if (input == null || velocity == null || attributes == null || characterState == null)
continue;
if (input.IsJumping && characterState.IsOnFloor)
{
var jumpHeight = attributes.GetValue(Attribute.JumpHeight);
velocity.DesiredVelocity.Y = (float)System.Math.Sqrt(2f * world.Config.GravityStrength * jumpHeight);
}
}
}
}

View File

@@ -0,0 +1,9 @@
using GameCore.ECS.Interfaces;
using GameCore.Math;
namespace GameCore.Movement;
public class RotationComponent : IComponent
{
public Vector3 Rotation;
}

View File

@@ -0,0 +1,29 @@
using GameCore.ECS;
using GameCore.ECS.Interfaces;
using GameCore.Input;
namespace GameCore.Movement;
public class RotationSystem : ISystem
{
private const float MinPitch = -(float)System.Math.PI / 2f;
private const float MaxPitch = (float)System.Math.PI / 2f;
public void Update(World world, float deltaTime)
{
var entities = world.GetEntitiesWith<InputStateComponent>();
foreach (var entity in entities)
{
var input = world.GetComponent<InputStateComponent>(entity);
var rotation = world.GetComponent<RotationComponent>(entity);
if (input == null || rotation == null)
continue;
rotation.Rotation.Y += input.LookDirection.Y;
rotation.Rotation.X += input.LookDirection.X;
rotation.Rotation.X = System.Math.Clamp(rotation.Rotation.X, MinPitch, MaxPitch);
}
}
}