Visual C++ ile Görsel Programlama 5 (Win32)

Visual C++ ile Görsel Programlama 5 ( Zamanlayıcı ve Haraket )

Untitled Document

Visual C++ ile Görsel Programlama 5 ( Zamanlayıcı ve Haraket )

Basit bir iki boyutlu Oyun yazmaya geçmeden önce son öğreneceğimiz Zamanlayıcı olacak ; kod sayfasında baş kısımda tanımlama yapıyoruz.
#define ID_ZAMAN 100
ZAMAN isimli bir değişken tanımlıyoruz. daha sonra WM_CREATE mesajı içersinde SetTimer komutu ile bu değişkeni zamanlayıcı yapıyoruz.

case WM_CREATE:
     SetTimer( hWnd, ID_ZAMAN, 1000, NULL );
break;

Bu işlemi yaptıktan sonra bu zamanlayıcı otomatik olarak her saniyede bir kez WM_TIMER isimli bir mesaj gönderir.(1000birim=1 saniye) zamanlayıcıyı 5 saniyelik yapmak isteseydik bu değeri 5000 yapacaktık.

WM_TIMER: //Zamanlayıcı mesajı
wParam: // birden fazla zamanlayıcı kullanılırsa bu değer zamanlayıcı adını veren sayıyı taşır. ( ID_ZAMAN= 100 değerini verir)
lParam: // (TIMERPROC *) lParam; Zamanlayıcı için ayrı bir LRESULT CALLBACK düzenlenmişse bunun adını verir (adres olarak)

buna bir örnek verirsek şu şekilde yazabiliriz. iki tane zamanlayıcımız olduğunu düşünelim. ID_ZAMAN ve ID_ZAMAN2 bu durumda:


case WM_TIMER:
    switch(wParam)
    {
        case ID_ZAMAN:
                // birinci zamanlayıcı mesaj yolladı
       break;

        case ID_ZAMAN2:
                // ikinci zamanlayıcı mesaj yolladı
        break;

    }
break;


devamlı olmasını istediğimiz olayları yukarda kırmızı ile işaretlenen noktaya yazacağız. Eğer buraya bir mesaj kutusu koysaydık her saniyede bir kez mesaj kutusu açılacaktı. Aşağıdaki gibi yazabilirsiniz.

case ID_ZAMAN:
               MessageBox(NULL,"zaman geldi","mesaj başlığı",MB_OK);
break;

Şimdi de bunu kullanarak pencere üzerinde kayan bir resim gösteren bir uygulama yapalım. Bir önceki derste resim eklemeyi gösteren projeye zamanlayıcı eklemek isteseydik değişkenlerin karışık görünmemesi için #define ID_ZAMAN 120 isimli tanımayı da resource.h içersine yazacaktık. sol taraftan dosya adına çift tıklayıp bunu yazdıktan sonra SourceFiles kısmındaki ana kod sayfasına tıklayıp geri dönüyoruz.


Eğer Microsoft'tan başka bir firmanın derleyicisini kullanıyorsanız. #define satırını kodun en başına yazabilirsiniz. aşağıdaki şekilde.

#include <windows.h>
#define ID_ZAMAN 120

