reckfellENGINE

Своя отрисовка 2D: _Draw и QueueRedraw

Нарисовать метку, обновлять её только при изменении данных и правильно применять трансформацию.

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

Полный пример без текстур

LocalMarker рисует круг и две линии в собственных координатах. Центр — Vector2.Zero; Position самой Entity перемещает готовый рисунок. DrawCircle не создаёт физическое тело, область клика или Control: взаимодействие задаётся отдельно.

Нужен C#-проект Reckfell.NET.Sdk 1.0.0, net10.0. Сохраните LocalMarker.cs и CanvasExample.cs в проект, выполните dotnet build, создайте уровень с корнем Entity2D, прикрепите CanvasExample.cs и сохраните .rscene. Запустите: видны белая метка мира и синий маркер HUD. Обработчик щелчка в примере переносит белую метку.

LocalMarker.cs
C#
using Reckfell;

public partial class LocalMarker : Entity2D
{
    public float Radius { get; private set; } = 12;
    public Color Ink { get; private set; } = Colors.White;
    public int DrawCount { get; private set; }

    public bool SetStyle(float radius, Color ink)
    {
        if (!float.IsFinite(radius) || radius <= 0 || radius > 256)
            return false;
        Radius = radius;
        Ink = ink;
        QueueRedraw();
        return true;
    }

    public override void _Draw()
    {
        DrawCount++;
        DrawCircle(Vector2.Zero, Radius, Ink);
        DrawLine(new Vector2(-Radius, 0), new Vector2(Radius, 0), Colors.Black, 2);
        DrawLine(new Vector2(0, -Radius), new Vector2(0, Radius), Colors.Black, 2);
    }
}
CanvasExample.cs
C#
using Reckfell;

public partial class CanvasExample : Entity2D
{
    public Entity2D Rig { get; private set; } = null!;
    public LocalMarker Marker { get; private set; } = null!;
    public Camera2D Camera { get; private set; } = null!;
    public CanvasLayer Hud { get; private set; } = null!;
    public LocalMarker HudMarker { get; private set; } = null!;

    public override void _Ready()
    {
        Rig = new Entity2D { Position = new Vector2(64, 48) };
        AddChild(Rig);
        Marker = new LocalMarker { Position = new Vector2(24, 0) };
        Rig.AddChild(Marker);
        Camera = new Camera2D { Position = new Vector2(160, 120) };
        AddChild(Camera);
        Camera.MakeCurrent();
        Hud = new CanvasLayer { Layer = 1, FollowViewportEnabled = false };
        AddChild(Hud);
        HudMarker = new LocalMarker { Position = new Vector2(24, 24) };
        HudMarker.SetStyle(8, new Color(0.25f, 0.45f, 1));
        Hud.AddChild(HudMarker);
        var label = new Label { Position = new Vector2(42, 12), Text = "HUD" };
        Hud.AddChild(label);
    }

    public override void _UnhandledInput(InputEvent input)
    {
        if (input is InputEventMouseButton { Pressed: true, ButtonIndex: MouseButton.Left })
            Marker.Position = Rig.ToLocal(Rig.GetGlobalMousePosition());
    }
}

Как обновляется рисунок

_Draw вызывается движком для записи команд рисования. Вызывайте DrawCircle и DrawLine внутри _Draw; не переносите их в _Process. Сохранённые команды используются при следующих кадрах: _Draw не является callback каждого кадра.

SetStyle сначала проверяет радиус, затем меняет данные и вызывает QueueRedraw. Это запрос отложенной перерисовки, а не немедленный вызов _Draw. Несколько запросов до обработки объединяются. DrawCount здесь нужен для наблюдения за callback, а не для измерения количества draw calls GPU.

Для анимируемой формы меняйте её данные в _Process с учётом delta и запрашивайте QueueRedraw. Если меняется только Position, Rotation или Scale, трансформация применяется к сохранённым командам: заново генерировать тот же круг не требуется.

Настроить форму

Radius задан в локальных единицах. Масштаб родителя изменяет и круг, и толщину его линий; неравномерный масштаб превращает круг в эллипс. Чтобы метка оставалась постоянного размера в HUD, держите её в независимом CanvasLayer с подходящим масштабом.

Положительная width в DrawLine задаёт толщину. Отрицательная ширина использует другой режим линии, который иначе ведёт себя при масштабировании. Пример явно задаёт 2. Сглаживание и чёткость тонких линий зависят от выбранного режима, координат и растяжения Viewport; этот пример не настраивает общий AA проекта.

Если изменения не видны

  • Поменяли поле Radius или Ink напрямую: свойства закрыты для записи; используйте SetStyle, который вызывает QueueRedraw.
  • SetStyle вернул false: радиус должен быть конечным и находиться в (0,256]. Это ограничение примера.
  • Вызвали QueueRedraw вне дерева: запрос не сохраняется как бесконечная очередь. При добавлении видимого CanvasItem движок организует начальную отрисовку.
  • Ждёте новые пиксели сразу после вызова: дождитесь кадра. Callback, отправка и отображение — разные этапы.
  • Вызываете QueueRedraw из _Draw: перенесите изменение состояния наружу. Не стройте цикл перерисовки внутри callback.

Координаты · Слои

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

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

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

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