float x = 100.0f, y = 100.0f; // 球心座標
float dx = 0.0f, dy = 0.0f; // 速度向量 (像素/幀)
float speed = 10.0f; // 按鍵施加的初始速度增量
float friction = 0.99f; // 摩擦係數 (0
void UpdatePhysics(RECT clientRect) {
// 1. 摩擦衰減
dx *= friction;
dy *= friction;
// 2. 位置積分
x += dx;
y += dy;
// 3. 邊界檢測與反彈 (座標修正 + 速度取反)
// 右邊界
if (x > clientRect.right - radius) {
x = (clientRect.right - radius) - (x - (clientRect.right - radius));
dx = -dx;
}
// 左邊界
if (x < radius) {
x = radius + radius - x;
dx = -dx;
}
// 底邊界
if (y > clientRect.bottom - radius) {
y = (clientRect.bottom - radius) - (y - (clientRect.bottom - radius));
dy = -dy;
}
// 頂邊界
if (y < radius) {
y = radius + radius - y;
dy = -dy;
}
}
case WM_KEYDOWN:
switch (wParam) {
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;
#include <windows.h>
float x=100, y=100, dx=0, dy=0, speed=10, friction=0.99f;
const int R=16;
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) {
static HBRUSH hBrush; RECT rc;
switch(msg) {
case WM_CREATE:
SetTimer(hWnd, 1, 5, NULL); // 5ms ≈ 200FPS 物理更新
hBrush = CreateSolidBrush(RGB(0,0,0));
return 0;
case WM_TIMER:
GetClientRect(hWnd, &rc);
UpdatePhysics(rc); // 上述邏輯
InvalidateRect(hWnd, &rc, TRUE);
return 0;
case WM_KEYDOWN:
// 上述鍵盤邏輯
return 0;
case WM_PAINT: {
PAINTSTRUCT ps; HDC hdc = BeginPaint(hWnd, &ps);
SelectObject(hdc, hBrush);
Ellipse(hdc, x-R, y-R, x+R, y+R); // 畫圓
EndPaint(hWnd, &ps);
return 0;
}
case WM_DESTROY:
KillTimer(hWnd, 1); DeleteObject(hBrush); PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, msg, wp, lp);
}
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int nShow) {
WNDCLASS wc = {CS_HREDRAW|CS_VREDRAW, WndProc, 0,0, hInst,
LoadIcon(NULL,IDI_APPLICATION), LoadCursor(NULL,IDC_ARROW),
(HBRUSH)(COLOR_WINDOW+1), NULL, L"PhysDemo"};
RegisterClass(&wc);
HWND hWnd = CreateWindow(L"PhysDemo", L"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 0;
}
hge->Timer_GetDelta() 取得幀時間差 dt,物理更新改為 x += dx * dt; dx *= pow(friction, dt * 1000); 實現**幀率無關**物理。hge->Gfx_RenderLine 或精靈 hgeSprite。hge->Effect_PlayEx(snd, volume, pan, pitch):pan = (x - centerX) / (width/2) 計算左右聲道(-1~1)。完整 HGE Demo + Win32 SDK 版 + 可執行檔:
https://www.BkJia.com/uploadfile/2012/0213/20120213111636377.rar
掌握「位置積分 → 邊界修正 → 速度反轉」這一核心循環,即可在任何 2D 引擎或裸 API 上快速構建物理交互原型。