Siv3D / OpenSiv3D

C++20 framework for creative coding 🎮🎨🎹 / Cross-platform support (Windows, macOS, Linux, and the Web)
https://siv3d.github.io/
MIT License
994 stars 136 forks source link

Circularに.lerpを追加 #1203

Closed zaligan closed 1 month ago

zaligan commented 6 months ago

追加する機能の内容 | Describe the solution you'd like Circularにlerp関数を実装する。

その機能の追加によって解決する問題 | Is your feature request related to a problem? Please describe. Circularでr,theta両方を一定の割合で変化させたい時、現状ではrとtheta別々にlerp関数を実行する必要があるが、以下のように1行で求めることが可能となる。

// スタート位置(Circular )からゴール位置(Circular )へ t の割合だけ進んだ位置
const Circular pos = from.lerp(to, t);

備考 | Additional context 実装してもよければプルリクエストを出します。

Reputeless commented 6 months ago

実装判断の前に Circular の Lerp にニーズがあるか・自然な挙動になるかを確認したいので、 実装予定の Circular の Lerp の動きを体験できる、現行版向けのサンプルプログラムを書いてもらえますか。

zaligan commented 6 months ago

左クリックした場所へ向けて円が移動(Lerp)するサンプルとなります。

# include <Siv3D.hpp>

/// @brief from から to へ t の割合で Lerp する
/// @param スタート地点です。
/// @param to ゴール地点です。
/// @param t スタート地点からゴール地点までの割合です。
/// @return t の割合だけ進んだ座標のCircular
[[nodiscard]]
Circular Lerp(const Circular& from, const Circular& to, double t) noexcept
{
    return Circular{ Math::Lerp(from.r, to.r, t), Math::LerpAngle(from.theta, to.theta, t) };
}

void Main()
{
    Scene::SetBackground(ColorF{ 0.6, 0.8, 0.7 });

    Window::Resize(1280, 720);

    // 2D カメラ
    Camera2D camera{ Vec2{ 0, 0 }, 1.0, CameraControl::None_ };

    Circular from(100, 0);

    Circular to = from;

    Circular pos = from;

    Circle c1{ pos, 10 };

    Stopwatch stopwatch{ StartImmediately::Yes };

    while (System::Update())
    {
        // 移動の割合 0.0~1.0
        const double t = Min(stopwatch.sF(), 1.0);

        // from から to へ t の割合で Lerp する
        pos = Lerp(from, to, t);

        c1.setCenter(pos);

        // クリックした座標へ移動
        if (MouseL.down())
        {
            from = pos;
            to = Circular{ Cursor::PosF() - Scene::Center() };
            stopwatch.restart();
        }

        // 2D カメラを更新
        camera.update();
        {
            // 2D カメラの設定から Transformer2D を作成する
            const auto t = camera.createTransformer();

            for (int32 i = 0; i < 8; ++i)
            {
                Circle{ 0, 0, (50 + i * 50) }.drawFrame(2);
            }

            c1.draw(Palette::Pink);

        }

        // 2D カメラ操作の UI を表示する
        camera.draw(Palette::Orange);
    }
}
Reputeless commented 6 months ago

サンプルありがとうございます。円周上の 2 点間の移動、見た目的に問題なさそうです。 実装ができ次第、pull request を作成していただいて OK です。