欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

HGE引擎学习笔记1 : 如何模拟物理碰撞

程序员文章站 2022-06-01 19:57:37
模拟物理碰撞要解决的几个问题:   1.怎样模拟速度的变化? 设置一个摩擦系数friction(0

模拟物理碰撞要解决的几个问题:
 
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 ( )
 * 声明 : 版权没有 盗版不究
 */ 
 
#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源码及可运行程序下载地址:


摘自 活该你挨踢