首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C >> 關於C

HGE 引擎入門:基於 Win32 SDK 實現 2D 物理碰撞模擬(含摩擦、反彈、聲音設計)

     編輯:關於C

HGE (Haaf's Game Engine) 是一款輕量級 2D 遊戲引擎,適合學習遊戲核心循環與物理模擬。本文通過一個「快樂小球」Demo,展示如何在 Win32 SDK 原生環境下實現帶摩擦力的碰撞反彈,並討論聲音參數設計思路。

核心物理模型

  1. 速度衰減:引入摩擦係數 friction (0, 1),每幀 dx *= friction; dy *= friction; 模擬自然減速。
  2. 邊界檢測與反彈:預測下一幀位置 x+dx, y+dy 是否超出邊界,若超出則位置修正(鏡像回彈)並速度取反(dx = -dx)。
  3. 聲音參數映射(設計思路):
    • 音量/播放速度 ← 碰撞速度大小
    • 左右聲道平衡 ← 球體 X 座標相對窗口寬度

完整 Win32 SDK 實現


/** collision.cpp - 小球封閉區域碰撞模擬 **/
#include <windows.h>

float x = 100.0f, y = 100.0f;     // 球中心坐標
float speed = 10.0f;              // 初始速度響應值
float friction = 0.99f;           // 摩擦係數
float dx = 0.0f, dy = 0.0f;       // 速度分量

LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE, PSTR, int nShow) {
    WNDCLASS wc = {0};
    wc.lpszClassName = "GenericAppClass";
    wc.lpfnWndProc = MainWndProc;
    wc.style = CS_OWNDC | CS_VREDRAW | CS_HREDRAW;
    wc.hInstance = hInst;
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
    wc.lpszMenuName = "GenericAppMenu";
    RegisterClass(&wc);

    HWND hWnd = CreateWindow("GenericAppClass", "Happy Ball",
        WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX & ~WS_THICKFRAME,
        100, 100, 800, 600, NULL, NULL, hInst, NULL);
    ShowWindow(hWnd, nShow);

    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}

LRESULT CALLBACK MainWndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
    static PAINTSTRUCT ps;
    static HDC hDC;
    static HBRUSH hBrush;
    static RECT rect;
    const int R = 16;

    switch (msg) {
    case WM_CREATE:
        SetTimer(hwnd, 1, 5, NULL);          // 5ms 定時器 ~200FPS 物理步進
        hBrush = CreateSolidBrush(RGB(0,0,0));
        return 0;

    case WM_PAINT:
        hDC = BeginPaint(hwnd, &ps);
        SelectObject(hDC, hBrush);
        Ellipse(hDC, x-R, y-R, x+R, y+R);    // 繪製小球
        EndPaint(hwnd, &ps);
        break;

    case WM_KEYDOWN:
        switch (wp) {
        case VK_UP:    dy -= speed; break;
        case VK_DOWN:  dy += speed; break;
        case VK_LEFT:  dx -= speed; break;
        case VK_RIGHT: dx += speed; break;
        }
        break;

    case WM_TIMER: {                          // 物理步進
        dx *= friction; dy *= friction;
        x += dx; y += dy;
        GetClientRect(hwnd, &rect);

        // X 軸邊界
        if (x > rect.right - R)  { x = (rect.right - R) - (x - (rect.right - R)); dx = -dx; }
        if (x < R)               { x = R + R - x; dx = -dx; }
        // Y 軸邊界
        if (y > rect.bottom - R) { y = rect.bottom - R - (y - (rect.bottom - R)); dy = -dy; }
        if (y < R)               { y = R + R - y; dy = -dy; }

        InvalidateRect(hwnd, &rect, TRUE);    // 觸發重繪
        break;
    }

    case WM_DESTROY:
        KillTimer(hwnd, 1);
        DeleteObject(hBrush);
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hwnd, msg, wp, lp);
}

關鍵技術點解析

定時器驅動物理步進

SetTimer(hwnd, 1, 5, NULL) 每 5ms 觸發 WM_TIMER,在其中更新位置速度,而非在繪製消息中計算,實現渲染與邏輯解耦。

位置修正公式推導

右邊界超出 delta = x - (right - R),修正位置 x = (right - R) - delta,等價於鏡像反射,保證球體不穿牆且能量守恆(忽略摩擦)。

輸入響應

WM_KEYDOWN 直接修改速度分量,而非位置,配合摩擦力產生「滑行感」。注意:長按按鍵會疊加速度,Demo 中建議輕點鬆開。

HGE 版本差異

HGE 封裝了精靈、聲音、粒子系統,上述邏輯對應 hge->System_SetState(HGE_FRAMEFUNC, FrameFunc) 回調中執行,繪製用 hgeSprite->Render(x, y),聲音用 hge->Effect_PlayEx() 可直接設置音量、聲道、播放速率,無需手動計算聲道混合。

資源下載

完整源碼與可執行文件:https://up.2cto.com/2012/0213/20120213111636377.rar

總結

這個 Demo 雖簡單,卻包含了遊戲主循環、定時器驅動物理、邊界碰撞響應、鍵盤輸入處理、GDI 繪製等核心要素。理解這些基礎,是進階學習 HGE、Box2D、Unity 等引擎物理系統的紮實墊腳石。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved