Odbijająca się kulka C++

Witam, zrobiłem taką odbijającą się piłeczkę od ścianek, ale nie wiem kompletnie dlaczego mi wywala mase błędów… oto kod:

#include "windows.h" //musimy zainkludowac glowna biblioteke windows

#include "stdio.h"

#include "stdlib.h"


//klasa kulki bedzie pierwsza klasa jaka wprowadzimy do gry


class AKulka

{

public:

	HBRUSH PedzelKulki;

	float x,y,r; // r promien

	float Wektor[2]; // [x,y]

	float Predkosc;

	AKulka(){ // konstruktor klasy zaklada ze kulka rozpoczyna swa gre od srodka (pole gry to 500x500 punktow)

		x=250;

		y=250;

		r=15;

		Predkosc = 12.5f;

		Wektor[0]=0.26f;	//poczatkowy kierunek kulki (zaczyna lecac do gory)

		Wektor[1]=0.23f;

	}

}

	void RysujKulke(HDC hdc)	//funkcja rysujaca korzysta z koloru kulki

	{

		SelectObject(hdc,PedzelKulki);

		Ellipse(hdc,int(x-r),int(y+r),int(x+r),int(y-r));	//funkcja ellipse rysuje elipsy 

	}

	void PrzesunKulke()

	{

		x+=Wektor[0]*Predkosc; //przesuwamy kulke o predkosc w kierunku Wektora

		y+=Wektor[1]*Predkosc;

	}

	void Kolizja()

	{

		if (x+Wektor[0]*Predkosc+r > 500)	//Tutuj sprawdzamy kolizje ze sciankami bocznymi

			Wektor[0]*=-1;

		if (y+Wektor[1]*Predkosc+r > 500)

			Wektor[1]*=-1;

		if (x+Wektor[0]*Predkosc-r < 0)

			Wektor[0]*=-1;

		if (y+Wektor[1]*Predkosc-r < 0)

			Wektor[1]*=-1;

	}

}

;



AKulka kulka; //globalna deklaracja kulki


LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam); //Deklaracja funkcji obslugujacej 


int APIENTRY WinMain(HINSTANCE hInstance, //Windowsowy odpowiednik funkcji int main()

                     HINSTANCE hPrevInstance,	//hInstance jest jednoznacznym identyfikatorem programu nadawanym podczas uruchamiania

                     PSTR szCmdLine, //hPrevInstance nie jest uzywany w dzisiejszych Windowsach

                     int iCmdShow) //szCmdLine jest stringiem zawierajacym komendy linii polecen Windowsa (Menu Start:: Uruchom)

												//iCmdShow podaje domyslny (ustawiany w Windowsie) stan otwierania programu (maksymalizacja okna, minimalizacja, normalne)

