Game yang berjalan pada platform yang
mendukung berbagai kontroler masukan menawarkan pengalaman gaming
terkaya. Ini adalah kasus tidak hanya dengan PC (yang menggunakan
keyboard, mouse, dan joystick), tetapi juga dengan sebagian besar konsol
game melalui perangkat eksotis. Dalam beberapa tahun terakhir, kami telah
menggunakan standar controller, pesawat-gaya joystick, snowboards,
bantalan tarian segala macam, dan bahkan pancing! Ada dua jalur pengembang
mungkin mengikuti ketika coding untuk platform tersebut. Beberapa game akan
memilih untuk menggunakan satu (dan hanya satu) dari pengendali yang ada.
Hal ini terjadi di sebagian besar game strategi, yang untuk alasan
gameplay biasanya dikodekan dengan mouse PC dalam pikiran. Di sisi lain,
beberapa permainan lain akan membiarkan pengguna memilih metode input yang
dia inginkan untuk mempekerjakan. Aksi game untuk PC sering dapat bermain
dengan keyboard, joystick, gamepad, dan bahkan kadang-kadang mouse. Meskipun baik
untuk pemain, itu datang pada biaya rumit kode penanganan masukan
signifikan, dan ini adalah persis di mana hardware abstraksi menjadi
masalah. Dengan abstraksi perangkat keras, maksud saya coding permainan
dengan "virtual" controller dalam pikiran, sehingga setiap controller
yang sesuai dengan profil abstrak dapat dipasang ke dalam kode dengan nol
dampak pada mesin permainan. semua Anda perlu Anda lakukan adalah menulis
kontroler handler generik (biasanya, sebuah kelas abstrak murni) yang
spesifik pengendali berasal melalui warisan. Kemudian, pada saat runtime,
hanya jenis kontroler dipilih oleh pemain adalah dibuat, menyediakan cara
halus dan elegan mengintegrasikan kontroler yang berbeda.
Figure 5.3 shows
how this class structure would work out.
Perhatikan bagaimana,
demi kejelasan, saya telah membuat sebuah kontroler global yang sangat
menyerupai sebuah game konsol. Ini memiliki dua kontroler arah dan empat
tombol. Input ini kemudian dapat dipetakan ke keyboard (menggunakan tombol
untuk pilihan yang berbeda), sebuah joystick analog, atau joystick digital.
Satu-satunya barang kita perlu diwaspadai adalah kepekaan yang berbeda
ditemukan di tombol dan tongkat. Sebuah kunci dapat ditekan atau dilepaskan, sehingga
hanya membutuhkan nilai biner, sedangkan joystick mungkin akan memetakan ke
satu set terus menerus. Dengan demikian, beberapa kode diskritisasi akan
diminta untuk menawarkan output standar. Sebuah alternatif yang lebih baik jika
Anda menggunakan DirectInput adalah untuk mengambil keuntungan dari pemetaan
tindakan, yang memungkinkan perangkat Anda untuk kembali tidak nilai-nilai
negara tertentu tetapi berorientasi pada nilai permainan. Kita dapat menetapkan
aktivitas perangkat untuk acara permainan, sehingga controller masukan akan
menerima nilai-nilai yang entah bagaimana perangkat independen. Untuk Misalnya,
kita dapat memiliki joystick dan menetapkan gerakan pada sumbu X ke "muka
kiri" tindakan. kita bisa kemudian menetapkan tombol khusus untuk acara
yang sama, sehingga kode kontrol input menjadi independen perangkat. Kita dapat
mengubah perangkat, dan sebagai kontrol yang menerima pesan abstrak, semuanya
akan tetap bekerja. Pemetaan tindakan tidak sulit untuk mendapatkan bekerja di
bawah DirectInput, meskipun kode terlalu panjang untuk menjadi rinci di sini.
Langkah pertama adalah menentukan tindakan dalam permainan kami:
enum GAME_ACTIONS {
WALK,
WALK_LEFT,
WALK_RIGHT,
JUMP
QUIT
};
Kemudian, kita harus menyediakan peta tindakan yang berkaitan sumbu dan tombol atau kunci untuk tindakan yang berbeda:
DIACTION g_adiaActionMap[] =
{
// Joystick input mappings
{ WALK, DIAXIS_FIGHTINGH_LATERAL, 0,
ACTION_NAMES[WALK], },
{ JUMP, DIBUTTON_FIGHTINGH_JUMP, 0,
ACTION_NAMES[JUMP], },
// Keyboard input mappings
{ WALK_LEFT, DIKEYBOARD_LEFT, 0,
ACTION_NAMES[WALK_LEFT], },
{ WALK_RIGHT, DIKEYBOARD_RIGHT, 0,
ACTION_NAMES[WALK_RIGHT], },
{ JUMP, DIKEYBOARD_J, 0, ACTION_NAMES[JUMP],
},
{ QUIT, DIKEYBOARD_Q, DIA_APPFIXED,
ACTION_NAMES[QUIT], },
// Mouse input mappings
{ WALK, DIMOUSE_XAXIS, 0, ACTION_NAMES[WALK],
},
{ JUMP, DIMOUSE_BUTTON0, 0, ACTION_NAMES[JUMP],
},
};
Inisialisasi sistem
input akan sangat mirip dengan contoh sebelumnya. Semua kita perlu lakukan
adalah menghitung semua perangkat input didukung oleh peta tindakan. Hal ini
akan dicapai dengan panggilan untuk EnumerateDevicesBySemantics, yang akan
menerima peta tindakan dan membutuhkan callback di mana semua perangkat mungkin
akan dikembalikan. Callback kemudian harus membangun peta tindakan untuk itu
spesifik perangkat. Setelah itu dibersihkan, panggilan membaca berikutnya akan
kembali perangkat-data spesifik, seperti berikut contoh:
hr = pdidDevice->Poll();
hr = pdidDevice->GetDeviceData(
sizeof(DIDEVICEOBJECTDATA),
rgdod, &dwItems, 0 );
for( DWORD j=0; j<dwItems; j++ )
{
UINT_PTR dwAction = rgdod[j].uAppData;
switch( dwAction )
{
case WALK:
(...)
}
}
Perhatikan bahwa
GetDeviceData mengembalikan daftar tindakan, sehingga kami dapat memproses
beberapa tombol atau kunci dalam lingkaran yang sama.