#include #include 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 &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 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; }