Recent Comments

counter



Free web hostingWeb hosting

Bab V. Tombol Dan In-Game Menu

Download BAB5-Tombol Dan In-Game Menu.zip (2.47 MB)

In-game menu, adalah bagian dari game yang terdiri atas beberapa tombol dan berinteraksi dengan pemain melalui alat input (keyboard maupun mouse) untuk mengarahkan pemain menuju sub-bagian dari game loop. Umumnya aplikasi game memiliki in-game menu yang berfungsi untuk berbagai hal dari memulai sebuah game baru (new game), loading game yang tersimpan (load game), pengaturan / konfigurasi game (game options) hingga menu untuk keluar dari game (quit game), seperti tampak pada gambar di bawah. Pada bab ini Anda akan mempelajari pembuatan tombol dengan menggunakan sprite.

image002

5.1 Menggerakkan kursor mouse

Pada bab sebelumnya, Anda telah melakukan pembuatan sebuah sprite yang ditujukan sebagai kursor mouse. Namun, Anda belum dapat menggerakkan kursor mouse tersebut karena Anda belum membuat fungsi yang memeriksa penekanan tombol dan pergerakan mouse sedangkan device mouse telah Anda buat melalui perintah

DirectInput->CreateDevice(GUID_SysMouse, &DIDeviceMouse, NULL)

Sebuah mouse umumnya terdiri atas 3 tombol (tombol kiri, tombol tengah yang beroda, tombol kanan). Pergerakkannya pun dapat dianggap berada pada sumbu x, y dan z. Perhatikan gambar mouse di bawah ini :

image003

Di pasaran, sebuah mouse pasti memiliki tombol kiri dan tombol kanan tetapi belum tentu memiliki tombol tengah yang beroda (wheel). Ada juga yang memiliki tombol tengah yang tidak beroda. Untuk menggunakan device mouse, Anda panggil perintah Acquire dan kemudian menyimpan data penekanan dan pergerakan mouse pada struktur DIMOUSESTATE melalui perintah GetDeviceState.

typedef struct DIMOUSESTATE { LONG lX;

LONG lY;

LONG lZ;

BYTE rgbButtons[4];

} DIMOUSESTATE, *LPDIMOUSESTATE;

Variabel lX, lY dan lZ digunakan untuk menyimpan pergerakan mouse. Nilai variabel tersebut akan berisi 0, 1 dan -1. Bila bernilai 0, mouse diartikan tidak bergerak pada sumbu tersebut, bila bernilai 1, mouse diartikan sedang bergerak ke kanan(X+) / atas(Y+) / maju(Z+) dan bila bernilai -1, mouse diartikan sedang bergerak ke kiri(X-) / bawah(Y-) / mundur(Z-). Array rgbButtons menentukan apakah tombol-tombol mouse ditekan(di klik) atau tidak.

Struktur DIMOUSESTATE ini menganggap terdapat maksimal empat tombol pada mouse. Walaupun saya belum pernah menggunakan tombol keempat, tetapi saya pernah melihat sebuah mouse dengan tombol keempat pada sisi mouse. Tombol rgbButtons[0] adalah tombol kiri mouse, rgbButtons[1] adalah tombol kanan mouse, rgbButtons[2] adalah tombol tengah mouse dan rgbButtons[3] adalah tombol keempat mouse yang, mungkin, terletak di sisi mouse. Perintah Acquire dan GetDeviceState dilakukan setiap frame di dalam game loop.

Untuk keyboard, sama seperti mouse yang harus di cek setiap frame penekanan tombolnya bila ingin digunakan di dalam game. Namun, data penekanan tombol keyboard disimpan dalam array sebanyak 256 buah. Untuk memudahkan programmer, DirectInput telah mendefinisikan ulang isi array tersebut agar mudah diingat. Contohnya nilai array 0×01 adalah DIK_ESCAPE (tombol ESC), 0×02 adalah DIK_1 (angka 1), 0×1E adalah DIK_A (huruf A), dsb. Untuk melihat keseluruhan definisi tersebut, lihat dokumentasi DirectX tentang “Keyboard Device Enumerated Type”.

Agar device keyboard dan mouse dapat digunakan di dalam game, tiap device harus memeriksa apakah terjadi penekanan tombol atau tidak. Bila terjadi penekanan tombol, maka ambil data tombol apa yang ditekan oleh pemain. Karena dimungkinkan device keyboard maupun mouse digunakan oleh aplikasi lain, maka Anda harus terus memanggil perintah Acquire sebelum mengambil state dari device. Fungsi AmbilMasukan() berikut akan melakukan tugas tersebut. Fungsi ini akan terus dipanggil sebelum proses render dilakukan. Ketikkan fungsi ini di dalam file “Gameku.cpp”.

VOID AmbilMasukan(){

if (FAILED(DIDeviceKeyboard->Acquire())) { DIDeviceKeyboard->Acquire();}

else

{

DIDeviceKeyboard->GetDeviceState(sizeof(TombolYangDitekan),

(LPVOID)&TombolYangDitekan);

}

if (FAILED(DIDeviceMouse->Acquire())) { DIDeviceKeyboard->Acquire();}

else

{

DIDeviceMouse->GetDeviceState( sizeof(DIMOUSESTATE), &mouse_state );

}

}

VOID Render()

{

AmbilMasukan();

Direct3DDevice -> Clear (0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,

D3DCOLOR_XRGB(0,0,0),1.0f,0);

Direct3DDevice -> Present(NULL,NULL,NULL,NULL);

}

Sekarang Anda akan membuat fungsi untuk menggerakkan kursor mouse. Umumnya kursor mouse adalah sprite 2D, walaupun dimungkinkan untuk menggunakan obyek 3D sebagai kursor mouse. Pada bab ini, Anda hanya menggunakan sprite 2D sebagai kursor mouse. Oleh karena itu, Anda hanya membutuhkan pergerakan mouse pada sumbu X dan sumbu Z saja. Ketikkan kode yang ditebalkan berikut di dalam file “DirectXku.h” :

char TextPembuka[JumTeks][256];char temptext[256];

float fPosKursorX, fPosKursorY;

VOID UpdateKursorMouse(float LebarJendela, float TinggiJendela)

{

fPosKursorX += mouse_state.lX;

fPosKursorY += mouse_state.lY;

if (fPosKursorX<0) { fPosKursorX = 0;}

if (fPosKursorY<0) { fPosKursorY = 0;}

if (fPosKursorX>LebarJendela) { fPosKursorX = LebarJendela;}

if (fPosKursorY>TinggiJendela) { fPosKursorY = TinggiJendela;}

}

Dan ketikkan kode yang ditebalkan berikut di dalam file “Gameku.cpp” :

VOID Render(){

AmbilMasukan();

UpdateKursorMouse(640.0f,480.0f);

Direct3DDevice -> Clear (0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,

D3DCOLOR_XRGB(0,0,0),1.0f,0);

Direct3DDevice -> BeginScene();

spSplashScreen.RenderSprite(Direct3DDevice,0,0);

spKursorMouse.RenderSprite(Direct3DDevice,PosKursorX,PosKursorY);

Direct3DDevice -> EndScene();

Direct3DDevice -> Present(NULL,NULL,NULL,NULL);

}

Dua variabel yang menyimpan posisi kursor mouse pada sumbu X dan Y adalah fPosKursorX dan fPosKursorY. Nilai variabel tersebut akan bertambah satu bila mouse bergeser ke kanan (X) atau ke atas (Y). Begitu pula sebaliknya. Agar posisi kursor tidak melebihi ukuran jendela maka perlu ditetapkan batas-batas pergerakan kursor mouse.

Fungsi UpdateKursorMouse() dipanggil di dalam fungsi Render(). Kemudian nilai dari PosKursorX dan PosKursorY digunakan oleh spKursorMouse sebagai posisi penempatan obyek sprite tersebut.

Tidak sulit bukan ? Sekarang build aplikasi Anda. Dan perhatikan apa yang terjadi dengan kursor mouse pada saat Anda menggerakkan mouse.

5.2 Membuat Tombol

Anda akan membuat tombol dari beberapa sprite yang menyatakan keadaan ketika kursor mouse berada di atas tombol, tidak berada di atas tombol, dan ketika tombol ditekan.

image004 (over)keadaan ketika kursor mouse berada di atas tombol

file : tombolover.png 131×43pixel

image005 (off)keadaan ketika kursor mouse tidak berada di atas tombol

file : tomboloff.png 131×43pixel

image006 (on)keadaan ketika tombol di klik

file : tombolon.png 131×43pixel

Karena Tombol sebenarnya adalah tiga buah sprite berukuran sama yang dalam proses render hanya salah satu dari ketiga sprite tersebut yang digambar, maka sebelum mendeklarasikan sebuah tombol, Anda perlu melakukan inisialisasi ketiga sprite tersebut. Variabel-variabel dan fungsi-fungsi yang dibutuhkan adalah sebagai berikut, ketik di dalam file “DirectKu.h” :

class Tombol{

public :

float fPosX;

float fPosY;

int iLebar;

int iTinggi;

ObyekSprite* spTomOff;

ObyekSprite* spTomOn;

ObyekSprite* spTomOver;

bool bTombolOn;

bool bTombolOver;

bool bTombolUp;

VOID Init(ObyekSprite* TomOff, ObyekSprite* TomOn, ObyekSprite* TomOver);

VOID RenderDanCekStatusTombol(LPDIRECT3DDEVICE9 m_pd3dDevice);

};

Variabel / Fungsi

Keterangan

float fPosX, fPosY

Posisi tombol relatif terhadap kiri atas layar

int iLebar,iTinggi

Ukuran tombol

ObyekSprite*

spTomOff, spTomOn, spTomOver

Pointer ke obyek sprite yang dibutuhkan sebagai kondisi tombol off, on dan over

bool bTombolOn

Bernilai TRUE bila tombol diklik

bool bTombolOver

Bernilai TRUE bila kursor berada di atas mouse

Bernilai FALSE bila kursor tidak berada di atas mouse

bool bTombolUp

Bernilai TRUE bila tombol kiri mouse telah selesai ditekan, berguna untuk Tombol yang hanya sekali diklik saja

VOID Tombol::Init(ObyekSprite* TomOff, ObyekSprite* TomOn, ObyekSprite* TomOver ){

if (TomOff == NULL || TomOn == NULL || TomOver == NULL)

{

MessageBox(NULL,”Salah satu sprite untuk tombol belum diinisialisasikan”,

NULL,MB_OK);

}

else

{

spTomOff = TomOff; spTomOn = TomOn; spTomOver = TomOver;

iLebar = spTomOff->SpriteInfo.Width;

iTinggi = spTomOff->SpriteInfo.Height;

}

}

Fungsi Tombol::Init() hanya melakukan penunjukkan pada obyek sprite yang digunakan sebagai penampakan kondisi-kondisi Tombol. Di dalam fungsi ini juga dilakukan penentuan ukuran Tombol, yang pada awalnya ditentukan oleh ukuran sprite spTomOff. Jadi sebaiknya, gunakanlah ukuran sprite yang sama untuk tiap-tiap kondisi Tombol.

VOID Tombol::RenderDanCekStatusTombol(LPDIRECT3DDEVICE9 m_pd3dDevice){

if ((fPosKursorX > fPosX)&&(fPosKursorX <fPosX + iLebar)

&&(fPosKursorY > fPosY)&&(fPosKursorY < fPosY + iTinggi))

{

bTombolOver = TRUE; bTombolUp = FALSE;

if (mouse_state.rgbButtons[0])

{

bTombolOn = TRUE;

}

}

else

{

bTombolOver = FALSE;bTombolUp = FALSE;bTombolOn= FALSE;

}

if ((mouse_state.rgbButtons[0]==0)&&(bTombolOn==TRUE))

{

bTombolUp = TRUE;bTombolOn = FALSE;

}

if ((bTombolOn == TRUE))

{

spTomOn->RenderSprite(m_pd3dDevice,fPosX,fPosY);

}

if ((bTombolOn == FALSE)&&(bTombolOver == TRUE))

{

spTomOver->RenderSprite(m_pd3dDevice,fPosX,fPosY);

}

if ((bTombolOn == FALSE)&&(bTombolOver == FALSE))

{

spTomOff->RenderSprite(m_pd3dDevice,fPosX,fPosY);

}

}

Fungsi Tombol::RenderDanCekStatusTombol() akan memeriksa posisi kursor mouse pada layar dan penekanan mouse, dan kemudian mengubah status tombol berdasarkan posisi kursor mouse dan penekanan mouse tersebut, apakah kursor mouse sedang berada di atas tombol (bTombolOver = TRUE), tombol sedang ditekan (bTombolOn = TRUE) atau tombol selesai ditekan (bTombolUp = TRUE). Setelah menentukan status tombol, Tombol::RenderDanCekStatusTombol() akan menentukan sprite yang mana yang harus ditampilkan.

5.3 Menggunakan Class Tombol

Class Tombol diatas membutuhkan tiga buah sprite, oleh karena itu hal yang perlu Anda lakukan adalah inisialisasi sprite-sprite tersebut. Saya akan memberi contoh penggunaan dua buah tombol. Dua buah tombol tersebut menggunakan sprite-sprite yang sama untuk menghemat memori. Pendeklarasian dilakukan seperti biasa yaitu :

ObyekSprite spTombolOff;ObyekSprite spTombolOn;

ObyekSprite spTombolOver;

Kemudian dilanjutkan dengan inisialisasi sprite-sprite tersebut saat aplikasi game pertama kali dijalankan.

VOID InitObyekGame(){

spTombolOff.InisialisasiSprite(Direct3DDevice,”bitmap/tomboloff.png”);

spTombolOn.InisialisasiSprite(Direct3DDevice,”bitmap/tombolon.png”);

spTombolOver.InisialisasiSprite(Direct3DDevice,”bitmap/tombolover.png”);

spTombolOff.bPNGAlpha = spTombolOn.bPNGAlpha = spTombolOver.bPNGAlpha = TRUE;

}

