Merge branch 'animal-bob' into main
Walking sway for animals (AnimalBobSystem) to make movement feel livelier. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -323,6 +323,7 @@ public sealed class WorldScene : Scene
|
||||
UpdateSystems.Add(new AnimalAppearanceSystem(_needs));
|
||||
UpdateSystems.Add(new AnimalGrowthSystem(Context.Clock, SecondsPerDay, _animals, CellSize));
|
||||
UpdateSystems.Add(new AnimalFacingSystem(_animals, CellSize));
|
||||
UpdateSystems.Add(new AnimalBobSystem(Context.Clock));
|
||||
UpdateSystems.Add(new AnimalMortalitySystem(Store, _animals, CellSize));
|
||||
UpdateSystems.Add(new CorpseSystem(Store, Context.Clock, SecondsPerDay, climate));
|
||||
UpdateSystems.Add(
|
||||
|
||||
@@ -1688,6 +1688,52 @@ public sealed class AnimalFacingSystem(AnimalSet animals, int cellSize)
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// «Раскачка» при ходьбе (презентация): идущий зверь покачивается из стороны в сторону (наклон спрайта
|
||||
/// через <see cref="Transform2D.Rotation"/>), стоящий — плавно выпрямляется. Делает движение живее, не
|
||||
/// затрагивая симуляцию (она вращение не использует). Фаза покачивания идёт по игровому времени (стоп на
|
||||
/// паузе, быстрее на ускорении) и сдвинута по id особи — звери качаются вразнобой. Граница sim/presentation
|
||||
/// цела: система пишет только поворот трансформа.
|
||||
/// </summary>
|
||||
public sealed class AnimalBobSystem(GameClock clock) : QuerySystem<AnimalBrain, Transform2D>
|
||||
{
|
||||
private const float SwaySpeed = 9f; // скорость набега фазы (рад/сек игрового времени)
|
||||
private const float SwayAmplitude = 0.08f; // амплитуда наклона (рад ≈ 4.6°)
|
||||
private const float MinMoveSq = 0.5f * 0.5f; // ближе к цели — считаем стоящим
|
||||
private const float UprightDecay = 0.85f; // как быстро выпрямляется стоя (за кадр)
|
||||
|
||||
private float _phase;
|
||||
|
||||
protected override void OnUpdate()
|
||||
{
|
||||
var dt = clock.DeltaTime;
|
||||
if (dt <= 0f)
|
||||
{
|
||||
return; // пауза — не качаем и не выпрямляем
|
||||
}
|
||||
|
||||
_phase += dt * SwaySpeed;
|
||||
foreach (var (brains, transforms, entities) in Query.Chunks)
|
||||
{
|
||||
var b = brains.Span;
|
||||
var t = transforms.Span;
|
||||
for (var i = 0; i < b.Length; i++)
|
||||
{
|
||||
ref var rot = ref t[i].Rotation;
|
||||
if ((b[i].Target - t[i].Position).LengthSquared() > MinMoveSq)
|
||||
{
|
||||
var offset = entities.EntityAt(i).Id * 0.7f; // десинхрон между особями
|
||||
rot = MathF.Sin(_phase + offset) * SwayAmplitude;
|
||||
}
|
||||
else
|
||||
{
|
||||
rot *= UprightDecay; // у цели/стоя — плавно к вертикали
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Рост и стадии (фаза A3): копит возраст в игровых днях, переключает стадию (Baby→Juvenile→Adult→
|
||||
/// Senior) по порогам из генов и при смене стадии меняет спрайт (детёныш/самка/самец) и размер.
|
||||
|
||||
Reference in New Issue
Block a user