You are on page 1of 21

Visual C++ ile Grsel Programlama 6 ( Balonlar Vur ) ilk oyunumuzu yazyoruz.

Fare ile ekrandaki hedefi kullanarak balonlar vuracaz, ama ksa srede hepsini vurmak. Her ne kadar bu tek blmlk basit bir oyun olsa da birok olay anlamanzda kaynak olacaktr. directX ve OpenGL oyunlarna gemeden nce bu oyunu iyice anlamaya alalm. Oyuna gemeden nce standart C zelliklerini daha renmek zorundayz. Programlamaya yeni baladysanz bu konuya balamadan nce ilk ders olan C temelleri ksmna mutlaka gz atn, bu ksmdaki konular anlamanz iin; Deiken, Sorgu ( if ), Dizi ( Array ), Yap ( Struct ) , gibi terimleri renmeniz gerekiyor. Aada kaynak kodu verilen oyunu sitemizden indirebilirsiniz. Visual C++ 6.0 iin kaynak kodunu indirmek iin tklayn

#include "windows.h" #include "time.h" //bitirme sresini hesaplamak iin #include "resource.h" //sadeceresimleri eklemek iin #define ID_ZAMAN 100 const char Classismi[] = "pencere"; HBITMAP resim=NULL; //balon resmi HBITMAP hedefRsm=NULL; //hedef resmi int hedefX; //hedefin konumu int hedefY; int ates=0; int i; int fark; //oyunu bitirme zaman int bitti; //tm balonlar vurulunca bitti=1 olacak time_t giris,bitis; //oyuna girme ve kma zamanlar typedef struct _BALON //balon cismi tanmlyoruz

{ // sadece iimizi kolaylatryor int X; //yoksa her balon iin bu deikenleri ayr ayr tanmlayacaktk. int Y; int saglam; //bu deer balon vurulmam ise 0 olacak int yon; //haraket yn int hiz; }BALON; BALON balon[7]; //yedi tane balon yapyoruz LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { HDC hdc; HDC resimhdc; PAINTSTRUCT ps; RECT anakare; HDC hedefhdc; char sure[8]; char metin[]="Bitirme sreniz : "; switch(msg) { case WM_KEYDOWN: if(wParam=VK_ESCAPE) //ESC tuuna basld { DestroyWindow(hwnd); } break; case WM_MOUSEMOVE: //fare haraket ettirildi hedefX = LOWORD(lParam); hedefY = HIWORD(lParam); break; case WM_LBUTTONDOWN: //fare sol tuu basld if(ates==0) { hdc=GetDC(hwnd); //hedefin altndaki renk sar ise ilem yaplr sar=RGB(255,255,0) if(GetPixel(hdc,hedefX+11,hedefY+11)==RGB(255,255,0)) { //sol tu baslnca tm balonlar dng ile kontrol edilip hedefin altndakiler belirleniyor for(i=0; i<7; i++) { if((balon[i].X < hedefX+11) && (hedefX+11 < balon[i].X+17)) { if((balon[i].Y < hedefY+11) && (hedefY+11 < balon[i].Y+39)) { //hedefin altndaki balonun salam isimli deikeni 1(bir) yaplyor

balon[i].saglam=1;

bitti=1; } } }

brakmal break;

} ReleaseDC(hwnd,hdc); ates=1; //ate edildi, tekrar ate iin tuu }

case WM_LBUTTONUP: //fare sol tuu brakld ates=0; //tuu brakmadan tekrar ate edemez break; case WM_PAINT: //pencere boyama ilemi hdc = BeginPaint(hwnd, &ps); break; EndPaint(hwnd, &ps);

case WM_TIMER: //zamanlayc, saniyede 20 kere tekrarlanan izim ve haraket ilemleri hdc = GetDC(hwnd); GetClientRect(hwnd, &anakare); FillRect(hdc, &anakare, (HBRUSH)

(WHITE_PEN));

resimhdc = CreateCompatibleDC(hdc); //iki tane resim tutucu hdc tanmlanyor hedefhdc = CreateCompatibleDC(hdc); SelectObject(resimhdc,resim); for(i=0; i<7; i++) { //izim yaplrken salam deikeni 0(sfr) olanlar iziliyor if(balon[i].saglam==0) { //balonlar iz BitBlt(hdc,balon[i].X,balon[i].Y,17,39,resimhdc,0,0,SRCAND); //balonlar sol tarafa kamasn if(balon[i].X <= 0) { balon[i].yon=1; } //balonlar sa tarafa kamasn if(balon[i].X >= 500) {

