程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C >> 關於C >> HGE引擎學習筆記1 : 如何模擬物理碰撞

HGE引擎學習筆記1 : 如何模擬物理碰撞

編輯:關於C

模擬物理碰撞要解決的幾個問題:
 
1.怎樣模擬速度的變化?
設置一個摩擦系數friction(0<friction<1.0)和響應用戶按鍵之後的一個X坐標單時間片增量dx,一個Y坐標單時間片增量dy,每隔一個時間片dx *= friction; dy *= friction;只要參數設置得當,看起來就會覺得速度自然地減慢.因為我們所用的浮點數的數據類型的精度限制,物體在經過一定數量時間片後就會停下來.
 
2.怎樣模擬碰撞?
每個時間片處理過程中,判斷物體的邊緣坐標加上dx與dy後有沒有超過屏幕邊緣,如果超過,則采取一定的策略重新設置物體坐標讓其在正常范圍內,如X軸超過,則對dx取反;如Y軸超過,則對dy取反.計算好坐標之後再進行繪圖.
 
3.碰撞過程中的聲音處理
這裡涉及到音量,左右聲道,播放速度.對音量和播放速度可以按照場景來設置,可以考慮根據X,Y坐標作為其中一個參數.左右聲道比較合理的處理方案是根據窗口寬度和物體X坐標來決定左右聲道的混合比例.
 
 
WINDOWS SDK窗口對此過程的模擬(僅摹仿了速度和碰撞等,對聲音的相關處理貌似比較復雜,還沒搞清楚怎麼寫.由於是做個簡單DEMO,並沒有加入多線程等技術,所以程序裡的坐標等數據的同步並不精准,上,下,左,右鍵最好是短暫地點一下即松開,連著按的話會出現速度的突兀變化):
[cpp]
/**
 * FILE : collision.cpp
 * 功能 : 模擬一個小球在一個封閉區域內的碰撞等活動
 * 作者 : mzlogin ( http://blog.csdn.net/mzlogin )
 * 聲明 : 版權沒有 盜版不究
 */ 
 
#include <windows.h> 
 
float x = 100.0f;    // 球的中心點X坐標 
float y = 100.0f;    // 球的中心點Y坐標 
float speed = 10.0f;    // 球響應按鈕後的初始速度 
float friction = 0.99f; // 球與地面的摩擦系數 
float dx = 0.0f;    // X軸增量 
float dy = 0.0f;    // Y軸增量 
 
LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM); 
 
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int nCmdShow) 

    WNDCLASS wc; 
    MSG msg; 
    HWND hWnd; 
 
    if( !hPrevInstance ) 
    { 
        wc.lpszClassName = "GenericAppClass"; 
        wc.lpfnWndProc = MainWndProc; 
        wc.style = CS_OWNDC | CS_VREDRAW | CS_HREDRAW; 
        wc.hInstance = hInstance; 
        wc.hIcon = LoadIcon( NULL, IDI_APPLICATION ); 
        wc.hCursor = LoadCursor( NULL, IDC_ARROW ); 
        wc.hbrBackground = (HBRUSH)( COLOR_WINDOW+1 ); 
        wc.lpszMenuName = "GenericAppMenu"; 
        wc.cbClsExtra = 0; 
        wc.cbWndExtra = 0; 
 
        RegisterClass( &wc ); 
    } 
 
    hWnd = CreateWindow( "GenericAppClass", 
            "Happy Ball", 
            WS_OVERLAPPEDWINDOW & (~WS_MAXIMIZEBOX) & (~WS_THICKFRAME), 
            100, 
            100, 
            800, 
            600, 
            NULL, 
            NULL, 
            hInstance, 
            NULL 
            ); 
 
    ShowWindow( hWnd, nCmdShow ); 
 
    while( GetMessage( &msg, NULL, 0, 0 ) ) { 
        TranslateMessage( &msg ); 
        DispatchMessage( &msg ); 
    } 
 
    return msg.wParam; 

 
LRESULT CALLBACK MainWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 

    static PAINTSTRUCT ps; 
    static HDC hDC; 
    static HBRUSH hBrush; 
    static RECT rect; 
    GetClientRect(hwnd, &rect); 
    const int nRadius = 16; 
 
    switch (message) 
    { 
        case WM_CREATE: 
            SetTimer(hwnd, 1, 5, NULL); 
            hBrush = CreateSolidBrush(RGB(0,0,0)); 
            return 0; 
 
        case WM_PAINT: 
            hDC = BeginPaint(hwnd, &ps); 
            SelectObject(hDC, hBrush); 
            Ellipse(hDC, x - nRadius, y - nRadius, x + nRadius, y + nRadius); 
            EndPaint(hwnd, &ps); 
            break; 
 
        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; 
 
        case WM_TIMER: 
            dx *= friction; 
            dy *= friction; 
            x += dx; 
            y += dy; 
            if (x > rect.right - nRadius) { x = (rect.right - nRadius) - (x - (rect.right - nRadius)); dx = -dx; } 
            if (x < nRadius) { x = nRadius + nRadius - x; dx = -dx; } 
            if (y > rect.bottom - nRadius) { y = rect.bottom - nRadius - (y - (rect.bottom - nRadius)); dy = -dy; } 
            if (y < nRadius) {y = nRadius + nRadius - y; dy = -dy; } 
            InvalidateRect(hwnd, &rect, TRUE); 
 
            break; 
 
        case WM_DESTROY: 
            KillTimer(hwnd, 1); 
            DeleteObject(hBrush); 
            PostQuitMessage(0); 
            return 0; 
    } 
    return DefWindowProc(hwnd, message, wParam, lParam); 

HGE示例源碼及Win32SDK源碼及可運行程序下載地址:http://up.2cto.com/2012/0213/20120213111636377.rar


摘自 活該你挨踢

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved