#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
0 B
|👍
/👎
0 B
|👍
/👎
0 B
|👍
/👎