balon[i].yon=0; } -hiz- kadar deitiriliyor //balonlarn yeri if(balon[i].yon==0) { balon[i].X}else{ balon[i].X+=balon[i].hiz; } } }

=balon[i].hiz;

//balonlarn hepsi vuruldu mu? for(i=0; i<7 ;i++) { if(balon[i].saglam==0) { bitti=0; } } //balonlar bittiyse pencereyi kapat if(bitti==1) { DestroyWindow(hwnd); } //hedefi iz SelectObject(hedefhdc,hedefRsm); BitBlt(hdc, hedefX, hedefY, hedefX+22, hedefY+24, hedefhdc, 0, 0, SRCAND); DeleteDC(resimhdc); DeleteDC(hedefhdc); ReleaseDC(hwnd, hdc); break; case WM_CREATE: // pencere oluurken sadece bir kez yaplacak ilemler //resimleri ykle resim = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_BITMAP1)); hedefRsm= LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_BITMAP2)); //zamanlaycy ayarla SetTimer( hwnd, ID_ZAMAN, 50, NULL ); GetClientRect(hwnd, &anakare); hedefX=anakare.right/2; //hedefi pencerede ortaladk hedefY=anakare.bottom/2; for(i=0; i<7 ;i++) //balonlarn konumunu belirle {

balon[i].X=i*15; //tektek yazmak yerine satrda belirledik balon[i].Y=i*50; //dng ile iki balon[i].hiz=2; } balon[3].hiz=1; //drt balonun hzn balon[1].hiz=4; balon[5].hiz=1; balon[6].hiz=3; balon[1].yon=1; // balonun ynn balon[4].yon=1; balon[0].yon=1; ShowCursor(FALSE); //fare okunu gizle time(&giris);

deitiriyoruz

deitiriyoruz

break;

case WM_CLOSE: //pencere kapatld DestroyWindow(hwnd); break; case WM_DESTROY: //pencere yok ediliyor DeleteObject(resim); DeleteObject(hedefRsm); KillTimer(hwnd, ID_ZAMAN); //balonlar bittiyse bitirme sresini gster if(bitti==1) { ShowCursor(TRUE); time(&bitis); fark=difftime(bitis,giris); itoa(fark,sure,10); strcat(metin,sure); strcat(metin," saniye"); MessageBox(NULL,metin,"Oynadnz iin teekkr ederiz",MB_OK); } PostQuitMessage(0); 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; wc.cbSize wc.style wc.lpfnWndProc wc.cbClsExtra = = = = sizeof(WNDCLASSEX); 0; WndProc; 0;

wc.cbWndExtra wc.hInstance wc.hIcon wc.hCursor wc.hbrBackground wc.lpszMenuName wc.lpszClassName wc.hIconSm

= = = = = = = =

0; hInstance; LoadIcon(NULL, IDI_APPLICATION); LoadCursor(NULL, IDC_ARROW); (HBRUSH)(COLOR_WINDOW+1); NULL; Classismi; LoadIcon(NULL, IDI_APPLICATION);

if(!RegisterClassEx(&wc)) { MessageBox(NULL, "Pencere tanmlama hatas!", "Hata!", MB_ICONEXCLAMATION | MB_OK); return 0; } hwnd = CreateWindow(Classismi,"www.tr3d.com -> basit oyun denemesi",WS_DLGFRAME, 200, 200, 500, 400,NULL, NULL, hInstance, NULL); ShowWindow(hwnd, SW_SHOW); UpdateWindow(hwnd); while(GetMessage(&Msg, NULL, 0, 0) > 0) { TranslateMessage(&Msg); DispatchMessage(&Msg); } return Msg.wParam; }

Konuyu anladk m ? Uygulama sorusu: Bu oyunu gelitirin. Baz balonlarn yukar ve aa gitmesini salayan bir kod ekleyin. Ylan oyunu iin kaynak kodlar. Drekon'un almasna eklenerek yaplmtr.Bu yzden aklamas olmayan yerler iin Drekon'un eski tutoriallerine baknz... Faydal olabilmesi dileiyle...XaeRO...

