Game Design PL - Kurs DirectX


Autor: Worm
Data: 4 Marzec 2001

Intro
Tym artykułem chciałbym rozpocząć pierwszą część serii artykułów na temat programowania z wykorzystaniem bibliotek DirectX w Visual C++. Seria adresowana jest dla początkujących, więc wszystko będę dokładnie opisywał. W pierwszej lekcji zajmiemy sie DirectDraw i grafiką 2D.

Do dzieła!
Spróbujemy napisać program który wyświetli nam plik graficzny (bitmapę) w trybie DirectDraw. Utwórz nowy Obszar Roboczy i nazwij go 'Kurs DirectX', utwórz w nim nowy projekt i nazwij go 'Lekcja1'. Następnie dodaj pliki 'ddraw.lib', 'dxguid.lib', 'lekcja1.cpp' i 'tlo.bmp'. Po obejrzeniu działania programu możemy przejść do analizy kodu.

#include <windows.h>
#include <ddraw.h>
//Dodajemy dwa pliki nagłówkowe wymagane abyśmy mogli korzystać z większości funkcji

LPDIRECTDRAW lpDD; //Deklarujemy obiekt DirectDraw
LPDIRECTDRAW4 lpDD4; //Deklarujemy obiekt DirectDraw4
LPDIRECTDRAWSURFACE4 lpDDSEkran; //Deklarujemy powierzchnię podstawową

HWND okno; //Deklarujemy okno do inicjalizacji programu

HDC kontekst; //Deklarujemy kontekst urządzenia

LRESULT CALLBACK PetlaKomunikatow(HWND, UINT, WPARAM, LPARAM);
//Deklarujemy funkcję 'PetlaKomunikatow" której użyjemy do przechwytywania zdarzeń

char klasa[] = "nazwa_klasy";
//Aby się nie powtarzać w dalszej części kodu, tworzymy sobie zmienną w której przechowujemy nazwę klasy okna

