2009年10月30日 星期五

彈跳球



#undef  UNICODE
#undef _UNICODE
#pragma comment (lib, "msimg32.lib")
#define daviddr_2009_7_1

#include <windows.h>
#include <cmath>
#include <time.h>
#define ID_TIMER 1

const int cW = 640, cH = 480;           //記錄視窗真實邊界

int bW = cW - 2*GetSystemMetrics (SM_CXSIZEFRAME); 
int bH = cH - 2*GetSystemMetrics (SM_CYSIZEFRAME)-
                GetSystemMetrics (SM_CYCAPTION);                  
HDC hdcMem;

struct Ball
{
    COLORREF c;
    float x, y, vx, vy, r;

    float vlen() {
        return sqrt (vx*vx + vy*vy);
    }
    void draw() {
        SetDCBrushColor (hdcMem, c);
        Ellipse (hdcMem, x-r, y-r, x+r, y+r);
    }
    void move() {                    
        x += vx;  y += vy;
        if (x<=r)   x=r+1,  vx=-vx; 
        if (x>bW-r) x=bW-r, vx=-vx;
        if (y<=r)   y=r+1,  vy=-vy;  
        if (y>bH-r) y=bH-r, vy=-vy;            
    }
}; 

void collide_test (Ball& a, Ball& b)
{
    if (&a == &b) return;                   //不可能和自身碰撞
    float dot, 
          dx = b.x-a.x, 
          dy = b.y-a.y,
          r  = a.r + b.r, 
          d  = dx*dx + dy*dy;

    if (d < r*r && (d = sqrt (d)) &&         
        0 < (dx*a.vx + dy*a.vy)/(a.vlen()*d)){
        dx /= d; 
        dy /= d;      
        dot = b.vx*dx - a.vx*dx + b.vy*dy - a.vy*dy;
        dx *= dot; 
        dy *= dot;
        a.vx += dx; a.vy += dy;  
        b.vx -= dx; b.vy -= dy;        
    }
}


LRESULT CALLBACK WndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    static PAINTSTRUCT ps;
    static HBITMAP     hBmp;
    static HDC         hdc;
    static int i, j;
    static const int DELAY = 16;
    static const int nBall = 22;
    static Ball ball[nBall];
    static GRADIENT_RECT grect = {0,1};
    #define RC (rand()%256)<<8 
    static TRIVERTEX vtx[2] = {{0,0,RC,RC,RC,0},{bW,bH,RC,RC,RC,0}};
    
    switch (msg) 
    {
       case WM_CREATE:    
            hdc    = GetDC (hwnd);
            hdcMem = CreateCompatibleDC (hdc);
            hBmp   = CreateCompatibleBitmap (hdc, cW, cH);
            ReleaseDC (hwnd, hdc);
            SelectObject (hdcMem, hBmp);
            DeleteObject (hBmp);
            SelectObject (hdcMem, GetStockObject(DC_BRUSH));
            SetTimer (hwnd, ID_TIMER, DELAY, 0);
            for (i=0; i<nBall; ++i) {
                ball[i].c  = RGB(rand()%256,rand()%256,rand()%256);
                ball[i].x  = rand()%cW;
                ball[i].y  = rand()%cH;
                ball[i].r  = 10+rand()%36;
                ball[i].vx = float (4+rand()%8);
                ball[i].vy = float (4+rand()%8);                
            }
            return 0;
            
       case WM_DESTROY:
            KillTimer (hwnd, ID_TIMER);
            DeleteDC (hdcMem);
            PostQuitMessage (0);
            return 0; 
            
       case WM_PAINT:
            hdc = BeginPaint (hwnd, &ps);
            GradientFill (hdcMem, vtx, 2, &grect, 1, 1);
            for (i=0; i<nBall; ++i) ball[i].draw();
            BitBlt (hdc, 0,0, cW, cH, hdcMem, 0,0, SRCCOPY);
            EndPaint (hwnd, &ps);
            return 0; 
    
       case WM_TIMER:       
            for (i=0; i<nBall; ++i) {
                ball[i].move(); 
                for (j=0; j<nBall; ++j)
                    collide_test (ball[i], ball[j]);
            }
            InvalidateRect (hwnd, 0, false);
            return 0;
    }
    return DefWindowProc (hwnd, msg, wParam, lParam);    
}

int WINAPI WinMain (HINSTANCE hInst, HINSTANCE, PSTR, int nShow)
{
    srand ((UINT)time(0));            
    WNDCLASSEX wc = {0x30,3,WndProc,0,0,hInst,0,0,(HBRUSH)1,0,"T",0};
    if (!RegisterClassEx(&wc)) return 0; 
    HWND hwnd = CreateWindow ("T"," ",13565952,100,50,cW,cH,0,0,hInst,0);
    if (!hwnd) return 0;  
    MSG msg;  
    ShowWindow (hwnd, nShow);
    while (GetMessage (&msg, 0,0,0)) {
        TranslateMessage (&msg);
        DispatchMessage (&msg);
    }
    return msg.wParam;
}

沒有留言:

張貼留言