Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- I want to draw the 'fletching' for the bottom side of the arrow as well (should be fletching on top and bottom), mirroring the top, and also make the fletching swept backward instead of front as it is presently (make it point the correct side).
- Here's the modified code for the fletching section in diff-like format:
- ```diff
- // Fletching (3 short diagonal lines)
- const float fletch = 20.0f;
- const float step = 5.0f;
- // Top fletching
- for (int i = 0; i < 3; ++i)
- {
- float x = g_arrowPosX - arrowLen + i * step;
- g_pRenderTarget->DrawLine(
- D2D1::Point2F(x, arrowY),
- - D2D1::Point2F(x + fletch, arrowY - fletch * 0.4f + i * 3.0f),
- + D2D1::Point2F(x - fletch, arrowY - fletch * 0.4f + i * 3.0f),
- g_pBrush, 2.0f);
- }
- + // Bottom fletching
- + for (int i = 0; i < 3; ++i)
- + {
- + float x = g_arrowPosX - arrowLen + i * step;
- + g_pRenderTarget->DrawLine(
- + D2D1::Point2F(x, arrowY),
- + D2D1::Point2F(x - fletch, arrowY + fletch * 0.4f - i * 3.0f),
- + g_pBrush, 2.0f);
- + }
- ```
- Would you like me to explain the changes I made to the code?
- ######################################################################################
- ######################################################################################
- ## endroughxfer-urldump #1#
- ## <EOF><EOF>
- ######################################################################################
- ######################################################################################
- New Code /w Fixes:::
- // BowAndArrow.cpp
- // Simple Win32 / Direct2D demo - "wireframe longbow"
- // Build: cl /EHsc /DUNICODE /D_UNICODE BowAndArrow.cpp d2d1.lib user32.lib gdi32.lib
- #include <windows.h>
- #include <d2d1.h>
- #include <chrono>
- #include <cmath>
- #include <algorithm>
- #pragma comment(lib, "d2d1")
- // -------------------------------------------------
- // Small RAII helper to release COM objects
- // -------------------------------------------------
- template<class T> void SafeRelease(T** pp)
- {
- if (*pp) { (*pp)->Release(); *pp = nullptr; }
- }
- // -------------------------------------------------
- // Animation constants
- // -------------------------------------------------
- constexpr float COCK_TIME = 1.0f; // seconds
- constexpr float HOLD_TIME = 0.5f; // seconds
- constexpr float FIRE_TIME = 1.0f; // seconds
- constexpr UINT TIMER_ID = 1;
- constexpr UINT TIMER_MS = 16; // ~60 FPS
- enum class AnimStage { Cocking, Hold, Firing, Done };
- constexpr float ARROW_REST_OFFSET = 500.0f; // pixels in-front of bow ( > 0 )
- // String pull distance (pixels) and bow X center
- constexpr float STRING_MAX_PULL = 180.0f;
- constexpr float CX_BOW = 220.0f;
- // -------------------------------------------------
- // Global state (kept simple for a demo)
- // -------------------------------------------------
- HWND g_hWnd = nullptr;
- ID2D1Factory* g_pFactory = nullptr;
- ID2D1HwndRenderTarget* g_pRenderTarget = nullptr;
- ID2D1SolidColorBrush* g_pBrush = nullptr;
- float g_windowW = 1280.0f;
- float g_windowH = 720.0f;
- float g_arrowPosX = CX_BOW + ARROW_REST_OFFSET; // head starts free-floating
- // Geometry helpers (depend on window height, so they are updated in WM_SIZE)
- float cx = CX_BOW;
- float topY = 120.0f;
- float bottomY = 600.0f; // will be overwritten in WM_SIZE
- float midY = 360.0f;
- float halfHeight = 240.0f;
- // Animation variables
- AnimStage g_stage = AnimStage::Cocking;
- float g_timeInStage = 0.0f; // seconds
- auto g_prevTick = std::chrono::high_resolution_clock::now();
- float g_stringOffset = 0.0f; // 0 = relaxed, 1 = fully drawn
- //float g_arrowPosX = 0.0f; // head position
- // -------------------------------------------------
- // Helpers
- // -------------------------------------------------
- float Lerp(float a, float b, float t) { return a + (b - a) * t; }
- // Create or re-create render target
- HRESULT CreateDeviceResources()
- {
- if (g_pRenderTarget) return S_OK;
- RECT rc; GetClientRect(g_hWnd, &rc);
- D2D1_SIZE_U size = D2D1::SizeU(rc.right - rc.left,
- rc.bottom - rc.top);
- HRESULT hr = g_pFactory->CreateHwndRenderTarget(
- D2D1::RenderTargetProperties(),
- D2D1::HwndRenderTargetProperties(g_hWnd, size),
- &g_pRenderTarget);
- if (SUCCEEDED(hr))
- hr = g_pRenderTarget->CreateSolidColorBrush(
- D2D1::ColorF(D2D1::ColorF::White), &g_pBrush);
- return hr;
- }
- void DiscardDeviceResources()
- {
- SafeRelease(&g_pBrush);
- SafeRelease(&g_pRenderTarget);
- }
- // -------------------------------------------------
- // Core rendering
- // -------------------------------------------------
- void OnRender()
- {
- if (FAILED(CreateDeviceResources()))
- return;
- g_pRenderTarget->BeginDraw();
- g_pRenderTarget->Clear(D2D1::ColorF(0x202020)); // dark bg
- // -------------------------------------------------
- // 1. Draw Bow limbs (two quadratic curves)
- // -------------------------------------------------
- ID2D1PathGeometry* pGeom = nullptr;
- ID2D1GeometrySink* pSink = nullptr;
- if (SUCCEEDED(g_pFactory->CreatePathGeometry(&pGeom)))
- {
- pGeom->Open(&pSink);
- //--------------------------------------------------------------
- // One continuous ")"-shaped limb with a slightly pointy tip.
- // End-points stay on the string ( (cx, topY) & (cx, bottomY) )
- //--------------------------------------------------------------
- constexpr float NOSE = 35.0f; // how far the tips stick out
- const float BULGE = halfHeight * 0.5f; // max belly distance (x)
- pSink->BeginFigure(D2D1::Point2F(cx, topY), D2D1_FIGURE_BEGIN_HOLLOW);
- // Draw semicircle bow with pointy tip at middle
- // First quarter - top to middle-top
- pSink->AddBezier(
- D2D1::BezierSegment(
- D2D1::Point2F(cx + NOSE, topY + halfHeight * 0.1f), // slight curve at top
- D2D1::Point2F(cx + BULGE, topY + halfHeight * 0.5f), // first quarter curve
- D2D1::Point2F(cx + BULGE + NOSE, midY - NOSE))); // approaching tip
- // Middle part with pointy tip
- pSink->AddBezier(
- D2D1::BezierSegment(
- D2D1::Point2F(cx + BULGE + NOSE * 1.2f, midY - NOSE * 0.5f), // curve to tip
- D2D1::Point2F(cx + BULGE + NOSE * 1.5f, midY), // pointy tip
- D2D1::Point2F(cx + BULGE + NOSE * 1.2f, midY + NOSE * 0.5f))); // curve from tip
- // Last quarter - middle-bottom to bottom
- pSink->AddBezier(
- D2D1::BezierSegment(
- D2D1::Point2F(cx + BULGE + NOSE, midY + NOSE), // after tip
- D2D1::Point2F(cx + BULGE, bottomY - halfHeight * 0.5f), // last quarter curve
- D2D1::Point2F(cx + NOSE, bottomY - halfHeight * 0.1f))); // approaching bottom
- // Connect back to string
- pSink->AddBezier(
- D2D1::BezierSegment(
- D2D1::Point2F(cx + NOSE * 0.5f, bottomY - NOSE * 0.25f), // curve to bottom
- D2D1::Point2F(cx, bottomY), // bottom endpoint
- D2D1::Point2F(cx, bottomY))); // dummy point (required)
- pSink->EndFigure(D2D1_FIGURE_END_OPEN);
- pSink->Close();
- g_pRenderTarget->DrawGeometry(pGeom, g_pBrush, 2.0f);
- SafeRelease(&pSink);
- SafeRelease(&pGeom);
- }
- // -------------------------------------------------
- // 2. Draw Bow string
- // -------------------------------------------------
- float pull = g_stringOffset * STRING_MAX_PULL;
- D2D1_POINT_2F p1 = D2D1::Point2F(cx, topY);
- D2D1_POINT_2F pm = D2D1::Point2F(cx - pull, midY);
- D2D1_POINT_2F p2 = D2D1::Point2F(cx, bottomY);
- g_pRenderTarget->DrawLine(p1, pm, g_pBrush, 2.0f);
- g_pRenderTarget->DrawLine(pm, p2, g_pBrush, 2.0f);
- // -------------------------------------------------
- // 3. Draw Arrow (simple shaft + head + tail)
- // -------------------------------------------------
- float arrowY = midY;
- float arrowLen = 240.0f;
- float arrowHead = 18.0f;
- // Shaft
- g_pRenderTarget->DrawLine(
- D2D1::Point2F(g_arrowPosX, arrowY),
- D2D1::Point2F(g_arrowPosX - arrowLen, arrowY),
- g_pBrush, 2.0f);
- // Arrow head (small triangle)
- D2D1_POINT_2F headPts[3] = {
- D2D1::Point2F(g_arrowPosX, arrowY),
- D2D1::Point2F(g_arrowPosX - arrowHead, arrowY - arrowHead * 0.5f),
- D2D1::Point2F(g_arrowPosX - arrowHead, arrowY + arrowHead * 0.5f)
- };
- g_pRenderTarget->DrawLine(headPts[0], headPts[1], g_pBrush, 2.0f);
- g_pRenderTarget->DrawLine(headPts[0], headPts[2], g_pBrush, 2.0f);
- // Fletching (3 short diagonal lines)
- const float fletch = 20.0f;
- const float step = 5.0f;
- // Top fletching
- for (int i = 0; i < 6; ++i)
- {
- float x = g_arrowPosX - arrowLen + i * step;
- g_pRenderTarget->DrawLine(
- D2D1::Point2F(x, arrowY),
- D2D1::Point2F(x - fletch, arrowY - fletch * 0.4f + i * 3.0f),
- g_pBrush, 2.0f);
- }
- // Bottom fletching
- for (int i = 0; i < 6; ++i)
- {
- float x = g_arrowPosX - arrowLen + i * step;
- g_pRenderTarget->DrawLine(
- D2D1::Point2F(x, arrowY),
- D2D1::Point2F(x - fletch, arrowY + fletch * 0.4f - i * 3.0f),
- g_pBrush, 2.0f);
- }
- // Present
- HRESULT hr = g_pRenderTarget->EndDraw();
- if (hr == D2DERR_RECREATE_TARGET)
- DiscardDeviceResources();
- }
- // -------------------------------------------------
- // Animation tick (called from WM_TIMER)
- // -------------------------------------------------
- void UpdateAnimation()
- {
- // Compute delta time
- auto now = std::chrono::high_resolution_clock::now();
- float dt = std::chrono::duration<float>(now - g_prevTick).count();
- g_prevTick = now;
- g_timeInStage += dt;
- switch (g_stage)
- {
- case AnimStage::Cocking:
- {
- float t = min(g_timeInStage / COCK_TIME, 1.0f);
- g_stringOffset = t; // 0 -> 1 (string pulled left)
- float startX = cx + ARROW_REST_OFFSET; // <<< NEW
- float cockedX = cx - STRING_MAX_PULL + 50.0f; // same as before
- g_arrowPosX = Lerp(startX, cockedX, t);
- if (t >= 1.0f) { g_stage = AnimStage::Hold; g_timeInStage = 0.f; }
- } break;
- case AnimStage::Hold:
- if (g_timeInStage >= HOLD_TIME)
- {
- g_stage = AnimStage::Firing; g_timeInStage = 0.f;
- }
- break;
- case AnimStage::Firing:
- {
- float t = min(g_timeInStage / FIRE_TIME, 1.0f);
- g_stringOffset = 1.0f - t; // 1 -> 0 (same)
- float startX = cx - STRING_MAX_PULL + 50.0f; // << same value as cockedX
- float endX = g_windowW + 100.0f; // fly off screen right
- g_arrowPosX = Lerp(startX, endX, t);
- if (t >= 1.0f)
- {
- g_stage = AnimStage::Cocking; g_timeInStage = 0.f;
- } // loop
- } break;
- case AnimStage::Done:
- // Not used anymore, but kept for completeness
- break;
- }
- // Request redraw
- InvalidateRect(g_hWnd, nullptr, FALSE);
- }
- // -------------------------------------------------
- // Window procedure
- // -------------------------------------------------
- LRESULT CALLBACK WndProc(HWND hWnd, UINT msg,
- WPARAM wParam, LPARAM lParam)
- {
- switch (msg)
- {
- case WM_CREATE:
- if (FAILED(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED,
- &g_pFactory)))
- return -1; // abort window creation
- SetTimer(hWnd, TIMER_ID, TIMER_MS, nullptr);
- g_prevTick = std::chrono::high_resolution_clock::now();
- return 0;
- case WM_SIZE:
- {
- g_windowW = static_cast<float>(LOWORD(lParam));
- g_windowH = static_cast<float>(HIWORD(lParam));
- // Update dependent geometry values
- topY = 120.0f;
- bottomY = g_windowH - 120.0f;
- midY = (topY + bottomY) * 0.5f;
- halfHeight = (bottomY - topY) * 0.5f;
- if (g_pRenderTarget)
- g_pRenderTarget->Resize(
- D2D1::SizeU(static_cast<UINT>(g_windowW),
- static_cast<UINT>(g_windowH)));
- }
- return 0;
- case WM_TIMER:
- if (wParam == TIMER_ID)
- UpdateAnimation();
- return 0;
- case WM_PAINT:
- {
- PAINTSTRUCT ps;
- BeginPaint(hWnd, &ps);
- OnRender();
- EndPaint(hWnd, &ps);
- } return 0;
- case WM_DESTROY:
- KillTimer(hWnd, TIMER_ID);
- DiscardDeviceResources();
- SafeRelease(&g_pFactory);
- PostQuitMessage(0);
- return 0;
- }
- return DefWindowProc(hWnd, msg, wParam, lParam);
- }
- // -------------------------------------------------
- // WinMain - entry point
- // -------------------------------------------------
- int WINAPI wWinMain(HINSTANCE hInst, HINSTANCE, PWSTR, int nCmdShow)
- {
- const wchar_t CLASS_NAME[] = L"BowWindow";
- WNDCLASS wc = {};
- wc.lpfnWndProc = WndProc;
- wc.hInstance = hInst;
- wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
- wc.lpszClassName = CLASS_NAME;
- RegisterClass(&wc);
- g_hWnd = CreateWindowEx(0, CLASS_NAME, L"Direct2D - Longbow Demo",
- WS_OVERLAPPEDWINDOW,
- CW_USEDEFAULT, CW_USEDEFAULT,
- static_cast<int>(g_windowW),
- static_cast<int>(g_windowH),
- nullptr, nullptr, hInst, nullptr);
- ShowWindow(g_hWnd, nCmdShow);
- // Main message loop
- MSG msg;
- while (GetMessage(&msg, nullptr, 0, 0))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- return 0;
- }
- ######################################################################################
- ######################################################################################
- ## endroughxfer-urldump #1#
- ## <EOF><EOF>
- ######################################################################################
- ######################################################################################
- Original Code:::
- // BowAndArrow.cpp
- // Simple Win32 / Direct2D demo - "wireframe longbow"
- // Build: cl /EHsc /DUNICODE /D_UNICODE BowAndArrow.cpp d2d1.lib user32.lib gdi32.lib
- #include <windows.h>
- #include <d2d1.h>
- #include <chrono>
- #include <cmath>
- #include <algorithm>
- #pragma comment(lib, "d2d1")
- // -------------------------------------------------
- // Small RAII helper to release COM objects
- // -------------------------------------------------
- template<class T> void SafeRelease(T** pp)
- {
- if (*pp) { (*pp)->Release(); *pp = nullptr; }
- }
- // -------------------------------------------------
- // Animation constants
- // -------------------------------------------------
- constexpr float COCK_TIME = 1.0f; // seconds
- constexpr float HOLD_TIME = 0.5f; // seconds
- constexpr float FIRE_TIME = 1.0f; // seconds
- constexpr UINT TIMER_ID = 1;
- constexpr UINT TIMER_MS = 16; // ~60 FPS
- enum class AnimStage { Cocking, Hold, Firing, Done };
- constexpr float ARROW_REST_OFFSET = 500.0f; // pixels in-front of bow ( > 0 )
- // String pull distance (pixels) and bow X center
- constexpr float STRING_MAX_PULL = 180.0f;
- constexpr float CX_BOW = 220.0f;
- // -------------------------------------------------
- // Global state (kept simple for a demo)
- // -------------------------------------------------
- HWND g_hWnd = nullptr;
- ID2D1Factory* g_pFactory = nullptr;
- ID2D1HwndRenderTarget* g_pRenderTarget = nullptr;
- ID2D1SolidColorBrush* g_pBrush = nullptr;
- float g_windowW = 1280.0f;
- float g_windowH = 720.0f;
- float g_arrowPosX = CX_BOW + ARROW_REST_OFFSET; // head starts free-floating
- // Geometry helpers (depend on window height, so they are updated in WM_SIZE)
- float cx = CX_BOW;
- float topY = 120.0f;
- float bottomY = 600.0f; // will be overwritten in WM_SIZE
- float midY = 360.0f;
- float halfHeight = 240.0f;
- // Animation variables
- AnimStage g_stage = AnimStage::Cocking;
- float g_timeInStage = 0.0f; // seconds
- auto g_prevTick = std::chrono::high_resolution_clock::now();
- float g_stringOffset = 0.0f; // 0 = relaxed, 1 = fully drawn
- //float g_arrowPosX = 0.0f; // head position
- // -------------------------------------------------
- // Helpers
- // -------------------------------------------------
- float Lerp(float a, float b, float t) { return a + (b - a) * t; }
- // Create or re-create render target
- HRESULT CreateDeviceResources()
- {
- if (g_pRenderTarget) return S_OK;
- RECT rc; GetClientRect(g_hWnd, &rc);
- D2D1_SIZE_U size = D2D1::SizeU(rc.right - rc.left,
- rc.bottom - rc.top);
- HRESULT hr = g_pFactory->CreateHwndRenderTarget(
- D2D1::RenderTargetProperties(),
- D2D1::HwndRenderTargetProperties(g_hWnd, size),
- &g_pRenderTarget);
- if (SUCCEEDED(hr))
- hr = g_pRenderTarget->CreateSolidColorBrush(
- D2D1::ColorF(D2D1::ColorF::White), &g_pBrush);
- return hr;
- }
- void DiscardDeviceResources()
- {
- SafeRelease(&g_pBrush);
- SafeRelease(&g_pRenderTarget);
- }
- // -------------------------------------------------
- // Core rendering
- // -------------------------------------------------
- void OnRender()
- {
- if (FAILED(CreateDeviceResources()))
- return;
- g_pRenderTarget->BeginDraw();
- g_pRenderTarget->Clear(D2D1::ColorF(0x202020)); // dark bg
- // -------------------------------------------------
- // 1. Draw Bow limbs (two quadratic curves)
- // -------------------------------------------------
- ID2D1PathGeometry* pGeom = nullptr;
- ID2D1GeometrySink* pSink = nullptr;
- if (SUCCEEDED(g_pFactory->CreatePathGeometry(&pGeom)))
- {
- pGeom->Open(&pSink);
- //--------------------------------------------------------------
- // One continuous ")"-shaped limb with a slightly pointy tip.
- // End-points stay on the string ( (cx, topY) & (cx, bottomY) )
- //--------------------------------------------------------------
- constexpr float NOSE = 35.0f; // how far the tips stick out
- const float BULGE = halfHeight * 0.5f; // max belly distance (x)
- pSink->BeginFigure(D2D1::Point2F(cx, topY), D2D1_FIGURE_BEGIN_HOLLOW);
- // Draw semicircle bow with pointy tip at middle
- // First quarter - top to middle-top
- pSink->AddBezier(
- D2D1::BezierSegment(
- D2D1::Point2F(cx + NOSE, topY + halfHeight * 0.1f), // slight curve at top
- D2D1::Point2F(cx + BULGE, topY + halfHeight * 0.5f), // first quarter curve
- D2D1::Point2F(cx + BULGE + NOSE, midY - NOSE))); // approaching tip
- // Middle part with pointy tip
- pSink->AddBezier(
- D2D1::BezierSegment(
- D2D1::Point2F(cx + BULGE + NOSE * 1.2f, midY - NOSE * 0.5f), // curve to tip
- D2D1::Point2F(cx + BULGE + NOSE * 1.5f, midY), // pointy tip
- D2D1::Point2F(cx + BULGE + NOSE * 1.2f, midY + NOSE * 0.5f))); // curve from tip
- // Last quarter - middle-bottom to bottom
- pSink->AddBezier(
- D2D1::BezierSegment(
- D2D1::Point2F(cx + BULGE + NOSE, midY + NOSE), // after tip
- D2D1::Point2F(cx + BULGE, bottomY - halfHeight * 0.5f), // last quarter curve
- D2D1::Point2F(cx + NOSE, bottomY - halfHeight * 0.1f))); // approaching bottom
- // Connect back to string
- pSink->AddBezier(
- D2D1::BezierSegment(
- D2D1::Point2F(cx + NOSE * 0.5f, bottomY - NOSE * 0.25f), // curve to bottom
- D2D1::Point2F(cx, bottomY), // bottom endpoint
- D2D1::Point2F(cx, bottomY))); // dummy point (required)
- pSink->EndFigure(D2D1_FIGURE_END_OPEN);
- pSink->Close();
- g_pRenderTarget->DrawGeometry(pGeom, g_pBrush, 2.0f);
- SafeRelease(&pSink);
- SafeRelease(&pGeom);
- }
- // -------------------------------------------------
- // 2. Draw Bow string
- // -------------------------------------------------
- float pull = g_stringOffset * STRING_MAX_PULL;
- D2D1_POINT_2F p1 = D2D1::Point2F(cx, topY);
- D2D1_POINT_2F pm = D2D1::Point2F(cx - pull, midY);
- D2D1_POINT_2F p2 = D2D1::Point2F(cx, bottomY);
- g_pRenderTarget->DrawLine(p1, pm, g_pBrush, 2.0f);
- g_pRenderTarget->DrawLine(pm, p2, g_pBrush, 2.0f);
- // -------------------------------------------------
- // 3. Draw Arrow (simple shaft + head + tail)
- // -------------------------------------------------
- float arrowY = midY;
- float arrowLen = 240.0f;
- float arrowHead = 18.0f;
- // Shaft
- g_pRenderTarget->DrawLine(
- D2D1::Point2F(g_arrowPosX, arrowY),
- D2D1::Point2F(g_arrowPosX - arrowLen, arrowY),
- g_pBrush, 2.0f);
- // Arrow head (small triangle)
- D2D1_POINT_2F headPts[3] = {
- D2D1::Point2F(g_arrowPosX, arrowY),
- D2D1::Point2F(g_arrowPosX - arrowHead, arrowY - arrowHead * 0.5f),
- D2D1::Point2F(g_arrowPosX - arrowHead, arrowY + arrowHead * 0.5f)
- };
- g_pRenderTarget->DrawLine(headPts[0], headPts[1], g_pBrush, 2.0f);
- g_pRenderTarget->DrawLine(headPts[0], headPts[2], g_pBrush, 2.0f);
- // Fletching (3 short diagonal lines)
- const float fletch = 20.0f;
- const float step = 5.0f;
- for (int i = 0; i < 3; ++i)
- {
- float x = g_arrowPosX - arrowLen + i * step;
- g_pRenderTarget->DrawLine(
- D2D1::Point2F(x, arrowY),
- D2D1::Point2F(x + fletch, arrowY - fletch * 0.4f + i * 3.0f),
- g_pBrush, 2.0f);
- }
- // Present
- HRESULT hr = g_pRenderTarget->EndDraw();
- if (hr == D2DERR_RECREATE_TARGET)
- DiscardDeviceResources();
- }
- // -------------------------------------------------
- // Animation tick (called from WM_TIMER)
- // -------------------------------------------------
- void UpdateAnimation()
- {
- // Compute delta time
- auto now = std::chrono::high_resolution_clock::now();
- float dt = std::chrono::duration<float>(now - g_prevTick).count();
- g_prevTick = now;
- g_timeInStage += dt;
- switch (g_stage)
- {
- case AnimStage::Cocking:
- {
- float t = min(g_timeInStage / COCK_TIME, 1.0f);
- g_stringOffset = t; // 0 -> 1 (string pulled left)
- float startX = cx + ARROW_REST_OFFSET; // <<< NEW
- float cockedX = cx - STRING_MAX_PULL + 50.0f; // same as before
- g_arrowPosX = Lerp(startX, cockedX, t);
- if (t >= 1.0f) { g_stage = AnimStage::Hold; g_timeInStage = 0.f; }
- } break;
- case AnimStage::Hold:
- if (g_timeInStage >= HOLD_TIME)
- {
- g_stage = AnimStage::Firing; g_timeInStage = 0.f;
- }
- break;
- case AnimStage::Firing:
- {
- float t = min(g_timeInStage / FIRE_TIME, 1.0f);
- g_stringOffset = 1.0f - t; // 1 -> 0 (same)
- float startX = cx - STRING_MAX_PULL + 50.0f; // << same value as cockedX
- float endX = g_windowW + 100.0f; // fly off screen right
- g_arrowPosX = Lerp(startX, endX, t);
- if (t >= 1.0f)
- {
- g_stage = AnimStage::Cocking; g_timeInStage = 0.f;
- } // loop
- } break;
- case AnimStage::Done:
- // Not used anymore, but kept for completeness
- break;
- }
- // Request redraw
- InvalidateRect(g_hWnd, nullptr, FALSE);
- }
- // -------------------------------------------------
- // Window procedure
- // -------------------------------------------------
- LRESULT CALLBACK WndProc(HWND hWnd, UINT msg,
- WPARAM wParam, LPARAM lParam)
- {
- switch (msg)
- {
- case WM_CREATE:
- if (FAILED(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED,
- &g_pFactory)))
- return -1; // abort window creation
- SetTimer(hWnd, TIMER_ID, TIMER_MS, nullptr);
- g_prevTick = std::chrono::high_resolution_clock::now();
- return 0;
- case WM_SIZE:
- {
- g_windowW = static_cast<float>(LOWORD(lParam));
- g_windowH = static_cast<float>(HIWORD(lParam));
- // Update dependent geometry values
- topY = 120.0f;
- bottomY = g_windowH - 120.0f;
- midY = (topY + bottomY) * 0.5f;
- halfHeight = (bottomY - topY) * 0.5f;
- if (g_pRenderTarget)
- g_pRenderTarget->Resize(
- D2D1::SizeU(static_cast<UINT>(g_windowW),
- static_cast<UINT>(g_windowH)));
- }
- return 0;
- case WM_TIMER:
- if (wParam == TIMER_ID)
- UpdateAnimation();
- return 0;
- case WM_PAINT:
- {
- PAINTSTRUCT ps;
- BeginPaint(hWnd, &ps);
- OnRender();
- EndPaint(hWnd, &ps);
- } return 0;
- case WM_DESTROY:
- KillTimer(hWnd, TIMER_ID);
- DiscardDeviceResources();
- SafeRelease(&g_pFactory);
- PostQuitMessage(0);
- return 0;
- }
- return DefWindowProc(hWnd, msg, wParam, lParam);
- }
- // -------------------------------------------------
- // WinMain - entry point
- // -------------------------------------------------
- int WINAPI wWinMain(HINSTANCE hInst, HINSTANCE, PWSTR, int nCmdShow)
- {
- const wchar_t CLASS_NAME[] = L"BowWindow";
- WNDCLASS wc = {};
- wc.lpfnWndProc = WndProc;
- wc.hInstance = hInst;
- wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
- wc.lpszClassName = CLASS_NAME;
- RegisterClass(&wc);
- g_hWnd = CreateWindowEx(0, CLASS_NAME, L"Direct2D - Longbow Demo",
- WS_OVERLAPPEDWINDOW,
- CW_USEDEFAULT, CW_USEDEFAULT,
- static_cast<int>(g_windowW),
- static_cast<int>(g_windowH),
- nullptr, nullptr, hInst, nullptr);
- ShowWindow(g_hWnd, nCmdShow);
- // Main message loop
- MSG msg;
- while (GetMessage(&msg, nullptr, 0, 0))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement