Hyluss icon

Szalona piłka

Hyluss | PRO | 01/03/17 09:03:54 PM UTC | 0 ⭐ | 10390 👁️ | Never ⏰ | []
C++ (WinAPI) |

0 B

|

None

|

0 👍

/

0 👎

#include <windows.h>
#include <vector>
TCHAR AppName[] = TEXT("Szalona piłka");
 
// funkcja rozszerzająca zwykłą rand o losowanie z przedziału ujemnych
int random(int min, int max)
{
    int Random;
    // losujemy w pętli, jeśli losuje 0, bo piłka utknie w miejscu wtedy
    while  ((Random = min + (rand() / (RAND_MAX / (max - min) ) ) ) == 0);
    return Random;
}
class ball
{
private:
    int _x; // współrzędna X lewego górnego punktu (początek rysowania
    int _y; // współrzędna Y lewego górnego punktu (początek rysowania
    int _size;  // średnica piłki, dodając ją do X i Y otrzymujemy drugi punkt
    int _przesuniecieX; // jednostkowe przesunięcię piłki po osi X
    int _przesuniecieY; // jednostkowe przesunięcię piłki po osi Y
    COLORREF _kolor;    // kolor piłki
public:
    ball() {};
    //Settery
    void Set_x(const int x) {
        _x = x;
    };
    void Set_y(const int y) {
        _y = y;
    };
    void Set_size(const int size) {
        _size = size;
    };
    void Set_przesuniecieX(const int przesuniecieX) {
        _przesuniecieX = przesuniecieX;
    };
    void Set_przesuniecieY(const int przesuniecieY) {
        _przesuniecieY = przesuniecieY;
    };
    void Set_kolor(COLORREF kolor)
    {
        _kolor = kolor;
    }
    //Gettery
    const int Get_x() {
        return _x;
    };
    const int Get_y() const {
        return _y;
    };
    const int Get_size() const {
        return _size;
    };
    const int Get_przesuniecieX() const {
        return _przesuniecieX;
    };
    const int Get_przesuniecieY() const {
        return _przesuniecieY;
    };
    const COLORREF Get_kolor() const {
        return _kolor;
    };
 
    BOOLEAN TouchTop(const RECT &r) {
        if (_y <= r.top)
        {
            _y = r.top;
            return TRUE;
        }
        else return FALSE;
    };
    BOOLEAN TouchBottom(const RECT &r) {
        if ((_y + _size) >= r.bottom)
        {
            _y = r.bottom - _size;
            return TRUE;
        }
        else return FALSE;
    };
    BOOLEAN TouchLeft(const RECT &r) {
        if (_x <= r.left)
        {
            _x = r.left;
            return TRUE;
        }
        else return FALSE;
    };
    BOOLEAN TouchRight(const RECT &r) {
        if ((_x + _size) >= r.right)
        {
            _x = r.right - _size;
            return TRUE;
        }
        else return FALSE;
    };
    // sprawdza czy pilka znajduje sie w obszarze klienckim
    //oraz czy koliduje z sciankami;
    void odbicia(const RECT &ClientRect)
    {
        _x += _przesuniecieX;
        _y += _przesuniecieY;
 
        if (TouchBottom(ClientRect) == TRUE) {
            _przesuniecieX = random(-10, 10);
            _przesuniecieY = random(-10, -1);
        }
        if (TouchRight(ClientRect) == TRUE) {
            _przesuniecieX = random(-1, -10);
            _przesuniecieY = random(-10, 10);
        }
        if (TouchLeft(ClientRect) == TRUE) {
            _przesuniecieX = random(1, 10);
            _przesuniecieY = random(-10, 10);
        }
        if (TouchTop(ClientRect) == TRUE) {
            _przesuniecieX = random(-10, 10);
            _przesuniecieY = random(1, 10);
        }
    };
};
// dodaje pilki do wektora
void Pilki_dodaj(std::vector<ball> &pilka, const int numer, const RECT &ClientRect)
{
    int i = pilka.size();
    const int end = i + numer;
    for (i; i < end; i++)
    {
        pilka.push_back(ball());
        pilka[i].Set_x(random(20, ClientRect.right - 100));
        pilka[i].Set_y(random(20, ClientRect.bottom - 100));
        pilka[i].Set_size(random(20, 100));
        pilka[i].Set_przesuniecieX(random(-5, 5));
        pilka[i].Set_przesuniecieY(random(-5, 5));
        pilka[i].Set_kolor(RGB(rand() % 255, rand() % 255, rand() % 255) );
    }
}
// sprawdzanie czy kliknięto w piłkę
BOOLEAN klikniecie(ball &pilka, const int x, const int y, const HDC &hdc) {
    if (GetPixel(hdc, x, y) == pilka.Get_kolor())
    {
        if (x >= pilka.Get_x() && x <= (pilka.Get_x() + pilka.Get_size()) && y >= pilka.Get_y() && y <= (pilka.Get_y() + pilka.Get_size()))
        {
            return TRUE;
        }
    }
    else return FALSE;
};
 
LRESULT CALLBACK WindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    static HDC hdc = GetDC(hwnd);
    static int IdTimer = 1;
    static RECT ClientRect;
    GetClientRect(hwnd, &ClientRect);
    static std::vector <ball> pilki;// tablica pilek
    static HBRUSH brush = (HBRUSH)GetStockObject(DC_BRUSH); // brush stockowy
    switch (message)
    {
        case WM_CREATE:
        {
            Pilki_dodaj(pilki, 1, ClientRect);// dodanie 'n' piłek
            SetWindowTextA(hwnd, "LPM - Dodanie kola \t\t PPM - Usuniecie kola");
            SetTimer(hwnd, IdTimer, 10, NULL); // timer co 10 ms
        }break;
        case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdcBuffor;  // buffor, w którym rysujemy piłki, a potem gotowy rysunek przenosimy do oryginalnego HDC
            HBITMAP bitmapBuffor; // to jest jakby "płótno" HDC po którym się rysuje
            HANDLE bitmapOld;       // uchwyt do poprzedniej bitmapy w hdcBuffor, trzeba o nim pamietać bo należy go zwolnić
            BeginPaint(hwnd, &ps);
            // tworzymy kompatybilny kontekst urządzenia
            hdcBuffor = CreateCompatibleDC(ps.hdc); // tworzymy kompatybilny kontekst HDC do oryginału
            bitmapBuffor = CreateCompatibleBitmap(ps.hdc, ClientRect.right, ClientRect.bottom); // kompatybilną bitmapę o takich smaych wymiarach
            bitmapOld = SelectObject(hdcBuffor, bitmapBuffor);  // nanosimy kompatybilną bitmapę na kompatybilne HDC, a starą bitmapę przypisujemy do uchwytu
            FillRect(hdcBuffor, &ClientRect, (HBRUSH)GetStockObject(WHITE_BRUSH));
 
            for (int i = 0; i < pilki.size(); i++)
            {
                SetDCBrushColor(hdcBuffor, pilki[i].Get_kolor());
                SelectObject(hdcBuffor, brush);
                Ellipse(hdcBuffor, pilki[i].Get_x(), pilki[i].Get_y(), pilki[i].Get_x() + pilki[i].Get_size(), pilki[i].Get_y() + pilki[i].Get_size());
            }
            // przekopiowujemy gotowy obraz z naniesionymi wszystkimi piłkami z kompatybilnego HDC do oryginalnego, bo wtedy dopiero się pojawi na ekranie
            BitBlt(ps.hdc, ClientRect.left, ClientRect.top, ClientRect.right, ClientRect.bottom, hdcBuffor, 0, 0, SRCCOPY);
            //przypisujemy starą bitmapę na powrót to kompatybilnego HDC, żeby potem ją zwolnić razem z tym HDC
            SelectObject(hdcBuffor, bitmapOld);
            DeleteObject(bitmapBuffor);
            DeleteDC(hdcBuffor);
 
            EndPaint(hwnd, &ps);
        }break;
        case WM_RBUTTONDOWN:
        {
            int x = LOWORD(lParam);
            int y = HIWORD(lParam);
            for (int i = 0; i < pilki.size();i++)
            {
                if (klikniecie(pilki[i], x, y, hdc) == TRUE)
                {
                    pilki.erase(pilki.begin() + i);
                    break;
                }
            }
        }break;
        case WM_LBUTTONDOWN:
        {
            Pilki_dodaj(pilki, 1, ClientRect);
        }break;
        case WM_TIMER:
        {
            switch (wParam)
            {
                case 1:
                {
                    for (int i = 0; i < pilki.size(); i++)
                    {
                        pilki[i].odbicia(ClientRect); // co 10 ms zmienia polozenie pilki
                    }
                    InvalidateRect(hwnd, NULL, FALSE);
                }break;
            }
        }break;
        case WM_CLOSE:
            KillTimer(hwnd, IdTimer);
            pilki.clear();
            ReleaseDC(hwnd, hdc);
            DestroyWindow(hwnd);
            break;
 
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
 
        default:
            return (DefWindowProc(hwnd, message, wParam, lParam));
    }
    return (0);
}
 
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    MSG msg;
    WNDCLASS wndclass;
 
    wndclass.style = CS_HREDRAW | CS_VREDRAW;
    wndclass.lpfnWndProc = WindowProc;
    wndclass.cbClsExtra = 0;
    wndclass.cbWndExtra = 0;
    wndclass.hInstance = hInstance;
    wndclass.hIcon = NULL;
    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wndclass.lpszMenuName = NULL;
    wndclass.lpszClassName = AppName;
 
    if (RegisterClass(&wndclass) == 0)
        return FALSE;
 
    HWND hwnd = CreateWindow(AppName, AppName, WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, NULL, NULL, hInstance, NULL);
 
    if (hwnd == NULL)
        return FALSE;
 
    while (GetMessage(&msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return (int)msg.wParam;
}

Comments

  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