reckfellENGINE

AnimatedSprite2D: кадры, атлас и управление временем

Собрать SpriteFrames и различать паузу, остановку, цикл и изменение скорости.

На этой странице

Разделить данные и воспроизведение

SpriteFrames — ресурс с именованными анимациями, текстурами кадров и длительностями. AnimatedSprite2D хранит состояние проигрывания: Animation, Frame, FrameProgress, SpeedScale. Две Entity могут использовать один ресурс кадров, сохраняя собственные позиции воспроизведения. Изменение общего SpriteFrames затронет обе; создайте отдельный ресурс, если набор кадров должен отличаться.

Для runnable-примера возьмите четыре файла и порядок запуска из движения 2D. ActorFrames.cs ниже полностью создаёт атлас 128×32, четыре региона по 32×32 и клипы idle/walk. Сторонние текстуры, импорт и ручная нарезка не нужны.

ActorFrames.cs
C#
using Reckfell;

public static class ActorFrames
{
    public static SpriteFrames Create()
    {
        using var image = Image.CreateEmpty(128, 32, false, Image.Format.Rgba8);
        image.Fill(Colors.Transparent);
        for (int i = 0; i < 4; i++)
        {
            int x = i * 32;
            int stride = i == 1 ? 3 : i == 3 ? -3 : 0;
            image.FillRect(new Rect2I(x + 9, 4, 14, 16), Colors.White);
            image.FillRect(new Rect2I(x + 19, 8, 3, 3), Colors.Black);
            image.FillRect(new Rect2I(x + 9 + stride, 20, 5, 8), new Color(0.25f, 0.45f, 1));
            image.FillRect(new Rect2I(x + 18 - stride, 20, 5, 8), new Color(0.25f, 0.45f, 1));
        }
        var atlas = ImageTexture.CreateFromImage(image);
        var frames = new SpriteFrames();
        frames.RemoveAnimation("default");
        frames.AddAnimation("idle");
        frames.SetAnimationLoopMode("idle", SpriteFrames.LoopMode.Linear);
        frames.SetAnimationSpeed("idle", 1);
        frames.AddAnimation("walk");
        frames.SetAnimationLoopMode("walk", SpriteFrames.LoopMode.Linear);
        frames.SetAnimationSpeed("walk", 8);
        for (int i = 0; i < 4; i++)
        {
            var region = new AtlasTexture { Atlas = atlas, Region = new Rect2(i * 32, 0, 32, 32) };
            frames.AddFrame("walk", region, i == 2 ? 2 : 1);
            if (i == 0) frames.AddFrame("idle", region);
        }
        return frames;
    }
}

Подставить свой атлас

Замените создание Image/ImageTexture загрузкой своей Texture2D и оставьте нарезку через AtlasTexture. Region задаётся в пикселях исходного изображения, не в диапазоне 0..1. Для сетки с отступами и промежутками учитывайте их при расчёте начала каждого региона. Держите одинаковое положение опорной точки персонажа внутри кадров: иначе картинка будет дёргаться даже при неподвижной Entity.

TextureFilter=Nearest в TopDownActor сохраняет жёсткие пиксельные границы. Это не настраивает импорт, размер Viewport или общий масштаб игры. FlipH зеркалит только изображение; Offset и Centered определяют его размещение относительно позиции Entity. При смене рисунка настройте физическую Shape отдельно.

Посчитать длительность

При положительной скорости длительность кадра в секундах равна relativeDuration / (animationFps × abs(SpeedScale × customSpeed)). customSpeed — аргумент Play. В примере walk имеет FPS=8 и веса 1,1,2,1. Полный линейный цикл длится 5/8=0,625 секунды при обоих множителях 1. Вес 2 означает удвоенную длительность кадра, а не две секунды.

SpeedScale=0 замораживает продвижение, но IsPlaying остаётся true, если проигрывание не остановлено. GetPlayingSpeed возвращает множитель со знаком, без FPS и веса кадра. Не используйте один IsPlaying для вывода «кадры сейчас меняются».

Управлять курсором

ДействиеРезультат
Play("walk")Запуск; после Pause продолжает тот же клип с сохранённого места
Pause()Сохраняет Frame и FrameProgress, выключает проигрывание
Stop()Останавливает и сбрасывает курсор к началу
SetFrameAndProgress(frame, progress)Явно задаёт кадр и его долю; обычно progress в [0,1]
PlayBackwards("walk")Запускает обратное проигрывание; положительный SpeedScale нужен для ожидаемого направления

Смена клипа через Play выбирает его начало, если не задан fromEnd. Чтобы принудительно перезапустить уже выбранный клип, вызовите Stop, затем Play. Не сбрасывайте Frame=0 в каждом _Process: анимация будет застревать на первом кадре. В движении из примера Play вызывается только при смене имени состояния.

Выбрать цикл и дождаться завершения

Используйте актуальный SetAnimationLoopMode: LoopMode.None для однократного проигрывания, Linear для обычного цикла, Pingpong для смены направления на концах. Пример нативно проверен для Linear и None; режим Pingpong сверён с исходником.

AnimationFinished приходит для завершившегося однократного клипа. Для циклического клипа используйте AnimationLooped. Если ждать AnimationFinished у ходьбы с Linear, ожидание не закончится при очередном обороте. FrameChanged означает изменение кадра, а не обязательно завершение действия или игровой удар.

Для атаки или другого игрового события задайте отдельное правило синхронизации: покадровая картинка сама не создаёт хитбокс и не гарантирует один игровой эффект на входной сигнал.

Полный персонаж · Своя отрисовка

Документация Reckfell EngineНаверх ↑
БЫСТРЫЙ ПЕРЕХОДНачало работыEntity и иерархияC# & .NET 10Сцены и префабы
Руководства и полный API Reckfell K
reckfellENGINE
RECKFELL ACCOUNT

Вход в аккаунт

Войдите в аккаунт Reckfell.

Один аккаунт для всей платформы Reckfell.