#include "windows.h" bool yem=FALSE; // yem iin boolean, yendi zaman false olacak ve yeni yem gerektii anlalacak #define ID_ZAMAN 120 // ylan iin #define ID_ZAMAN2 121 // ereve iin const char Classismi[] = "pencere"; int i,oncekix[100],oncekiy[100]; // // int k,yemx,yemy; // kullanld // i: ylan uzunluu oncekix ve y: ilerde akland k: yalnzca dnglerde yemx ve y: yem konumu iin

typedef struct _YILAN // ylanmz iin struct, bizim iin nemli olan yonu ve konumu { int yon; int x; int y; }YILAN; YILAN yilan[500]; // burda ylan bir dizi eklinde tanmladk. // say kanc para olduunu belirtiyor. // mesela yilan[1]: ylann ba,2: ikinci paras vb.. LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRUCT ps; RECT anakare; HBRUSH hbrush; // ii boyal cisimler iin gereken boya HBRUSH old_brush; // eski boyay hafzaya almak iin gerekli switch(msg) { (wParam)

// tua gre yn belirleniyor { // nemli olan ylann bann yn olduundan case VK_UP: // yalnzca ylan[1]'in ynn deitirmemiz yeterli if(yilan[1].yon==2) // dier paralar bir ncekini takip edecek yilan[1].yon=2; else yilan[1].yon=8; break; case VK_DOWN: // buradaki if ters yne hareketi engellemek if(yilan[1].yon==8) yilan[1].yon=8; // iin gerekli.mesela saa giderken sola basldnda else // saa gitmeye devam edecek. yilan[1].yon=2; break; case VK_LEFT: // 2,4,6,8'i kolaylk olsun diye kullandm if(yilan[1].yon==6) // hangi ynleri temsil ettiini bilirsiniz artk:) yilan[1].yon=6; else yilan[1].yon=4; break; case VK_RIGHT: if(yilan[1].yon==4)

case WM_KEYDOWN: switch

yilan[1].yon=4; else yilan[1].yon=6; break; default:break;

} break; case WM_CLOSE: DestroyWindow(hwnd); break; case WM_DESTROY:

//zamanlayclar imha et KillTimer(hwnd, ID_ZAMAN); KillTimer(hwnd, ID_ZAMAN2); PostQuitMessage(0); break; case WM_CREATE: i=3; yilan[1].x=10; yilan[1].y=10; // balang iin ylan // balangta ylan[1]'in // dier paralar da ayn // //

uzunluu 3'e ayarl konumu yerde balayacak

SetTimer( hwnd, ID_ZAMAN2, 0, NULL ); ereve iin zamanlayc SetTimer( hwnd, ID_ZAMAN, 20, NULL ); ylan iin zamanlayc. break; case WM_PAINT: bu WM_PAINT olayn anlamadm bi trl balang iin ylan izdim ama izmeseniz de oluyo hatta WM_PAINT ksmn tamamen silip denedim GetClientRect(hwnd, &anakare); biey deimedi:) formalite hdc = BeginPaint(hwnd, &ps);

// // // // // //

lan[k].x+10,yilan[k].y+10);