Biz buradaki kodu yeni bir proje için yazdık Pencere üzerinde haraket eden bir küre oluşacaktır. küre sağa doğru saniyede 10 birim gitmektedir.

 

 
#include "windows.h" #define ID_ZAMAN 120 const char Classismi[] = "pencere"; int yeriX=0; //cismin X ekseninde yeri int yeriY=0; //cismin Y ekseninde yeri LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { HDC hdc; // çizim için gerekli tanımlamalar PAINTSTRUCT ps; RECT anakare; switch(msg) { case WM_CLOSE: DestroyWindow(hwnd); break; case WM_DESTROY: //zamanlayıcıyı imha et KillTimer(hwnd, ID_ZAMAN); PostQuitMessage(0); break; case WM_CREATE: //zamanlayıcıyı belirle SetTimer( hwnd, ID_ZAMAN, 500, NULL ); break; case WM_PAINT: hdc = BeginPaint(hwnd, &ps); GetClientRect(hwnd, &anakare); FillRect(hdc, &anakare, (HBRUSH)(LTGRAY_BRUSH)); Ellipse(hdc,yeriX,yeriY,yeriX+30,yeriY+30); yeriX=yeriX+10; EndPaint(hwnd, &ps); break; case WM_TIMER: hdc=GetDC(hwnd); GetClientRect(hwnd, &anakare); FillRect(hdc, &anakare, (HBRUSH)(LTGRAY_BRUSH)); Ellipse(hdc,yeriX,yeriY,yeriX+30,yeriY+30); yeriX=yeriX+10; 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; 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+1); 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; } hwnd = CreateWindow(Classismi,"Pencere başlığı",WS_OVERLAPPEDWINDOW, 200, 200, 300, 200,NULL, NULL, hInstance, NULL); ShowWindow(hwnd, SW_SHOW); UpdateWindow(hwnd); while(GetMessage(&Msg, NULL, 0, 0) > 0) { TranslateMessage(&Msg); DispatchMessage(&Msg); } return Msg.wParam; }

yukardaki kod içersinde önemli olan nokta WM_TIMER kısmı ama WM_PAINT kısmını da inceleyelim.

case WM_PAINT:
     hdc = BeginPaint(hwnd, &ps); //ana çizim işlemi başlıyor
     GetClientRect(hwnd, &anakare); //pencere ölçüsünü alıyoruz
     FillRect(hdc, &anakare, (HBRUSH)(LTGRAY_BRUSH)); //aldığımız ölçüyü kullanarak pencereyi gri renge boyuyoruz

     Ellipse(hdc,yeriX,yeriY,yeriX+30,yeriY+30); // hdc üzerine daire çiziyoruz
     yeriX=yeriX+10; // X konumunu 10 arttırıyoruz

     EndPaint(hwnd, &ps); //ana çizim işlemi bitti
break;

case WM_TIMER:
     hdc=GetDC(hwnd); //çizim işlemi için ana hdc'yi çağırıyoruz
     GetClientRect(hwnd, &anakare); //pencere ölçüsü alıyoruz
     FillRect(hdc, &anakare, (HBRUSH)(LTGRAY_BRUSH)); //aldığımız ölçüyü kullanarak pencereyi gri renge boyuyoruz

     Ellipse(hdc,yeriX,yeriY,yeriX+30,yeriY+30); //hdc üzerine daire çiziyoruz
     yeriX=yeriX+10; // X konumunu 10 arttırıyoruz

     ReleaseDC(hwnd,hdc); //çizim işlemini bitiriyoruz
break;

Aslında komutu sadece WM_TIMER içine yazmamız gerekiyordu, ama eğer WM_PAINT içersinde benzer bir çizim kodu yazmazsak pencereye tazeleme mesajı geldiğinde bir saniye süre ile pencere tamamen beyaz olur. bunu görmek için case WM_PAINT ile break; arasını silebilirsiniz.

Bu projede Her saniye çizimi yeniden yapıyoruz. Ana pencereyi her seferinde gri renge boyayıp daireyi tekrar çiziyoruz, Fakat daire her çizimde farklı bir noktaya çizildiği için haraket ediyormuş gibi görünüyor.Bu yöntemde çizdiğimiz daireyi ana pencereden silmenin bir yolu yoktur. Birçok oyunda her an tüm sahne yeniden çizilir. saniyede kaç kere çizildiği ise FPS (frame per second) ismi ile tanımlanır. Yeni çıkan üç boyutlu oyunların bu kadar hızlı (ve pahalı) kartlar istemesinin sebebi budur. Saniyede birçok kere gördüğünüz cisimleri yeniden yeniden çizmektedirler.

Konuyu anladık mı ?
Uygulama sorusu: Bu uygulamayı geliştirin. Yuvarlak cisim sağ kenara çarpınca geri gitsin.

 

Ekleyen: drekon

Kapalı

Topic closed automatically because it`s been more than a year!