int WINAPI WinMain(HINSTANCE naszprogram, HINSTANCE, LPSTR, int tryb)
{

//WinMain to główna funkcja programu, uruchamiana razem z nim.
//W parametrze pierwszym (tzn. HINSTANCE naszprogram) deklarujemy instancję naszego programu.

WNDCLASS KlasaOkna;
KlasaOkna.lpszClassName = klasa;
KlasaOkna.hInstance = naszprogram;
KlasaOkna.lpfnWndProc = PetlaKomunikatow;
KlasaOkna.style = CS_OWNDC;
KlasaOkna.lpszMenuName = NULL;
KlasaOkna.hIcon = LoadIcon(NULL, IDI_WINLOGO);
KlasaOkna.hCursor = LoadCursor(NULL, IDC_ARROW);
KlasaOkna.hbrBackground = (HBRUSH)(COLOR_WINDOW + 2);
KlasaOkna.cbClsExtra = 0;
KlasaOkna.cbWndExtra = 0;
//Tu ustawiamy poszczególne parametry okna.

RegisterClass(&KlasaOkna);
//Rejestrujemy klasę okna (trzeba to zrobić)

okno = CreateWindow( klasa,
"Programowanie DirectX",
WS_EX_TOPMOST|WS_POPUP,
0,
0,
800,
600,
NULL,
NULL,
naszprogram,
NULL
);
//Używamy funkcji CreateWindow aby stworzyć okno programu...

ShowWindow(okno, tryb);
//...i wyświetlamy je na ekranie

/v/ Tutaj zaczyna się inicjalizacja DirectDraw! \v\

DirectDrawCreate(NULL, &lpDD, NULL); //Tworzymy obiekt DirectDraw o nazwie lpDD

lpDD->QueryInterface(IID_IDirectDraw4, (LPVOID *)&lpDD4);
//Pobieramy interfejs DirectDraw4 (aby wykorzystać możliwości DirectX'a od wersji 6.0)

lpDD->Release(); //Zwalniamy obiekt lpDD, bo nie będzie już potrzebny

lpDD4->SetCooperativeLevel(okno, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
//Ustawiamy tryb współpracy przed chwilą stworzonego obiektu lpDD4 z naszym programem

lpDD4->SetDisplayMode (800, 600, 16, 0, NULL); // Ustawiamy tryb pracy 800x600x16 bit

DDSURFACEDESC2 ddsd;
//Deklarujemy opis powierzchni na której będziemy wyświetlać grafikę

ZeroMemory(&ddsd, sizeof(ddsd));
//Zerujemy zakres pamięci wykorzystywany przez opis powierzchni ddsd

ddsd.dwSize = sizeof(ddsd);
//Ustawiamy właściwość .dwSize tak, żeby miała rozmiar opisu powierzchni ddsd

ddsd.dwFlags = DDSD_CAPS;
//Włączamy flagę mówiącą o tym, że wykorzystamy strukturę DDSD_CAPS

ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
//informujemy, że opis powierzchni ddsd odnosi się do powierzchni podstawowej

if (DD_OK==lpDD4->CreateSurface(&ddsd,&lpDDSEkran, NULL)) MessageBox(okno,

"Powierzchnia stworzona :)","Powierzchnia",MB_OK);

//Tworzymy powierzchnię podstawową lpDDSEkran z wykorzystaniem opisu powierzchni ddsd,
//następnie wyświetlamy komunikat jeśli operacja zakończy się sukcesem

HDC hdcmem;
HBITMAP hbmp;
//Deklarujemy kontekst 'hdcmem' oraz bitmapę 'hbmp'

hdcmem=CreateCompatibleDC(NULL);
//Ta linia kodu tworzy drugi kontekst, o takiej strukturze jak nasz podstawowy o nazwie 'kontekst'

hbmp=(HBITMAP)LoadImage(naszprogram, "tlo.bmp", IMAGE_BITMAP, 800, 600, LR_LOADFROMFILE);
//Ładowanie pliku 'tlo.bmp', rozciągnięcie go do rozmiaru 800x600 oraz zapamiętanie go w hbmp

SelectObject(hdcmem, hbmp); //Skopiowanie zawartości hbmp do kontekstu hdcmem

lpDDSEkran->GetDC(&kontekst); //Pobranie kontekstu urządzenia, aby dało się go za chwilę użyć

BitBlt(kontekst,0,0,800,600,hdcmem,0,0,SRCCOPY);
//Skopiowanie zawartości kontekstu 'hdcmem' do kontekstu 'kontekst' - czyli wyświetlenie obrazka

DeleteObject(hbmp); //Usunięcie obiektu 'hbmp', aby już nam nie przeszkadzał
DeleteDC(hdcmem); //Usunięcie kontekstu 'hdcmem' - nie będzie już potrzebny
lpDDSEkran->ReleaseDC(kontekst); //Zwolnienie głównego kontekstu

MSG komunikat;
for(;;)
{
if (PeekMessage(&komunikat,NULL,0,0,PM_REMOVE))
 {
 if (komunikat.message==WM_QUIT || komunikat.message==WM_KEYDOWN) break;

 TranslateMessage(&komunikat);
 DispatchMessage(&komunikat);
 }
} //To jest pętla komunikatów, dzięki której komputer reaguje na nasze polecenia

lpDDSEkran->Release();
lpDD4->RestoreDisplayMode();
lpDD4->Release();
//Zwolnienie powierzchni ekranu, przywrócenie trybu graficznego, zwolnienie obiektu lpDD4

return komunikat.wParam; //Wartość którą zwraca funkcja WinMain

} //Koniec funkcji WinMain

LRESULT CALLBACK PetlaKomunikatow (HWND okno, UINT komunikat, WPARAM wParam, LPARAM lParam)

{
switch (komunikat)
   {
  case WM_DESTROY:
    PostQuitMessage (0);
    break;

  default:
    return( DefWindowProc (okno, komunikat, wParam, lParam));
  }
return 0;
}
//Pętla komunikatów odpowiadająca na nasze reakcje


//====THE END czyli KONIEC====\\

\v/ (Stąd możesz skopiować kod bezpośrednio do edytora) \v/

\v/ (Tak wygląda efekt działania naszego programu) \v/

Zakończenie
Dzięki powyższemu kodowi zainicjalizowaliśmy i zwolniliśmy tryb DirectDraw. Myślę, że wyświetlenie bitmapy na ekranie po przejrzeniu tego arta nie będzie już stwarzało problemu. Już wkrótce następna część serii programowania z wykorzystaniem DirectX. Acha - program wymaga zainstalowanych bibliotek DirectX w wersji przynajmniej 5.0.

! Materiały wykorzystane w tym artykule: lekcja1.zip !

(c) 2001 by Game Design PL - http://www.warsztat.px.pl