Visual C++ ile Görsel Programlama 3 (Win32)
Visual C++ ile , Kontroller ve Şekiller ve çizim
Visual C++ ile Görsel Programlama 3 ( Kontroller ve Şekiller)
önceki derslerde pencere yapmayı ve mesaj almayı öğrendik. Bu kısımda ise iki boyutlu oyunlar için gerekli olan temel bilgileri öğreneceğiz. öncelikle tüm oyunlarda gerekli olan kontrollere bakalım
Klavyeden ve Fare ile Oyun Kontrolu
Klavyeden giriş yapılırken case WM_KEYDOWN isimli mesaj alınarak değerlendirme yapılır. Aşağıdaki Kod ile sadece Enter tuşu ile işlem yapılırken görünüyor. Diğer tüm mesajlarda olduğu gibi bu da LRESULT CALLBACK kısmında alınacaktır.
break; |
Bu kısımda switch (wParam) isimli bölüme dikkatinizi çekeyim.LRESULT CALLBACK fonksiyonuna bakarsak parantez içinde fonksiyona gelen mesajdan başka parametreler olduğunu görüyoruz ( alttaki wParam ve lParam). Bu parametreler her mesaj için farklı değerler almaktadır.
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
bunu bir örnekle daha iyi anlatabilirim. diyelim ki LRESULT CALLBACK fonksiyonuna WM_KEYDOWN( TuşBasıldı ) mesajı geliyor, bu durumda wParam isimli değişken hangi tuşun basıldığını belirtir. bunların sayı olarak listesini aaşğıya yazdım. lParam değişkeni ise tuşun tekrarlama sayısı veya Alt Ctrl tuşarı ile birlikte basılı olup olmadığını belirtir.
Klavye ve Fare tuşları için hexadecimal sayıları WM_KEYDOWN >> wParam için | ||
Sembolik ismi | Değeri | Açıklaması |
VK_LBUTTON | 01 | Fare sol tuşu |
VK_RBUTTON | 02 | Fare Sağ tuşu |
VK_RETURN | 0D | Enter Tuşu |
VK_SPACE | 20 | Boşluk Tuşu |
VK_LEFT | 25 | Sol Ok Tuşu |
VK_UP | 26 | yukarı Ok Tuşu |
VK_RIGHT | 27 | Sağ ok Tuşu |
VK_DOWN | 28 | Aşağı ok Tuşu |
Sayılar | ||
VK_0 | 30 | 0 tuşu |
VK_1 | 31 | 1 tuşu |
VK_2 | 32 | 2 tuşu |
VK_3 | 33 | 3 tuşu |
VK_4 | 34 | 4 tuşu |
VK_5 | 35 | 5 tuşu |
VK_6 | 36 | 6 tuşu |
VK_7 | 37 | 7 tuşu |
VK_8 | 38 | 8 tuşu |
VK_9 | 39 | 9 tuşu |
Harfler | ||
VK_A | 41 | A harfi |
VK_B | 42 | B harfi |
VK_C | 43 | C harfi |
VK_D | 44 | D harfi |
VK_E | 45 | E harfi |
VK_F | 46 | F harfi |
VK_G | 47 | G harfi |
VK_H | 48 | H harfi |
VK_I | 49 | I harfi |
VK_J | 4A | J harfi |
VK_K | 4B | K harfi |
VK_L | 4C | L harfi |
VK_M | 4D | M harfi |
VK_N | 4E | N harfi |
VK_O | 4F | O harfi |
VK_P | 50 | P harfi |
VK_Q | 51 | Q harfi |
VK_R | 52 | R harfi |
VK_S | 53 | S harfi |
VK_T | 54 | T harfi |
VK_U | 55 | U harfi |
VK_V | 56 | V harfi |
VK_W | 57 | W harfi |
VK_X | 58 | X harfi |
VK_Y | 59 | Y harfi |
VK_Z | 5A | Z harfi |
Gelen mesajın fare ile ilgili olduğunu varsayalım WM_MOUSEMOVE (Fare Haraket Etti ) bu durumda wParam isimli değişken fare haraket ederken basılı olan tuş varsa onu belirtir. wParam = MK_LBUTTON ise sol tuş basılıdır. ( yukardaki listedeki gibi VK_LBUTTON da olabilir çünkü bunlar sayılara karşılık gelen hazır değişkenlerdir.)
WM_MOUSEMOVE >> wParam |
MK_CONTROL CTRL basılı MK_LBUTTON Sol tuş basılı MK_MBUTTON Orta tuş basılı MK_RBUTTON Sağ tuş basılı MK_SHIFT üst Ok tuşu basılı |
WM_MOUSEMOVE için lParam ise farenin konumunu belirtir. Ana pencerenin sol tarafı yatay eksende sıfır ve Pencerenin tepesi de Düşey eksende sıfır değerini alır.
xKonumu = LOWORD(lParam);
yKonumu = HIWORD(lParam);
Gördüğünüz gibi bazı durumlarda da lParam yada wParam isimli değişken iki parçaya ayrılabiliyor.
Fare ile ilgili bir uygulamayı aşağıda görmektesiniz. Pencere üzerinde fare tuşunu basılı tutarak sürüklerseniz basit bir çizim yapabilirsiniz.
#include const char Classismi[] = "pencere"; // gelen mesajları işleyen kısım LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { POINT fare; HDC hdc; switch(msg) { case WM_CLOSE: DestroyWindow(hwnd); break; case WM_DESTROY: PostQuitMessage(0); break; case WM_MOUSEMOVE: if(wParam==VK_LBUTTON) { fare.x = LOWORD(lParam); fare.y = HIWORD(lParam); hdc = GetDC(hwnd); SetPixel(hdc,fare.x,fare.y, RGB(255,25,20)); ReleaseDC(hwnd, hdc); } if(wParam==VK_RBUTTON) { fare.x = LOWORD(lParam); fare.y = HIWORD(lParam); hdc = GetDC(hwnd); SetPixel(hdc,fare.x,fare.y, RGB(255,255,0)); ReleaseDC(hwnd, hdc); } break; default: return DefWindowProc(hwnd, msg, wParam, lParam); } return 0; } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { WNDCLASSEX wc; HWND hwnd; MSG Msg; //birinci adım: Pencere özelliklerini belirten bir sınıf değişkeni tanımlanıyor wc.cbSize = sizeof(WNDCLASSEX); wc.style = 0; wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_WINDOW); wc.lpszMenuName = NULL; wc.lpszClassName = Classismi; wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); if(!RegisterClassEx(&wc)) { MessageBox(NULL, "Pencere tanımlama hatası!", "Hata!", MB_ICONEXCLAMATION | MB_OK); return 0; } // ikinci adım pencere oluşturma hwnd = CreateWindow(Classismi,"Pencere başlığı",WS_OVERLAPPEDWINDOW, 200, 200, 300, 200,NULL, NULL, hInstance, NULL); ShowWindow(hwnd, SW_SHOW); UpdateWindow(hwnd); // üçüncü adım: mesajların alınması ve ayrılması while(GetMessage(&Msg, NULL, 0, 0) > 0) { TranslateMessage(&Msg); DispatchMessage(&Msg); } return Msg.wParam; } |
Burada yaptığımız proje ilk derste öğrendiğimiz boş pencereye aşağıdaki kodu eklemekten ibaretti. Bunu aşağıda parça parça inceleyelim.
case WM_MOUSEMOVE: if(wParam==VK_RBUTTON) //Fare Sağ tuş basılınca |
ilk baştaki WM_MOUSEMOVE mesajını yukarda uzunca anlatmıştım. bu mesaj geldiğinde fare sürükleniyor demektir. bu sırada sol tuşun basılı olup olmadığını kontrol etmek için wParam değişkenini kontrol ediyoruz. (mavi ile yazılmış olan if komutu ile... dikkat: c++ da if komutu ile çift eşittir kullanılır)
case WM_MOUSEMOVE:
if(wParam == VK_LBUTTON)
{
//bu kısımdaki kodu aşağıda inceleyeceğiz.
}
break;
Şimdi de çizim kısmını inceleyelim öncelikle fonksiyonun başında POINT fare; isimli bir tanımlama yapıyoruz. point değişkeni point.X ve point.Y olarak iki parçadan oluşur. bunu kullanmak yerine int fareXkonumu; ve int fareYkonumu; isimli iki değişken tanımlayarak bunları kullanabilirdik. sadece görmeniz için bunu kullandım.
ilk kısımda lParam değişkeni ikiye parçalanarak farenin X ve Y değerleri alınıyor.
fare.x = LOWORD(lParam);
fare.y = HIWORD(lParam);
Daha sonra alınan bu iki noktayı kullanarak ana pencereye bir nokta atılıyor. burdaki esas komut SetPixel isimli komut. ama bunu kullanabilmek için önce hdc isimli bir tanımlama yapmamız gerekiyor. (HDC handle of display device context (DC) = çizim aracı için kulp diyebiliriz)
hdc = GetDC(hwnd);
SetPixel( hdc,fare.x,fare.y, RGB(255,25,20));
ReleaseDC(hwnd, hdc);
Handle Display Device Context (HDC)
hdc ile istediğimiz herhangi bir pencere yada pencere bileşeni izerine çizim veya resim yapmamız mümkün. Biz oyun yapmaya yoğunlaştığımız için sadece ana pencere üzerinde çizim yapacağız. çizim araçlarını kullanırken hdc isimli bir değişkeni bilmeye ihtiyacımız var. bunu bulmak için ana pencerenin handle(tutamaç,kulp) değerini bilmemiz yeterli. bunu da zaten en başta tanımladığımız için (hwnd) programın herhangi biryerinden çağırabiliriz.
hdc=GetDC(hwnd);
Bu komutu yazdığımızda hdc isimli değişken ana pencerenin çizim alanını temsil ediyor olacak. (bunu da program başında HDC hdc diye tanılmıştık, dikkat: C++ kullanırken tüm değişkenleri kullanmadan önce tanımlamalısınız) Bu fonksiyon yerine BeginPaint(hwnd,PaintStruct) fonksiyonu ile de çizime başlayabiliriz.
hdc isimli çizim değişkenini elde ettikten sonra bunun üzerinde istediğimiz çizimleri yapabilir yada üzerine resim yapıştırabiliriz. işimiz bittikten sonra da ReleaseDC(hwnd, hdc); diyerek bunu tekrar ait olduğu pencereye göndermeliyiz. Eğer BeginPaint fonksiyonunu kullanmışsak EndPaint(hwnd,PaintStruct) fonksiyonu ile çizimi bitirmeliyiz.
Şimdi bazı çizim fonksiyonlarına bakalım:
Ellipse( hdc,solkenar,üstkenar,sağkenar,altkenar); //pencereye daire ve elips çizer
Rectangle(hdc, solkenar,üstkenar,sağkenar,altkenar ); //kare veya dikdörtgen çizer
Pie(hdc, solkenar,üstkenar,sağkenar,altkenar,ilkKesmeX,ilkKesmeY, ikinciKesmeX,ikinciKesmeY); //pasta dilimi çizer
Polygon(hdc,NoktaYapısı,noktaSayısı); //çokgen çizer
RoundRect(hdc, solkenar,üstkenar,sağkenar,altkenar,daireEni,daireBoyu); //Köşeleri yuvarlak dikdörtgen çizer
DrawText(hdc, metinDeğişkeni,metinboyu,KareŞekliPointer, hizalama DT_CENTER);
hdc değişkenini bildikten sonra birkaç sayı kullanarak çeşitli şekiller çizebiliyoruz. kullanımlarına örnek verelim. bu örnekleri WM_PAINT mesajı içine yazabilirsiniz. Aşağıda mavi ile yazılı olan kodu hazırladığınız ana pencerede uygun yere taşımanız yeterli olacaktır.
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) switch (message) |
pencere üzerinde çizim yapmayı gördük, sonraki derste pencere üzerindeki resimler, resimlerin haraketlendirilmesi ve bunların çarpışması gibi işlemleri inceleyeceğiz.
Konuyu anladık mı ?
Uygulama sorusu: Yukardaki ilk örneği geliştirin. Klavyeden S tuşuna basınca sarı çizim yapılsın, M tuşuna basılınca mavi çizim yapılsın, K tuşuna basınca kırmızı çizim yapılsın.
Ekleyen: drekon
Kapalı
Eklediğim Dersler
Ders Kategorileri
Yeni Dersler (Tutorials)
- Armor Modelleme
Ekleyen: Dereli - Ücretsiz Zbrush Dersi.
Ekleyen: BurakB - Corona Render ile Salon Görselleştirme
Ekleyen: barcelona1988 - Tek Bir Resimle Nasıl Sinematik Görüntü Ala Biliriz?
Ekleyen: PixlandPictures - After Effects - Script kullanmadan karakter rigleme
Ekleyen: PixlandPictures - 3dsmax landscape_ Making of Part1
Ekleyen: altıneldiven - Oyun yapımı dersleri 5 - Unity3D Sahne Duzeni
Ekleyen: drekon