for(k=1;k<=i;k++) { Ellipse(hdc,yilan[k].x,yilan[k].y,yi } EndPaint(hwnd, &ps);

break; case WM_TIMER: switch(wParam) { case ID_ZAMAN: zamanlayc

// ylan iin

if(yem==FALSE) yem yendiinde FALSE olcak demitik { bu durumda yeni yem iin konum belirleniyor yemi rastgele biyere koycaz.bunun iin rand() kullandm (eski c'den kalma, belki visual c'de yemx=((rand()%160)/10)*10+10; baka komutlar da vardr.) ncelikle kullanmn akliim.a=rand()%30 denildiinde 0'la 30'arasnda rastgele bi say seilip a'ya atanr. yandaki 10'lar gznz korkutmasn.lk iki 10 rastgele yemy=((rand()%90)/10)*10+10; seilen saynn 10'un kat olmas iin.mesela 111 seilen say (111/10)*10=110 olur.bu bize lazm nk ylan hep 10'ar 10'ar hareket etcek 3. 10 ise sadece yemi ereve iinde tutmak iin gerekli. } hdc=GetDC(hwnd); GetClientRect(hwnd, &anakare); FillRect(hdc, &anakare, (HBRUSH)

// // // // // // // // // // // // //

(LTGRAY_BRUSH));

hbrush = CreateSolidBrush(RGB(50,50,250)); // balyoruz

yemi izmeye

// bu ksmlar ii dolu biey izmek iin old_brush = (HBRUSH)SelectObject(hdc,hbrush); // klasiktir.ben ezberliyemedim hala kopyala_yaptr:) // nce mavi renkli bir fra hazrlayp // eski fray old_brush'a attk.

Ellipse(hdc,yemx,yemy,yemx+10,yemy+1 // ve ap 10 olam mavi yemi izdik. yem=TRUE; // yem izildiine gre artk TRUE 0); // eski fray yerine koyup // yenisini sildik. +) yeni konumunun / belirlenmesi iin. { 1]=yilan[k].x; 1]=yilan[k].y; oncekix[k// ylann her parasnn u anki konumu oncekiy[k// oncekix ve y dizilerine alnyor if(k==1) { // ylan belirlenen yne gre hareket 10; // ettiriyoruz.nemli olan ylann SelectObject(hdc,old_brush); DeleteObject(hbrush); for(k=1;k<=i;k+ // hareket dngs: her parann teker teker /

if (yilan[1].yon==6) yilan[1].x+=

else // ban (yilan[1]) hareket ettirmek. yilan[1].x=10; // geri kalan paralar yalnzca onu takip else if(yilan[1].yon==2) // edecek. yilan[1].y+= 10; else if(yilan[1].yon==8) yilan[1].y=10; } else { yilan[k].x=oncekix[k -2]; // paralarn yeni konumlar belirleniyor yilan[k].y=oncekiy[k -2]; // tek ama paralarn kendinden nceki if(yilan[1].yon==4) // paraynn yerine gemesi } if((yilan[1].x<10) || (yilan[1].x>170) || (yilan[1].y>100) || (yilan[1].y<10)) { // ylann ereveye arpmas durumunda ID_ZAMAN); mesaj retilir ID_ZAMAN2); KillTimer(hwnd, // zamanlaycy durdurmazsak srekli yeni KillTimer(hwnd,

MessageBox(NULL,"AHA AHAHA ARPTIII!!!","GMMMMM",MB_OK); // mesajmz DestroyWindow(hwnd); // oyundan ksn istiyoruz PostQuitMessage(0); } // ve dngye gre k arttka ylanmzn paralar yeni konumlaryla iziliyor Ellipse(hdc,yilan[k].x,yilan[k].y,yilan[k].x+10,yilan[k].y+10); } ReleaseDC(hwnd,hdc); if(i>3) kendisine arpmas durumunu inceliyoruz olmasnn nedeni balangta paralarn stste // ylann // i>3 iken

// balamas, yoksa daha balangta oyun biterdi. { for(k=2;k<=i;k++) // yilan bann konumunun dier btn paralarla kyasland dng { if(yilan[1].x==yilan [k].x) // nce x konumu, eitse y konumu kontrol { // ediliyor o da eitse arpm demektir if(yilan[1]. y==yilan[k].y) { Kill Timer(hwnd, ID_ZAMAN); Kill Timer(hwnd, ID_ZAMAN2); Mess ageBox(NULL,"AHAAHAHA ARPTIII!!!","GMMMMM",MB_OK); Dest royWindow(hwnd); Post QuitMessage(0); } } } } if(yilan[1].x==yemx) bu sefer de yilan[1] (ba) konumu { yemle karlatrlyor if(yilan[1].y==yemy) x ve y'ler eitse yemi demektir { yem=FALSE; yendiinde FALSE olcan sylemitik i=i+1; yendiinde ylann boyunu bir artryoruz } // // // // //

} break; ereve iin zamanlayc CreateSolidBrush(RGB(0,0,0)); izdiriyoruz case ID_ZAMAN2: hbrush = // siyah renkli ereve //

old_brush = (HBRUSH)SelectObject(hdc,hbrush); Rectangle(hdc,0,0,10,150); Rectangle(hdc,180,0,200,150); Rectangle(hdc,0,0,200,10); Rectangle(hdc,0,110,200,130); SelectObject(hdc,old_brush); DeleteObject(hbrush); // Not: ereve iin yeni bir zamanlayc kullanmak zorunda kaldm yoksa izmiyor // nedenini bilmiyorum ama byle bile refresh sorunlar oluyor // (geici olarak ereve ihtiyacmz karlad) } break;

} return 0;

break; default: return DefWindowProc(hwnd, msg, wParam, lParam);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { WNDCLASSEX wc; HWND hwnd; MSG Msg; wc.cbSize wc.style wc.lpfnWndProc wc.cbClsExtra wc.cbWndExtra wc.hInstance wc.hIcon wc.hCursor wc.hbrBackground wc.lpszMenuName wc.lpszClassName wc.hIconSm = = = = = = = = = = = = sizeof(WNDCLASSEX); 0; WndProc; 0; 0; hInstance; LoadIcon(NULL, IDI_APPLICATION); LoadCursor(NULL, IDC_ARROW); (HBRUSH)(COLOR_WINDOW+1); NULL; Classismi; LoadIcon(NULL, IDI_APPLICATION);

if(!RegisterClassEx(&wc)) { MessageBox(NULL, "Pencere tanmlama hatas!", "Hata!", MB_ICONEXCLAMATION | MB_OK);

return 0; } hwnd = CreateWindow(Classismi,"YILAN DENEMES",WS_OVERLAPPEDWINDOW, 410, 330, 200, 150,NULL, NULL, hInstance, NULL); ShowWindow(hwnd, SW_SHOW); UpdateWindow(hwnd); while(GetMessage(&Msg, NULL, 0, 0) > 0) { TranslateMessage(&Msg); DispatchMessage(&Msg); } return Msg.wParam; } OpenGL Oyunlarna giri
boyutlu oyun programlamaya girerken OpenGL ile balamak daha mantkl olacaktr. nk DirectX ile oyun yazabilmek iin ncelikle microsoft.com sitesinden DirectX SDK ad verilen ve genellikle 400-500 Mb boyutlarnda olan dosyay indirmek gerekiyor. OpenGL ise birok dersleyici ile hazr gelmektedir. Ayrca hazrladnz OpenGL tabanl oyun birka deiiklik ile daha sonra DirectX ile de kullanlabilmektedir. Bu sebeple ilk aamada oyunlarmz OpenGL ile yazacaz. OpenGL nin sorunu ise eski ekran kartlar ile almamasdr, mutlaka 3D zellii olan bir kart gerekir(En azndan TNT veya Geforce ekran kart olmaldr) . DirectX ise ok eski kartlarla da almasna ramen siz program hangi versiyonda yazdysanz kullanc da directX'in o versiyonunu bilgisayarna yklemek zorundadr. bu sebeple birok oyun CDsi iersinde DirectX'in son versiyonu CD iinde verilir. Buradaki Derse balamadan nce ilk dersleri iyice inceleyin ve C programlama hakknda bilgi edinin, aksi halde buradan da birey anlamazsnz. Ayrca MFC programclnda uzman olsanz bile hereye tam anlam ile hakim olduunuz bir oyun yazmak iin MFC programlarn da bir kenara brakmalsnz. (internette MFC ile yazlm oyun rnekleri bulabilirsiniz ama ben MFC kullanmadan yazmanz tavsiye ederim) Balk Dosyalar: openGL ile program yazmak iin gerekli olan dosyalar Visual C kurulu olan dizinde include/gl dizini iindedir. buradaki komutlar programnzda kullanabilmek iin #include komutu ile iki dosyay programam dahil etmelisiniz. #include <gl/gl.h> #include <gl/glu.h>

opengl32.lib ve glu32.lib dosyalarn Project>>Settings>>Link ksmndan eklemelisiniz. Bunlar openGL komutlarn kullanabilmek iin yapmak zorundasnz.
bunun yannda library(ktphane) dosyalarn da projeye link(balama) ilemini de unutmamalsnz.

OpenGL ile ilemleri yaparken hdc=GetDC(hwnd); komutu ile izim ilemlerin balayacaz. daha nceki derslerde bu komutu incelemitik. ilemler bittikten sonra ReleaseDC(hwnd,hdc); komutu ile kapatacaz. Not: baz ekran kartlarnda penceretipi(wc) isimli deiken iersine CS_OWNDC parametresini girmek gerekmektedir. ( Ati Rage Pro, RivaTNT gibi.) penceretipi.style =CS_OWNDC ; veya baz rneklerde yle yazmtk wc.style Pixel Format Oyunu kodlamaya gemeden nce tanmlamak zorunda olduumuz bir deiken daha var. PixelFormat bu deiken az nce aldmz DC'yi nasl kullanacamz sisteme bildiriyor. Oyun hastalar u zellikleri belki dumutur; double buffering, z-buffer, color format alpha buffer... bu tip zellikleri bu deiken ile tanmlyoruz.

PIXELFORMATDESCRIPTOR pixelbilgisi; //deiken tanmlama ZeroMemory( &pixelbilgisi, sizeof( pixelbilgisi ) ); pixelbilgisi.nSize = sizeof( pixelbilgisi ); //deiken iersine bilgilerin doldurulmas pixelbilgisi.nVersion = 1; pixelbilgisi.dwFlags =PDF_DRAW_TO_WINDOW | PDF_SUPPORT_OPENGL | PDF_DOUBLEBUFFER; pixelbilgisi.iPixelType = PDF_TYPE_RGBA; pixelbilgisi.cColorBits = 24; pixelbilgisi.cDepthBits = 16; pixelbilgisi.iLayerType = PDF_MAIN_PLANE; int iFormat = ChoosePixelFormat( hdc, &pixelbilgisi ); //hdc iin en uygun pixel format belirleniyor SetPixelFormat( hDC, iFormat, &pixelbilgisi );
Double Buffer Double buffer kullandmzda Dc iersine izdiimiz herey hafzada grnr olmayan bir blgeye gider. PDF_DOUBLEBUFFER ile bunu yukarda tanmlam oluyoruz. Biz programa gster diyene kadar pencere zerinde gsterilmez. Bylece sahneyi grnmeden deitirip render ilemleri yaplr ve ilemlerin son hali kullancya gsterilir.bunu

tek bir fonksiyonla yaparz SwapBuffers(hdc); bylece son grnt pencere zerine aktarlr.

Render Context Oyun programna gemeden nce reneceimiz ok az fonksiyon kald. Sradaki ilem renderContext hazrlamak (RC). win32 ortamndaki herey gibi bunu da handle ile kontrol edeceiz. biraz farkl olarak HGLRC tipinde bir deiken ile tanmlanyor. Bu deiken OpenGL ile programmz arasnda kpr vazifesi yapacaktr.
HGLRC hrc; hrc = wglCreateContext(hdc);

RC ile iimiz bittikten sonra program kapanrken hafzadan silmek iin wglDeleteContext komutunu kullanyoruz.
Bu komut ile nceden aldmz hdc ile ilikili bir RC oluturuluyor.

wglDeleteContext(hrc);
ayn anda birden fazla OpenGL uygulamas alyor olabilir bu durumda kullandmz programdaki RC'y iaktif yapmak iin wglMakeCurrent komutu kullanlyor. wglMakeCurrent(hdc,hrc); OpenGl ile ilgili tm ilemleri ve fonksiyonlar kullandktan sonra Render Context deikenini dierlerinin de kullanabilmesi iin wglMakeCurrent komutunu tekrar kullanyoruz. tabii bu sefer parametresi bo olmal. wglMakeCurrent(NULL,NULL); Eer bizim programdan nce OpenGL render ilemini hangi programn kullandn bilmek isterseniz. wglCurrentDC ve wglCurrentContext komutlar ile o andaki bilgileri eskiDC ve eskiRC isimli iki deiken iersinde saklayabilirsiniz. wglGetCurrentContext. HDC eskihDC = wglGetCurrentDC(); HGLRC eskihRC = wglGetCurrentContext(); wglMakeCurrent( hdc, hrc ); //RC yi ele geirdiimize gre komutlar buraya yazyoruz iimiz bittikten sonra OpenGL sistemini bir nceki uygulamaya geri vermek iin yine makeCurrent komutunu kullanp az nce aldmz eski isimli deikenleri kullanyoruz. wglMakeCurrent(eskihDC,eskihRC); bu sisteme ayn anda birden fazla openGL ieren sistem kullanyorsanz ihtiyacnz olacak. aksi halde NULL diyip gerisine karmazsnz. rnek olarak ayn anda ekranda iki oyuncunun da kendi arabasn yarm ekranda srd grnty veren NeedForSpeed oyununu verebiliriz. Hepsini Toparlayalm rendiimiz tm deikenleri kullanarak pencerede OpenGL renderini aktif etmek ve iptal etmek iin iki fonksiyon yazabiliriz.

void OpenGL_aktif(HWND hWnd, HDC * hDC, HGLRC * hRC) { PIXELFORMATDESCRIPTOR pixelbilgisi; int iFormat; // pencerenin izim alan yakalanyor *hDC = GetDC( hWnd ); // pixel bilgisi deikeni tanmlanyor ZeroMemory( &pixelbilgisi, sizeof( pixelbilgisi ) ); pixelbilgisi.nSize = sizeof( pixelbilgisi );

pixelbilgisi.nVersion = 1; pixelbilgisi.dwFlags = PDF_DRAW_TO_WINDOW | PDF_SUPPORT_OPENGL | PDF_DOUBLEBUFFER; pixelbilgisi.iPixelType = PDF_TYPE_RGBA; pixelbilgisi.cColorBits = 24; pixelbilgisi.cDepthBits = 16; pixelbilgisi.iLayerType = PDF_MAIN_PLANE; iFormat = ChoosePixelFormat( *hDC, &pixelbilgisi ); SetPixelFormat( *hDC, iFormat, &pixelbilgisi ); // RC oluturulup aktif render atanyor *hRC = wglCreateContext( *hDC ); wglMakeCurrent( *hDC, *hRC ); } //openGL renderini iptal eden fonksiyon void OpenGL_iptal(HWND hWnd, HDC hDC, HGLRC hRC) { wglMakeCurrent( NULL, NULL ); wglDeleteContext( hRC ); ReleaseDC( hWnd, hDC ); }
Bylece OpenGL_aktif ve OpenGL_iptal isimli iki fonksiyon arasna istediimiz tm GL fonksiyonlarn yazabiliriz. DoubleBuffer sistemini hatrlayn. SwapBuffers komutunu da kullanmamz gerekiyor. Aadaki uygulama ile rendiklerimizi kullanalm.

#define WIN32_LEAN_AND_MEAN //ktphaneleri temizler // bunlar include etmek zorunlu #include #include #include

#include

//yardmc fonksiyonlar

//render fonksiyonu tanmlamas void RenderScene(); //dndrme iin kullanacamz a float angle = 0.0f; // genel DC tanmlamas HDC hdc; HDC kullanabiliriz.

// pixel formatn tanmlamak iin fonksiyon void SetupPixelFormat(HDC hDC) { int nPixelFormat; static PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), // 1, // PFD_DRAW_TO_WINDOW | // PFD_SUPPORT_OPENGL | // PFD_DOUBLEBUFFER, // PFD_TYPE_RGBA, // 32, // 0, 0, 0, 0, 0, 0, // nemseme 0, // 0, // nemseme 0, // 0, 0, 0, 0, // nemseme 16, // 0, // says 0, // PFD_MAIN_PLANE, // 0, // 0, 0, 0 }; // nemsenmiyor

yapnn boyu herzaman 1 pencere destei OpenGl destei Double Buffer destei RGBA destei 32 bit renk modu renk bit'lerini alpha buffer yok deien bit'leri ylma buffer yok ylma bit'lerini depth buffer bit says stencil buffer bit auxiliary buffer yok Ana izim yzeyi ayrlm alan layer maskeleri

// en uygun pixel formatn se nPixelFormat = ChoosePixelFormat(hDC, &pfd); // hdc ile pixel formatn ilikilendir. SetPixelFormat(hDC, nPixelFormat, &pfd); // Buradaki deerlerin hepsini bilmek zorunda deilsiniz. //sadece programa bu fonksiyonu ekleyin yeter

// Burada pencere hazrlanmas var, bunlar nceden rendiiniz iin aklama yazmyorum LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static HGLRC hRC; // Render context. hrc static HDC hDC; // Device context. hdc int width, height; //pencere eni ve boyu

switch(message) { case WM_CREATE: hDC = GetDC(hwnd); arlyor hdc = hDC; eitleniyor SetupPixelFormat(hDC); fonksiyonuna yollanyor hRC = wglCreateContext(hDC); oluturuluyor wglMakeCurrent(hDC, hRC); oalrak atanyor return 0; break; case WM_SIZE: height = HIWORD(lParam); width = LOWORD(lParam); if(height==0) { height = 1; } gre ayarla sfrla

// pencere oluturuluyor // pencereden izim alan // genel dc ile // yukardaki pixelFormat // Render Context // RC geerli pencere

// pencere boyu deiiyor // pencere boyunu al // pencere enini al // boy =0 olursa boy=1 yap

glViewport(0, 0, width, height); // grnm yeni boya glMatrixMode(GL_PROJECTION); glLoadIdentity(); // izim alann ayarla // grnm alann

// pencere grnmn hesapla gluPerspective(45.0f, (GLfloat)width/(GLfloat)height, 1.0f, 1000.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); sfrla return 0; break; // izim alann ayarla // grnm alann

case WM_CLOSE: mesaj siliniyor

// pencere kapanyor

wglMakeCurrent(hDC, NULL); wglDeleteContext(hRC); // render context // pencereyi imha etme

PostQuitMessage(0); mesaj atlyor return 0; break; default: break;

} // kullanlmayan mesajlar olduu gibi geri yolla return (DefWindowProc(hwnd, message, wParam, lParam));

} // an dng ve pencere oluturma int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { MSG msg; // mesaj deikeni WNDCLASSEX penceretipi; // pencere tipini belirlerken kullanlacak deken HWND hwnd; // pencere iin kulp(tutama,sap) bool bittiMi; is done or not. // This will be used to check if the program

// This is the Window class. Each attribute is defined for the creation of the // window. I will try to go over more in future tutorials but if you want the // complete list of all the different values you can pass, check out the MSDN. penceretipi.cbSize = sizeof(WNDCLASSEX); penceretipi.style = CS_HREDRAW | CS_VREDRAW; penceretipi.lpfnWndProc = WndProc; penceretipi.cbClsExtra = 0; penceretipi.cbWndExtra = 0; penceretipi.hInstance = hInstance; penceretipi.hIcon = LoadIcon(NULL, IDI_APPLICATION);//pencere ikonu penceretipi.hCursor = LoadCursor(NULL, IDC_ARROW);//fare ok iareti tipi penceretipi.hbrBackground = NULL; penceretipi.lpszMenuName = NULL; penceretipi.lpszClassName = "tr3d"; // deikenin snf ad penceretipi.hIconSm = LoadIcon(NULL, IDI_APPLICATION);//minik ikon if(!RegisterClassEx(&penceretipi)) return 0; hwnd = CreateWindowEx(NULL, "tr3d", //pencere tipini belirten snf ; yukardaki "ilk openGL program",// pencere bal WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_SYSMENU | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 100, 100, 400, 400, NULL, NULL, hInstance, NULL);

// pencere oluturmada hata varsa, program kapat if(!hwnd) return 0;

ShowWindow(hwnd, SW_SHOW); // oluturulan pencereyi gster UpdateWindow(hwnd); // boyama ilemi yap bittiMi = false; while(!bittiMi) //program hala alyor { PeekMessage(&msg, hwnd, NULL, NULL, PM_REMOVE); verirse if(msg.message == WM_QUIT) // program kapatma mesaj { } else { aada RenderScene(); bittiMi = true; // program sonlandr // aksi halde render ilemi yap //render ilemleri iin fonksiyon,

} } return msg.wParam; }