{


	MSG msg; //deklaracja komunikatu Windowsa

	WNDCLASS	wndclass; //deklaracja klasy okna

	HWND hwnd; //deklaracja uchwytu okna, sluzacego do jednoznacznej identyfikacji okna




	wndclass.style = CS_HREDRAW|CS_VREDRAW; //style okna CS_HREDRAW - oznacza ze okno bedzie odrysowane kiedy zmieni sie jego szerokosc, CS_VREDRAW- wysokosc

	wndclass.lpfnWndProc = WndProc; //wskaznik na funkcje odpowiedzialna za przyjmowanie i obsluge komunikatow

	wndclass.cbClsExtra = 0; //mozliwosc zadeklarowania dodatkowych bajtow pomagajacych w obsludze okna 

	wndclass.cbWndExtra = 0; //mozliwosc zadeklarowania dodatkowych bajtow pomagajacych w obsludze okna 

	wndclass.hInstance = hInstance; //klasa okna potrzebuje Identyfikatora programu, ktory pobieramy z deklaracji WinMain

	wndclass.hIcon = LoadIcon(NULL,IDI_APPLICATION); //Ikona ktora bedzie pokazywana w gornym pasku okna i w dolnym pasku programow otwartych. Jesli NULL to bez Ikony. Odznacz komentarz aby wczytac domyslna ikone. 

	wndclass.hCursor = LoadCursor(NULL,IDC_ARROW); //Kursor ktory bedzie widoczny na oknach utworzonych przy pomocy tej klasy okna. Jesli NULL to klepsydra.

	wndclass.hbrBackground = CreateSolidBrush(0xCCCCCC);//(HBRUSH)GetStockObject(LTGRAY_BRUSH);	//Tlo naszego okna. Obecnie wczytywany bedzie czarny pedzel. Okno nie musi posiadac tla(NULL);

	wndclass.lpszMenuName = NULL; //Nazwa Menu Okna // na razie nie uzywane

	wndclass.lpszClassName = "Program1"; //Nazwa klasy okna 


	RegisterClass(&wndclass); //Rejestrujemy klase okna, od tej pory mozemy uzywac jej nazwy ("Program1") w wywolaniu CreateWindow


	hwnd = CreateWindow( //Funkcja CreateWindow 

		"Program1", //nazwa klasy okna na podstawie ktorej budujemy nasze okno 

		"Witam", //nazwa ktora pojawi sie w gornym pasku tytulowym

		WS_POPUP|WS_VISIBLE, //WS_POPUP JEST STYLEM KTORY UDOSTEPNIA OKNO BEZ RAMKI I PRZYCISKOW JEZELI ROZSZERZYMY OKNO NA CALY EKRAN OTRZYMAMY TZW FULLSCREEN 

		0, //pozycja poczatkowa x (w gorym lewym rogu jest (0,0)

		0, //pozycja poczatkowa y

		GetSystemMetrics(SM_CXSCREEN), //szerokosc okna (GetSystemMetrics jest funkcja zwracajaca rozne parametry ustawien systemowych argument SM_CXSCREEN odpowiada za szerokosc pulpitu)

		GetSystemMetrics(SM_CXSCREEN), //wysokosc okna (GetSystemMetrics jest funkcja zwracajaca rozne parametry ustawien systemowych argument SM_CYSCREEN odpowiada za wysokosc pulpitu)

		NULL, //okno nadrzedne do tworzonego (poniewaz jest to pierwsze okno wiec wpisujemy NULL

		NULL, //uchwyt menu okna (poniewaz nie ma menu wiec dajemy NULL)

		hInstance, //identyfikator programu pobierany z WinMain

		NULL); //dodatkowe parametry tworzenia 	


	ShowWindow(hwnd,SW_NORMAL); //Mozemy wreszcie pokazac okno ktore wlasnie utworzylismy. Drugi Parametr funkcji sluzy do wybrania stanu w jakim okno sie pojawi np SW_MAXIMIZE -maksymalizuje je (SW_NORMAL - okno wyswietlane wedlug podanej przez nas serokosci/wysokosci)

	UpdateWindow(hwnd); //i odmalowac je, gdyz dopiero co powstale okno ma tlo "zebrane" bezposrednio z ekranu (mozna to zaobserwowac komentujac te linijke)



	// Tworzenie wszystkich kontrolek


	HWND t=CreateWindow("button","Puszczaj",WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,600,20,90,30,hwnd,(HMENU)przycisk_puszczaj,hInstance,NULL);

	t=CreateWindow("button","Stop",WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,700,20,90,30,hwnd,(HMENU)przycisk_stop,hInstance,NULL);

	t=CreateWindow("button","OK",WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,750,60,40,30,hwnd,(HMENU)przycisk_ok_promien,hInstance,NULL);

	t=CreateWindow("static"," promien",WS_BORDER|WS_CHILD|WS_VISIBLE,600,64,70,22,hwnd,(HMENU)static_promien,hInstance,NULL);

	t=CreateWindow("button","OK",WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,750,100,40,30,hwnd,(HMENU)przycisk_ok_predkosc,hInstance,NULL);

	t=CreateWindow("static"," predkosc",WS_BORDER|WS_CHILD|WS_VISIBLE,600,104,70,22,hwnd,(HMENU)static_predkosc,hInstance,NULL);


	//Kontrolki wymagajace wartosci poczatkowej


	char string[128]; //Inicjujemy poczatkowe wartosci w editach

	sprintf(string,"%.0f",kulka.r);

	t=CreateWindow("edit",string,WS_CHILD|WS_VISIBLE|ES_RIGHT|BS_PUSHBUTTON|WS_BORDER,680,64,60,22,hwnd,(HMENU)edit_promien,hInstance,NULL);

	sprintf(string,"%g",kulka.Predkosc);

	t=CreateWindow("edit",string,WS_CHILD|WS_VISIBLE|ES_RIGHT|BS_PUSHBUTTON|WS_BORDER,680,104,60,22,hwnd,(HMENU)edit_predkosc,hInstance,NULL);





	while(GetMessage(&msg,NULL,0,0))

	{

		TranslateMessage(&msg); //Komunikaty klawiatury tzw klawiszy wirtualnych (bede o nich szerzej mowil na zajeciach zwiazanych z obsluga klawiatury (ale sa to np klawisze F1..F12, ENTER ALT itp) musza zostac przetlumaczone na standard klawiszy Windowsa za pomoca funkcji TranslateMessage

		DispatchMessage(&msg); //Funkcja DispatchMessage wysyla komunikat do odpowiedniego okna

	}

	return msg.wParam; //w przypadku zakonczenia programu zwracany jest ten parametr (jest on wysylany z funkcja PostQuitMessage(0) gdzie zero jest wlasnie tym parametrem - opis funkcji nizej)

}