Dan juga penghapusan sprite dari ruang memori bila aplikasi game dihentikan.

VOID HapusObyekGame(){

spTombolOff.HapusSprite();

spTombolOn.HapusSprite();

spTombolOver.HapusSprite();

}

Bila pada penggunaan sprite bukan tombol, Anda mungkin sudah menuliskan perintah untuk penggambaran sprite di dalam fungsi Render(). Namun untuk penggunaan sprite tombol, proses penggambaran sprite tombol dilakukan oleh fungsi Tombol::RenderDanCekStatusTombol().

Deklarasikan dua buah tombol, satu untuk memulai permainan dan yang lain untuk menghentikan aplikasi.

Tombol tomMulai;Tombol tomKeluar;

Inisialisasikan kedua buah tombol tersebut agar menggunakan tiga buah sprite.

VOID InitObyekGame(){

spTombolOff.bPNGAlpha = spTombolOn.bPNGAlpha = spTombolOver.bPNGAlpha = TRUE;

tomMulai.Init(&spTombolOff,&spTombolOn,&spTombolOver);

tomKeluar.Init(&spTombolOff,&spTombolOn,&spTombolOver);

}

Kini kedua tombol Anda telah siap digunakan. Perhatikan pada fungsi Render(). Ketik kode tebal di bawah ini :

VOID Render(){

spSplashScreen.RenderSprite(Direct3DDevice,0,0);

tomMulai.fPosX = 425.0f; tomMulai.fPosY = 150.0f;

tomMulai.RenderDanCekStatusTombol(Direct3DDevice);

RenderTeks(”MULAI”, 450, 165, D3DCOLOR_XRGB(255,255,255));

if (tomMulai.bTombolOn == TRUE)

{

RenderTeks(”tomMulai Ditekan…”, 0, 0, D3DCOLOR_XRGB(255,255,255));

}

tomKeluar.fPosX = 450.0f; tomKeluar.fPosY = 190.0f;

tomKeluar.RenderDanCekStatusTombol(Direct3DDevice);

RenderTeks(”KELUAR”, 475, 205, D3DCOLOR_XRGB(255,255,255));

if (tomKeluar.bTombolUp)

{

bKeluar = TRUE;

}

spKursorMouse.RenderSprite(Direct3DDevice,fPosKursorX,fPosKursorY);

}

Untuk tomMulai, posisinya pada layar adalah (425,150). Di atas tombol tersebut digambar teks “MULAI” pada posisi (450, 165). Untuk tomKeluar, posisinya pada layar adalah (450,190). Di atas tombol tersebut digambar teks “KELUAR” pada posisi (475, 205). Bila mouse ditekan pada tomMulai, status tombol bTombolOn pada tomMulai menjadi TRUE, maka aplikasi akan menampilkan teks “tomMulai Ditekan…”. Bila mouse ditekan pada tomKeluar dan kemudian mouse tidak ditekan lagi, status tombol bTombolUp pada tomKeluar menjadi TRUE, maka aplikasi akan merubah nilai bKeluar menjadi TRUE yang berarti aplikasi dihentikan.

Perhatikan, bahwa penggambaran tombol-tombol dilakukan setelah penggambaran spSplashScreen dan sebelum penggambaran spKursorMouse. Anda harus memperhatikan urutan penggambaran obyek sprite pada back-buffer. Sprite yang berada paling belakang digambar paling awal, dalam kasus ini adalah spSplashScreen, dan sprite yang berada paling depan digambar paling akhir, dalam kasus ini adalah spKursorMouse.

Build dan jalankan aplikasi Anda. Dua gambar di bawah menunjukkan kondisi ketika kursor mouse sedang berada di atas salah satu tombol dan ketika salah satu tombol terus ditekan.

image007

ketika kursor mouse menekan sebuah tombol

image008

ketika kursor mouse di atas sebuah tombol

Perhatikan bahwa ketika tombol MULAI terus ditekan, teks “tomMulai Ditekan” terus ditampilkan. Sedangkan pada tombol KELUAR, ketika tombol KELUAR selesai ditekan, aplikasi akan dihentikan. Itulah perbedaan penggunaan status tombol, bahwa bTombolOn digunakan untuk tombol yang terus ditekan sedangkan bTombolUp digunakan untuk tombol yang sekali ditekan.

Dua tombol tersebut menunjukkan bahwa Anda telah membuat in-game menu yang berfungsi untuk mengarahkan pemain agar memulai permainan atau menghentikan aplikasi.

5.4 FAQ (Frequently Asked Questions)

Semoga FAQ ini dapat membantu Anda bila mendapat kesulitan…

Tanya : Mouse ?

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.

Leave a Reply

 

 

 

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>