Bab IV. Sprite 2D
Download BAB4-Sprite.zip (1.24 MB)
Pada bab ini, kita akan mempelajari mengenai sprite. Sprite sebagai komponen sebuah game, sangatlah penting untuk dipelajari. Didalam sebuah game, sprite dapat digunakan untuk splash-screen (layar pembuka), HUD (heads-up display), kursor mouse, maupun sebagai tombol bertekstur. Bab ini merupakan lanjutan dari bab sebelumnya, dimana source-code dari bab sebelumnya akan ditambahkan dengan kode-kode untuk pembuatan dan penggunaan sprite.
Jalankan VisualC++ dan buka file “Gameku.dsw” pada folder “\BAB4-Sprite\sebelum”. Hapus fungsi GameLoop() di dalam file “Gameku.cpp”.
4.1 Sprite 2D
Pada DirectX versi 8 ke atas, DirectDraw tidak digunakan lagi untuk penggambaran obyek dua dimensi. Fungsi untuk melakukan hal tersebut telah diambil alih oleh DirectXGraphics. Walaupun DirectX memiliki interface sendiri untuk proses penggambaran sprite pada layar, yaitu ID3DXSPRITE, namun saya tidak menggunakan interface tersebut di dalam bab ini. Mengapa? Karena dengan membuat class sprite sendiri, Anda dapat belajar tentang loading bitmap untuk tekstur, mengerti tentang penggunaan vertex di dalam pembuatan polygon dan proses penggambaran polygon beserta teksturnya pada back buffer.
![]()
Perhatikan gambar di atas. Dalam pembuatan sprite, Anda membutuhkan empat buah vertex untuk membuat sebuah bujur sangkar. Bujur sangkar tersebut kemudian “diisi” dengan tekstur bergambar. Lebar dan tinggi bujur sangkar dibuat sama seperti lebar dan tinggi tekstur.
Dengan menggunakan metode Triangle Strips yang ada pada DirectX, Anda dapat membuat sebuah bujur sangkar dari dua buah polygon yang dibentuk oleh empat buah vertex. Polygon pertama dibentuk oleh vertex0, vertex1 dan vertex2. Polygon kedua dibentuk oleh vertex1, vertex2 dan vertex3.
Setiap vertex membutuhkan data posisi, warna, koordinat UV dan FVF yang digunakan. Anda pasti sudah mengerti maksud posisi dan warna vertex, tapi apa itu UV dan FVF. UV adalah koordinat tekstur yang menentukan bagaimana tekstur “ditempelkan” ke polygon (Lihat Dokumentasi DirectX mengenai Texture Wrapping), sedangkan FVF (Flexible Vertex Format) adalah format vertex untuk memberitahukan kepada sistem render bagaimana DirectX akan me-render vertex tersebut (Lihat Dokumentasi DirectX mengenai D3DFVF).
Posisi, warna, UV dan FVF vertex pembentuk sprite dinyatakan dalam sebuah struktur, yaitu SPRITEVERTEX. Ketikkan kode-kode yang ditebalkan dibawah ini untuk membuat struktur SPRITEVERTEX.
| VOID HapusSemuaObyekDirectX() { … } struct SPRITEVERTEX |
DirectX memiliki berbagai FVF yang dapat digunakan. Tetapi penggunaan FVF perlu memperhatikan kemampuan kartu grafik saat memproses vertex-vertex dengan format tersebut. Untuk sprite, Anda hanya memerlukan tiga buah format saja yaitu D3DFVF_XYZRHW, D3DFVF_DIFFUSE dan D3DFVF_TEX1. Berikut keterangannya :
1. D3DFVF_XYZRHW
Posisi vertex dapat ditransformasikan.
2. D3DFVF_DIFFUSE
Menggunakan komponen warna.
3. D3DFVF_TEX1
Menggunakan tekstur koordinat nomor 1.
Sekarang Anda akan membuat sebuah class yang mewakili penggunaan sprite dalam aplikasi DirectX Anda. Ketikkan kode di bawah ini :
| class ObyekSprite { public : LPDIRECT3DVERTEXBUFFER9 SpriteVB; LPDIRECT3DTEXTURE9 TeksturSprite; D3DXIMAGE_INFO SpriteInfo; SPRITEVERTEX* vSpriteVertex; bool bPNGAlpha; HRESULT InisialisasiSprite(LPDIRECT3DDEVICE9 m_pd3dDevice,LPCTSTR NamaFileBMP); |
Dua interface DirectX digunakan yaitu IDirect3DVertexBuffer9 (ditunjuk oleh variabel SpriteVB) dan IDirect3DTexture9 (ditunjuk oleh variabel TeksturSprite). Struktur D3DXIMAGE_INFO digunakan untuk mengambil informasi bitmap sebagai tekstur sprite. Struktur SPRITEVERTEX telah dijelaskan sebelumnya. Variabel bPNGAlpha, digunakan untuk menentukan apakah tekstur sprite memiliki transparansi (format PNG) atau tidak memiliki transparansi (format BMP). Fungsi InisialisasiSprite akan melakukan tugas inisialisasi sprite dimana parameter yang diperlukan adalah device Direct3D dan nama file bitmap tekstur sprite.
| HRESULT ObyekSprite::InisialisasiSprite(LPDIRECT3DDEVICE9 m_pd3dDevice, LPCTSTR NamaFileBMP) { //buat vertex buffer if( FAILED( m_pd3dDevice->CreateVertexBuffer( 4*sizeof(SPRITEVERTEX), D3DUSAGE_WRITEONLY, SPRITEVERTEX::FVF, D3DPOOL_MANAGED, &SpriteVB, NULL ) ) ) { sprintf(temptext,”Gagal : Vertex Buffer Untuk \”%s\”.”, NamaFileBMP); MessageBox(NULL,temptext,NULL,MB_OK); return E_FAIL; } else { // jika berhasil membuat vertex buffer, load bitmap untuk tekstur if (FAILED(D3DXCreateTextureFromFileEx( m_pd3dDevice, NamaFileBMP, 0, 0, 0, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, D3DCOLOR_XRGB(0,0,0), NULL, NULL, &TeksturSprite ))) { sprintf(temptext,”Gagal : Loading Bitmap \”%s\”.”, NamaFileBMP); MessageBox(NULL,temptext,NULL,MB_OK); return E_FAIL; } else { // jika berhasil load bitmap, ambil informasi tentang bitmap tersebut D3DXGetImageInfoFromFile(NamaFileBMP, &SpriteInfo); } } bPNGAlpha = FALSE; return S_OK; } |
Hal yang pertama Anda lakukan pada fungsi InisialisasiSprite() adalah membuat vertex buffer. Apa itu vertex buffer ? Vertex buffer adalah ruang memori yang menyimpan informasi vertex. Device Direct3D membuat vertex buffer melalui perintah CreateVertexBuffer. Berikut keterangan pengisian parameter perintah CreateVertexBuffer pada kode di atas:
|
No |
Isi |
Keterangan |
|
1 |
4*sizeof(SPRITEVERTEX) |
Karena hanya dibutuhkan empat vertex, maka besar vertex buffer adalah empat kali ukuran struktur SPRITEVERTEX. |
|
2 |
D3DUSAGE_WRITEONLY |
Vertex buffer hanya akan ditulisi. Lihat Dokumentasi DirectX mengenai D3DUSAGE. |
|
3 |
SPRITEVERTEX::FVF |
Format vertex untuk vertex buffer ini adalah fvf pada struktur SPRITEVERTEX |
|
4 |
D3DPOOL_MANAGED |
Vertex Buffer diletakkan di memori sistem komputer. Lihat Dokumentasi DirectX mengenai D3DPOOL. |
|
5 |
&SpriteVB |
Representasi vertex buffer yang akan dibuat. |
|
6 |
NULL |
Tidak digunakan lagi. Isi dengan NULL. |
Bila vertex buffer berhasil dibuat, hal berikutnya adalah membuat tekstur sprite. Tekstur dibuat dari file bitmap melalui perintah D3DXCreateTextureFromFileEx. Perintah ini memiliki parameter yang cukup banyak untuk dijelaskan. Lihat dokumentasi DirectX tentang perintah tersebut.
Bila Vertex buffer dan tekstur telah berhasil dibuat di memori, hal berikutnya adalah mengambil informasi tekstur, kita memerlukan informasi panjang dan tinggi tekstur untuk menentukan panjang dan tinggi bujur sangkar.
Ketikkan kode berikut ini untuk membuat fungsi RenderSprite:
| VOID ObyekSprite::RenderSprite(LPDIRECT3DDEVICE9 m_pd3dDevice,float PosX, float PosY) { SpriteVB->Lock( 0, 0, (void**)&vSpriteVertex, 0 ); for( UINT i=0; i<4; i ++ ) { vSpriteVertex[i].p = D3DXVECTOR4( 0.0f, 0.0f, 0.9f, 1.0f ); vSpriteVertex[i].color = 0xffffffff; } // vertex 0 di kiri bawah vSpriteVertex[0].p.x = PosX; vSpriteVertex[0].p.y = PosY+SpriteInfo.Height; // vertex 1 di kiri atas vSpriteVertex[1].p.x = PosX; vSpriteVertex[1].p.y = PosY; // vertex 2 di kanan bawah vSpriteVertex[2].p.x = PosX+SpriteInfo.Width; vSpriteVertex[2].p.y = PosY+SpriteInfo.Height; // vertex 3 di kanan atas vSpriteVertex[3].p.x = PosX+SpriteInfo.Width; vSpriteVertex[3].p.y = PosY; //uv vSpriteVertex[0].tu = 0.0f; vSpriteVertex[0].tv = 1.0f; vSpriteVertex[1].tu = 0.0f; vSpriteVertex[1].tv = 0.0f; vSpriteVertex[2].tu = 1.0f; vSpriteVertex[2].tv = 1.0f; vSpriteVertex[3].tu = 1.0f; vSpriteVertex[3].tv = 0.0f; SpriteVB->Unlock(); m_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE ); m_pd3dDevice->SetTexture( 0, TeksturSprite ); m_pd3dDevice->SetRenderState( D3DRS_LIGHTING, TRUE ); |
Hmm… cukup panjang ya… sekarang udah hampir jam 3 pagi. Ngantuk juga nih… huammm… Dikarenakan fungsi ObyekSprite::RenderSprite() dapat menggambar sprite pada posisi yang diinginkan, maka setiap fungsi ini dipanggil, Anda perlu menentukan kembali posisi-posisi vertex pada layar monitor berdasarkan posisi sprite (PosX,PosY) terhadap kiri atas window. Posisi kiri atas sprite, yaitu vertex1, adalah posisi acuan penempatan sprite (Lihat Gambar). Dari gambar dapat dilihat bahwa posisi X vertex0 adalah PosX, posisi Y vertex0 adalah PosY+SpriteInfo.Height. Begitupula dengan posisi vertex-vertex lainnya. Perlu diingat, sebelum memindahkan posisi vertex di dalam vertex buffer, Anda diharuskan mengunci vertex buffer dengan perintah Lock.
![]()
Perhatikan kode-kode berikut :
| m_pd3dDevice->SetTexture( 0, TeksturSprite ); m_pd3dDevice->SetFVF( SPRITEVERTEX::FVF ); m_pd3dDevice->SetStreamSource( 0, SpriteVB, 0, sizeof(SPRITEVERTEX) ); m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP , 0, 2 ); |
Sebelum sprite digambar ke back buffer dengan perintah DrawPrimitive, Anda diharuskan memberitahu kepada device bahwa tekstur yang digunakan adalah TeksturSprite, FVF yang digunakan adalah SPRITEVERTEX::FVF, dan vertex buffer yang digunakan adalah SpriteVB.
Sprite 2D tidak membutuhkan penggunaan cahaya(light) dan kabut (fog), kecuali sprite 3D atau yang biasa disebut billboard. Bila tekstur sprite memiliki transparansi, maka D3DRS_ALPHABLENDENABLE di-set TRUE agar dapat menggunakan transparansi tersebut.
Dan fungsi ObyekSprite yang terakhir adalah ObyekSprite::HapusSprite().
| VOID ObyekSprite::HapusSprite() { if (SpriteVB!=NULL) { SpriteVB->Release(); SpriteVB = NULL;} if (TeksturSprite!=NULL) { TeksturSprite->Release(); TeksturSprite = NULL;} } |
4.2 Menggunakan Class ObyekSprite
Bagaimana cara menggunakan class ObyekSprite yang telah Anda buat bila Anda memiliki sebuah file BMP sebagai splash-screen dan sebuah file PNG sebagai kursor mouse?
![]()
bitmap\splashscreen.bmp,
640×480 pixel
Tidak ada transparansi
![]()
bitmap\kursor.png
20×20 pixel
Memiliki transparansi alpha
Bukalah file “Gameku.cpp”. Hal pertama yang harus Anda lakukan untuk menggunakan dua bitmap di atas sebagai sprite adalah mendeklarasikan dua variabel bertipe ObyekSprite. Kemudian di dalam fungsi InitObyekGame(), gunakan perintah ObyekSprite::InisialisasiSprite() dengan memasukkan nama file bitmap di atas pada parameter kedua dari tiap-tiap ObyekSprite. Atur nilai bPNGAlpha pada sprite kursor mouse agar bernilai TRUE. Di dalam fungsi HapusObyekGame(), gunakan perintah ObyekSprite::HapusSprite(). Kemudian di dalam fungsi Render(), gunakan perintah ObyekSprite::HapusSprite() untuk menggambar sprite pada back buffer. Ketikkan kode-kode dibawah ini untuk melakukan menggunakan ObyekSprite.
| #include <windows.h> #include “DirectXku.h” bool bKeluar = FALSE; ObyekSprite spSplashScreen; VOID InitObyekGame() VOID HapusObyekGame() VOID Render() spSplashScreen.RenderSprite(Direct3DDevice,0,0); Direct3DDevice -> EndScene(); |
Pada fungsi Render() di atas, terlihat bahwa sebelum penggambaran ObyekSprite dilakukan, back buffer harus dibersihkan terlebih dahulu dengan perintah Clear (0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,0),1.0f,0). Kemudian proses penggambaran ObyekSprite dilakukan di antara perintah BeginScene dan EndScene. Back Buffer ditampilkan ke layar monitor dengan perintah Present(NULL,NULL,NULL,NULL). Tidak terlalu rumit bukan ?
Compile dan Build aplikasi Anda. Berikut adalah gambar tampilan aplikasi Anda bila dijalankan.
![]()
Perhatikan sprite kursor mouse (gambar panah berwarna merah), amati bahwa Anda telah menggunakan transparansi untuk menggambar sprite tersebut. Kursor tersebut belum dapat Anda gerakkan, pada bab berikutnya Anda akan mempelajari tentang hal tersebut dan sekaligus membuat tombol dan in-game menu.
Selamat !!! Anda telah dapat membuat dan menggambar sprite. Sebenarnya masih banyak fitur dari sprite yang dapat kita buat. Contohnya penggunaan sprite beranimasi, mengatur transparansi, menampilkan sprite untuk beberapa frame saja, sprite dengan skew dan merubah warna difuse sprite untuk pemain berbeda. Di lain waktu dan kesempatan, saya akan mencoba membuat tutorial lain untuk menguprade fitur-fitur sprite yang Anda buat pada bab ini.
4.3 FAQ (Frequently Asked Questions)
Semoga FAQ ini dapat membantu Anda bila mendapat kesulitan…
Tanya : Mengapa pada saat aplikasi melakukan inisialisasi sprite, muncul kotak pesan “Gagal : Vertex Buffer Untuk “Splash.BMP”. Mungkin memori penuh?” ?
Jawab : Karena pada fungsi ObyekSprite::InisialisasiSprite(), digunakan D3DPOOL_MANAGED untuk membuat vertex buffer, maka DirectX mengatur secara otomatis, apakah vertex buffer akan dibuat pada memori sistem atau memori kartu grafik. Kegagalan tersebut terjadi karena salah satu atau kedua memori tersebut telah penuh.
Tanya : Mengapa pada saat aplikasi melakukan inisialisasi sprite, muncul kotak pesan “Gagal : Loading Bitmap “Splash.BMP”.” ?
Jawab : Kegagalan tersebut terjadi karena aplikasi tidak dapat menemukan file “Splash.BMP” atau dapat juga terjadi karena memori sistem atau memori kartu grafik telah penuh.



Recent Comments