[ad_1]
この問題を非常に簡単に説明します。カラー アニメーションを取得するには、色をスムーズに変更するために lerp アルゴリズムを使用する必要があります。これには、アニメーションの進行状況 (std::min)((deltaTime /duration), 1.0f が必要です。 ) しかし、このアニメーション手法を使用すると、アニメーション期間中にアニメーションが実行されますが、進行状況が 1 に達しないという問題があり、追加の CPU 消費を避けるためにタイマーを終了できます。
ウィンドウ クラスの処理には Direct2D API と Win32 API を使用していることに注意してください。
コードを紹介する前に、次のコードにあるウィンドウを更新する方法を説明します。
void Window::CreateTimer(bool update, std::uint16_t frameRate, std::uint64_t timerId) { SetTimer(m_Hwnd, timerId, 1000 / frameRate, nullptr); if (update) { HandleTimerEvent([&](const Event& event) { InvalidateRect(m_hWnd, nullptr, false); }); } }
更新フラグが true の場合、WM_TIMER を処理して、フレーム レート (この場合は 60 Hz) に基づいてウィンドウを無効にします。
ColorTransition の実装は次のとおりです。
class Transition { protected: Transition(Window* window, float duration) : m_Window(window), m_Duration(duration) { srand(static_cast<std::uint32_t>(time(nullptr))); QueryPerformanceFrequency(&m_Frequency); QueryPerformanceCounter(&m_LastFrameTime); SetTimerId(); SetFrameRate(); m_Window->CreateTimer(true, m_FrameRate, m_TimerId); } public: virtual void Update() = 0; public: void SetLastFrameTime() { m_LastFrameTime = m_CurrentTime; } void SetTimerId() { m_TimerId = static_cast<std::uint32_t>(rand()); } void SetFrameRate(std::uint32_t frameRate = 60) { m_FrameRate = frameRate; KillTimer(m_Window->GetWindow(), m_TimerId); m_Window->CreateTimer(true, m_FrameRate, m_TimerId); } protected: float m_Duration; Window* m_Window; LARGE_INTEGER m_Frequency, m_LastFrameTime, m_CurrentTime; std::uint32_t m_FrameRate, m_TimerId; bool m_IsDone; }; class ColorTransition : public Transition { public: ColorTransition(Window* window, float duration, D2D1::ColorF start, D2D1::ColorF end) : Transition(window, duration), m_Start(start), m_End(end), m_Color(start) { } D2D1::ColorF GetColor() const { return D2D1::ColorF( m_Color.r / 255.0f, m_Color.g / 255.0f, m_Color.b / 255.0f, m_Color.a / 255.0f); } void Update() override { QueryPerformanceCounter(&m_CurrentTime); float deltaTime = static_cast<float>(m_CurrentTime.QuadPart - m_LastFrameTime.QuadPart) / static_cast<float>(m_Frequency.QuadPart); float progress = (std::min)((deltaTime / m_Duration), 1.0f); m_Color.r = Lerp(m_Color.r, m_End.r, progress); m_Color.g = Lerp(m_Color.g, m_End.g, progress); m_Color.b = Lerp(m_Color.b, m_End.b, progress); m_Color.a = Lerp(m_Color.a, m_End.a, progress); if (progress >= 1.0f) { KillTimer(m_Window->GetWindow(), m_TimerId); m_IsDone = true; } } float Lerp(float start, float end, float progress) { return start + (end - start) * progress; } private: D2D1::ColorF m_Start, m_End, m_Color; };
ColorTransition.h を含む main.cpp:
ColorTransition transition(&window, 1.0f, D2D1::ColorF(0, 55, 255), D2D1::ColorF(255, 0, 0)); window.HandlePaintEvent[&](const Event& event) { ID2D1HwndRenderTarget* renderTarget = event.GetRenderTarget(); ID2D1SolidColorBrush* brush = nullptr; renderTarget->CreateSolidColorBrush( transition.GetColor(), &brush ); transition.Update(); renderTarget->FillRectangle( D2D1::RectF(10, 10, 110, 110), brush ); transition.SetLastFrameTime(); });
コードは理解するのが非常に簡単だと思うので、コードの説明は省略します。そして、私の問題が実際に何であるかを理解するのに十分なコードを提供したと思います。
私が試したこと:
たとえば、m_ElapsedTime という変数を使用して、最後のフレームからの経過時間を保存し、それが動作するトランジションアニメーションと等しいかどうかを確認できますが、トランジションがほぼ完了する前に停止し、それに対する解決策が見つかりませんでした。 。 私の場合、解決策を見つけるためにしばらく調べていたため、この種のアニメーションについての詳細はあまりありませんでした。そのため、ここで質問する必要がありました。 より良いアルゴリズムやその解決策を知っている場合は、私を助けてください。そして、私のコードが私が言ったように機能しない理由を説明してください。
[ad_2]
コメント