//Przed nami mozg programu Win32 czyli funkcja przetwarzajaca komunikaty

//jej parametrami sa

//hwnd	pozwala nam ustalic z ktorego okna nadszedl komunikat

//message	jest to nazwa komunikatu (np WM_SIZE (czyli Windows Message Size) odpowiada za zmiane szerokosci/wysokosci okna)

//wParam jest pierwszym z dwoch parametrow komunikatu - mozna powiedziec ze niesie tresc komunikatu czyli np. nowa wysokosc/serokosc

//lParam drugi parametr pomocniczy (gdyby pierwszy nie starczyl)


LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)

{

	//wszystkie komunikaty sa rozpatrywane za pomoca switcha


	static HBRUSH Pedzel_Czerwony;	//HBRUSH to uchwyt na pedzel ktorym bedziemy malowac wnetrza figur (slowo static oznacza ze bedzie zadeklarowane tylko po pierwszym wejsciu do funkcji WndProc i nie bedzie sie wyzerowywac

	static HBRUSH Pedzel_Zielony;

	static HBRUSH Pedzel_Niebieski;

	static HBRUSH Pedzel_Zolty;

	static HBRUSH Pedzel_Fioletowy;

	static HPEN	Pioro_Biale; //HPEN to uchwyt na pioro, ktorym bedziemy malowac obramowania figur oraz linie i punkty


	switch (message)

	{

	case WM_CREATE: //komunikat wysylany podczas wywolania funkcji CreateWindow mozna w tym miejscu inicjowac zmienne

		{


			SetTimer(hwnd,1,10,NULL);	//Inicjujemy zegar (Timer) aby zglaszal odrysowywanie pola gry co 10 milisekund (uzyskamy w ten sposob efekt animacji)

										//pierwszy parametr to okno dla ktorego zegarek chcemy ustawic, drugi to identyfikator zegarka (moze byc kilka zegarkow)

										//trzeci parametr to czas po jakim zegarek ma sie zglaszac, ostatni zas to wskaznik na funkcje TimerProc ktora obsluguje zegarki (my korzystamy z komunikatu WM_TIMER) wiec wstawiamy tu NULL


			Pedzel_Czerwony=CreateSolidBrush(0x0000FF);	//WM_CREATE to dobre miejsce by zainicjalizowac nasze pedzle odpowiednimi kolorami. Sluzy do tego funkcja CreateSolidBrush ktora jako argument pobiera wartosc koloru w jednostkach hexadecymalnych (tak jak w HTML'u) zasadnicza roznica jest jednak taka ze nie mamy skladowych koloru ustawionych w szyku RGB tylko BGR

			Pedzel_Zielony=CreateSolidBrush(0x00FF00);

			Pedzel_Niebieski=CreateSolidBrush(0xFF0000);

			Pedzel_Zolty=CreateSolidBrush(0x00FFFF);

			Pedzel_Fioletowy=CreateSolidBrush(0xFF00FF);

			Pioro_Biale=CreatePen(PS_SOLID,2,0xFFFFFF);	//Inicjalizujemy Pioro za pomoca funkcji CreatePen pierwszym argumentem jest styl piora (moze byc ciagle, kreskowane, kropkowane itp..), drugim jest grubosc piora (uwaga, tylko ciagle (PS_SOLID) moga miec grubosc wieksza niz 1), trzecim zas wytlumaczony wyzej kolor

			kulka.PedzelKulki=Pedzel_Zielony; //Ustawiamy kolor Kulki

		}

		return 0; //po kazdym case WM_ dajemy return jezeli chcemy aby Windows nie przetwarzal po nas dalej tego komunikatu oraz dajemy break, aby to robil

	case WM_KEYDOWN: //obsluga komunikatu nacisniecia klawisza klawiatury 

		switch(wParam) //robimy drugiego switcha od wParam w ktorym niesiona jest wiadomosc - "ktory przycisk zostal nacisniety"

		{

		case VK_ESCAPE: //obslugujemy klawisz Esc (jest to klawisz virtualny (stad przedrostek VK) klawisze virtualne to np. F1..F12 Enter, Insert, PageDown itp.)

			PostQuitMessage(0);	//kiedy nacisniemy Esc zostanie wyslana wiadomosc o zamknieciu programu z komunikatem powrotu rownym 0 (odpowiada to return 0 w typowym programie z funkcja main()

			return 0;		

		}

		return 0;

	case WM_COMMAND:			

		switch(LOWORD(wParam))

		{

		case przycisk_puszczaj:

			SetFocus(hwnd);	


			return 0;

		case przycisk_stop:	

			SetFocus(hwnd);	


			return 0;

		case przycisk_ok_promien:

			{

				char string[8];

				SetFocus(hwnd);

				GetWindowText(GetDlgItem(hwnd,edit_promien),string,7); //Nie funkcja GetWindowText jest warta opisu (gdyz robi ona dokladnie to na co wskazuje nazwa (pierwszy parametr to - z ktorego okna, drugi to tablica charakterow(string) , trzeci to ilosc liter ktore ma zostac pobrana (nie zapominajmy o zerze)).. Wiekszy opis poswiece funkcji GetDlgItem ktora zwraca hwnd przycisku.

																			//GetDlgItem jest funkcja skierowana raczej do obslugi Dialogow (okien z kontrolkami) niz do samych okien, jednak mozemy potraktowac nasze okno jako Dialog. Pierwszym argumentem jest - na ktorym oknie znajduje sie (kontrolka,przycisk lub okno potomne), ktorego hwnd potrzebujemy, drugim argumentem zas Identyfikator tej kontrolki, okna potomnego..)

																			//To wystarcza funkcji GetDlgItem aby jednoznacznie okreslic o kogo nam chodzi

				kulka.r=float(atoi(string)); //ustawiamy promien kulki

			}

			return 0;

		case przycisk_ok_predkosc:

			{

				char string[8];

				SetFocus(hwnd);

				GetWindowText(GetDlgItem(hwnd,edit_predkosc),string,7);		



				kulka.Predkosc=float(atof(string)); //ustawiamy pedkosc kulki

			}

			return 0;

		}

		return 0;

	case WM_PAINT: //obsluga komunikatu rysowania po oknie

		{					

			HDC hdc; //HDC jest uchwytem na kontekst urzadzenia. 

							//czcionki, tlo, a nawet jaka jest czcionka. Nie bedziemy mogli nic narysowac jezeli nie bedziemy wiedzieli w jakim stylu to robic to robic. HDC mowi nam jaki mamy dostepny styl.

			PAINTSTRUCT	ps; //PAINTSTRUCT jest informacja dotyczaca OBSZARU po jakim bedziemy malowac 

							//Po narysowaniu kwadratu musimy powiadomic Windows ze poprzedni obraz ktory wyswietlal (bez kwadratu) jest juz niewazny. Zjawisko to nazywamy uniewaznianiem (Invalidate) po odswiezeniu ekranu z juz narysowanym kwadratem musimy z powrotem zatwierdzic 

							//narysowany obraz. Zjawisko to nazywamy zatwierdzaniem (Validate). 



			hdc = BeginPaint(hwnd,&ps); //Funkcja BeginPaint odpowiada za przygotowanie nam kontekstu poprzez powiadomienie jej po ktorym oknie mamy malowac, dodatkowo wypelni nam PAINTSTRUCT informujac nas ktory skrawek ekranu


			kulka.RysujKulke(hdc);



			MoveToEx(hdc,0,500,NULL); //Linie otaczajace pole gry

			LineTo(hdc,500,500);

			LineTo(hdc,500,0);


			EndPaint(hwnd,&ps); //EndPaint konczy rysowanie poprzez zatwierdzenie CALEGO EKRANU rysowania (jest to ulatwienie - gdyz nie zatwierdzamy malych skrawkow ktore (po zatwierdzeniu wszystkich po kolei dadza nam i tak cala przestrzen rysujaca)

		}

		return 0;

	case WM_TIMER:	//komunikat WM_TIMER jest zglaszany przez ustawiony wczesniej przez nas zegarek

		{

			kulka.Kolizja(); //sprawdzamy kolizje

			kulka.PrzesunKulke();	//przesuwamy odpowiednio kulke

			RECT rect; //RECT to struktura - prostokat uzyjemy go by okreslic obszar pola gry do odrysowania

			rect.top=0;

			rect.right=500;

			rect.left=0;

			rect.bottom=500;



			InvalidateRect(hwnd,&rect,true);	//Tym razem InvalidateRect pobiera wskaznik na rect (aby odmalowac tylko ten obszar) oraz odmalowywuje tlo (ostatni parametr true)

		}

		return 0;

	case WM_DESTROY: //komunikat wywolywany przy nacisnieciu iksa na pasku tytulowym, a takze np. przez funkcje DestroyWindow(HWND) -sluzaca do zamykania okna "z zewnatrz"

		PostQuitMessage(0);	//dopisana przeze mnie funkcja PostQuitMessage - wysyla do petli komunikatow wiadomosc przerywajaca ja . 

		return 0;

	}

	return DefWindowProc(hwnd,message,wParam,lParam); 

}


z góry bardzo dziękuje za pomoc
  1. Po konstruktorze klasy AKulka masz zbędny zamykający nawias klamrowy.

  2. Brakuje definicji stałych:

  • [*:2nswf72k]przycisk_puszczaj