TranslateMessage(&msg); DispatchMessage(&msg);

// render ilemi : saniyede 25 veya daha fazla kez alyor //bylece yeniden yeniden izilen ekiller haraketli gibi grnyor void RenderScene() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // ncelikle ekran temizliyoruz glLoadIdentity(); //model grnmn sfrlyoruz angle = angle + 0.1f; deikeni // bu kullanacamz a

// ekrana gelen her karede bir artyor if(angle >= 360.0f) angle = 0.0f; // a 360 dan bykse // sfra dn

glTranslatef(0.0f, 0.0f, -5.0f); // izime balamadan nce 5 birim arkaya git glRotatef(angle, 0.0f, 0.0f, 1.0f); // angle isimli deiken kadar evirme ilemi yap // gen izmek iin nokta gerekiyor // glBegin/glEnd() arasna yazdklarmz izim olarak karmza kyor glBegin(GL_TRIANGLES); // gen izmeye bala

glColor3f(0.0f, 0.0f, 1.0f); glVertex3f(0.0f, 1.0f, 0.0f); glColor3f(1.0f, 0.0f, 0.0f); glVertex3f(1.0f, 0.0f, 0.0f); glColor3f(1.0f, 1.0f, 1.0f); glVertex3f(-1.0f, 0.0f, 0.0f); glEnd(); SwapBuffers(hdc); izdiklerimizi ekranda gster }

// ilk nokta rengi (mavi) // ilk noktann yeri // ikinci nokta (krmz) // ikinci noktann yeri // nc nokta (beyaz) // nc noktann yeri // izim ilemini bitir //buffer'leri evirip

// OpenGL ilk bata zor grlebilir fakat devaml kullanlan zelliklerine altktan sonra // elenceli programlar yazmaya balayacaksnz

Konuyu anladk m ? Uygulama sorusu: genin boyunu bytp rengini tamamen sar yapmay deneyin, dnme hzn be kat arttrn.