Keyboard
Keyboard
adalah perangkat input utama untuk game berbasis PC, tetapi juga tersedia untuk
ponsel, beberapa konsol, dan perangkat sawit. Yang membuat mereka, kemungkinan
besar, perangkat input yang paling banyak tersedia. Sayangnya, seperti perangkat
input populer sangat tidak cocok untuk game. Pemetaan keyboard mengambil waktu untuk
belajar, dan gambaran umum tentang keyboard ini sama sekali tidak praktis untuk
anak-anak kecil. Menjadi multifungsi perangkat yang dapat digunakan untuk
mengetik dokumen dan untuk bermain game, tidak mengherankan bahwa keyboard
dapat dibaca dengan menggunakan berbagai metode, tergantung pada kebutuhan
spesifik dari aplikasi. Beberapa metode mengambil string penuh, yang lain
bekerja atas dasar kunci-demi-kunci, dan sebagainya. Tapi untuk tujuan game,
dua jenis rutinitas relevan. Pertama, ada rutinitas sinkron, yang menunggu sampai
tombol ditekan dan kemudian melaporkannya ke aplikasi. Kedua, ada rutinitas
asynchronous, yang segera kembali setelah dipanggil, dan memberikan informasi
tentang aplikasi yang tombol ditekan, jika ada.
Mode
membaca sinkron digunakan untuk mengetik informasi, seperti nama karakter dalam
role-playing game (RPG). Mereka bekerja dengan polling kontroler sampai pesan
input kunci baru tiba. Tapi mereka tidak sangat baik cocok untuk gameplay
nyata. Kode permainan harus terus menerus memeriksa untuk melihat apakah tombol
ditekan, dan apapun respon, terus menggambar, melaksanakan AI, dan sebagainya.
Jadi, pengendali asynchronous adalah cara untuk pergi. Mereka menyediakan tes
cepat untuk memeriksa keadaan keyboard yang efisien. Rutinitas Asynchronous
juga bisa milik dua keluarga yang berbeda. Beberapa dari mereka yang dirancang
untuk menguji keadaan kunci individu, sehingga pemrogram melewati kode kunci sebagai
parameter dan mendapat negara sebagai terjadi. Lainnya, seperti yang terpapar
oleh DirectInput, mengambil keyboard seluruh negara dalam satu panggilan,
sehingga programmer kemudian dapat mengakses struktur data dan memeriksa
keadaan setiap tombol tanpa lebih lanjut cek hardware. Tipe kedua rutin umumnya
lebih efisien karena ada overhead kurang
terlibat.
Sebagai
contoh, kita akan fokus pada panggilan asynchronous satu tombol untuk platform
PC. Panggilan adalah Windows spesifik dan merupakan bagian dari Win32 API.
Perintahnya adalah
pendek
GetAsyncKeyState (int keycode); Panggilan ini menerima kode kunci dan
mengembalikan nilai pendek, yang mengkode informasi negara yang berbeda.
Kuncinya kode kita lulus sebagai parameter dapat menjadi karakter dikapitalisasi,
seperti "K", atau kode kunci diperpanjang, yang digunakan untuk
membaca karakter khusus. Dengan menggunakan kode kunci diperpanjang, kita bisa membaca
kunci tertentu, seperti Hapus, tombol fungsi, Tabs, dan sebagainya. Tabel 5.1
menyediakan daftar kode kunci khusus utama untuk ini menelepon.
Tabel 5.1. Keycodes untuk panggilan
GetAsyncKeyState
Keycode
Deskripsi
VK_RSHIFT
VK_SHIFT, VK, LSHIFT Salah satu dari dua Shift
VK_MENU Salah
satu dari tombol Alt
VK_CTRL
VK_RCTRL, VK_LCTRL Setiap tombol Ctrl
VK_UP,
VK_DOWN, VK_LEFT, VK_RIGHT The tombol kursor
VK_F1 ...
VK_F12 Tombol Fungsi
VK_ESCAPE The
tombol Esc
VK_SPACE The
Spasi
VK_RETURN
Enter / Return
VK_HOME,
VK_END, VK_PRIOR, VK_NEXT Tombol keypad numerik
VK_BACK The
tombol Backspace
VK_TAB Kunci
Tab
VK_INSERT,
VK_DELETE Insert dan Delete
Nilai
kembali mengkodekan keadaan kunci dilewatkan sebagai parameter. Bit yang paling
signifikan diaktifkan jika tombol saat ditekan, sedangkan least significant bit
diaktifkan jika kunci ini diaktifkan yang terakhir Waktu GetAsyncKeyState
dipanggil. Berikut adalah contoh bagaimana untuk memeriksa apakah tombol Shift
kiri adalah ditekan:
Jika
(GetAsyncKeyState (VK_LSHIFT))
{
/
/ Apapun
}
Perhatikan
bahwa, karena sifat panggilan, kita dapat memeriksa beberapa tombol. Contoh
berikutnya menunjukkan bagaimana untuk menguji untuk Shift kiri DAN Kembali
kombinasi:
Jika
((GetAsyncKeyState (VK_LSHIFT)) && (GetAsyncKeyState (VK_RETURN)))
{
/
/ Apapun
}
Seperti
yang Anda lihat, setiap tes kunci memerlukan system call, yang dapat
menyusahkan bagi sistem-sistem memeriksabanyak kunci yang berbeda. Sekarang,
mari kita bandingkan panggilan ini dengan cek keyboard yang utuh, yang dapat
dilakukan dengan menggunakan panggilan:
bool
GetKeyboardState (PBYTE * lpKeyState);
Berikut
hasilnya hanya mengkodekan apakah fungsi berhasil, dan daging yang sebenarnya
dikembalikan sebagai array lulus sebagai referensi. Kemudian, pemeriksaan
berturut-turut seperti berikut ini melakukan tes individu, yang tidak lain array
lookup sederhana:
if (keystate
[VK_RSHIFT])
{
Pergeseran
/ / kanan ditekan
}
Sekali
lagi, untuk game yang memeriksa banyak kunci (seperti simulator penerbangan),
opsi ini bisa lebih baik daripada diulang panggilan ke GetAsyncKeyState.
Programmer hanya perlu menyadari bahwa panggilan awal untuk GetKeyboardState
diperlukan untuk memuat array. Lain yang mungkin perangkap untuk diperhatikan
adalah bahwa modus kedua ini tidak segera memeriksa kunci ketika Anda melakukan
tes. Tombol diperiksa pada panggilan untuk GetKeyboardState. Jika ada yang
signifikan menunda antara tes ini dan lookup array, efek samping yang tidak
diinginkan mungkin terjadi karena array akan mengandung "lama"
nilai-nilai kunci. Keyboard dengan DirectInput DirectInput menyediakan akses
asynchronous cepat untuk negara-negara kunci. Sebuah panggilan tunggal dapat
mengambil keadaan Seluruh Keyboard, tes berikutnya sehingga hanya tabel lookup.
Operasi ini demikian sangat mirip dengan GetKeyboardState Win32 menelepon.
Namun sebelum kita menggali ke dalam kode pembacaan Keyboard, kita perlu
membahas bagaimana DirectInput bekerja.
DirectInput
merangkum keyboard, joystick, tikus, dan setiap masukan eksotis lainnya perifer
bawah umum interface yang disebut perangkat. Operasi ini benar-benar mudah.
Pertama-tama kita perlu boot DirectInput. Ini menyiratkan menciptakan objek
DirectInput, dari mana semua benda lain yang berhubungan dengan proses input
dapat berasal. Obyek DirectInput demikian dapat digunakan untuk membuat
perangkat, yang merupakan antarmuka logis untuk peripheral. Setelah perangkat
telah dibuat, kita perlu menentukan beberapa parameter, seperti format data
yang kita inginkan untuk pertukaran dengan perangkat, dan tingkat koperasi, yang
memberitahu DirectInput jika perangkat untuk dibagi di antara aplikasi yang
berbeda atau jika kita perlu secara eksklusif. Perangkat DirectInput kemudian
dapat disurvei asynchronous. Kami query keadaan perangkat, tidak menunggu peristiwa
tertentu seperti kunci atau tekan tombol. Ini berarti DirectInput akan
mengambil snapshot dari kondisi saat ini perangkat dan mengembalikannya ke
aplikasi sehingga dapat diproses. Sebagai ringkasan, berikut adalah daftar
langkah-langkah terlibat dalam mendirikan keyboard DirectInput:
1. Membuat
objek DirectInput.
2. Buat
perangkat keyboard yang.
3. Mengatur
format data untuk membacanya.
4. Mengatur
tingkat koperasi akan Anda gunakan dengan sistem operasi.
5. Baca data yang diperlukan.
Mari
kita sekarang beralih ke contoh spesifik, dimulai dengan kode DirectInput
diperlukan untuk boot API. Itu kode dalam bagian ini telah diuji di kedua
DirectX8 dan DirectX9. DirectInput hampir identik dalam kedua versi.
LPDIRECTINPUT8
g_pDI = NULL;
HRESULT hr
= DirectInput8Create (GetModuleHandle (NULL), DIRCTINPUT_VERSION,
IID_IDirectInput8,
(VOID **) & g_pDI, NULL)))
Dalam
kode sebelumnya, parameter pertama digunakan untuk mengirim pegangan contoh
untuk aplikasi yang menciptakan objek DirectInput. Kemudian, kita harus lulus
versi DirectInput kita meminta. Itu makro DIRCTINPUT_VERSION adalah cara yang
berguna untuk lulus nomor versi saat ini. Selanjutnya, kita harus lulus pengenal
antarmuka yang unik untuk obyek yang kita minta. Kami menggunakan IID_IDirectInput8
untuk meminta DirectInput objek, tetapi kita bisa menggunakan parameter lain
untuk menentukan versi ANSI atau Unicode antarmuka. Kami kemudian melewati
pointer sehingga kami dapat menerima objek sudah diinisialisasi, dan parameter
terakhir digunakan untuk melakukan Component Object Model (COM) agregasi. Anda
mungkin tidak akan ingin agregat Anda Objek DirectInput untuk hal lain,
sehingga meninggalkan ini sebagai NULL.
Sekarang
kita memiliki objek DirectInput siap untuk digunakan. Sekarang saatnya untuk
kode keyboard nyata. Kami akan pertama meminta perangkat dan mengatur beberapa
parameter yang menentukan bagaimana kita akan berkomunikasi dengannya.
Kemudian, kita akan memeriksa kode sumber yang digunakan untuk membaca data
dari keyboard. Langkah pertama adalah untuk benar-benar meminta perangkat dari
objek DirectInput. Hal ini dicapai dengan kalimat:
HRESULT hr
= g_pDI-> CreateDevice (GUID_SYSKeyboard, & g_pKeyboard, NULL);
Panggilan
harus menerima Global Unique Identifier (GUID) untuk perangkat yang diinginkan.
DirectInput dibangun di atas dari COM, model pemrograman berorientasi obyek.
Dalam COM, GUIDs digunakan untuk mengidentifikasi objek tertentu atau interface.
Secara internal, GUID hanya struktur 128-bit, tetapi mereka digunakan untuk
mewakili fungsi, benda, dan umumnya setiap DirectX membangun. Dalam kasus ini,
GUIDs klasik untuk perangkat yang berbeda
●
GUID_SYSKeyboard: Keyboard sistem default.
●
GUID_SysMouse: Sistem tikus default.
GUID
tambahan dapat diberikan ke joystick. Namun, GUID ini tidak harus ditulis secara
langsung, tetapi sebagai hasil dari panggilan untuk DirectInput8 ::
EnumDevices. Kami akan mencakup joystick pada bagian berikutnya. Untuk keyboard
kita, GUID_SYSKeyboard akan melakukan pekerjaan. Parameter kedua adalah pointer
ke baru menciptakan perangkat, dan parameter terakhir ini lagi disediakan untuk
agregasi dan sehingga harus diatur ke NULL. Sekarang, kita harus memberitahu
keyboard bagaimana kita ingin bertukar data. Hal ini dicapai dengan panggilan
untuk SetDataFormat, seperti yang ditunjukkan di sini:
HRESULT
hr = g_pKeyboard-> SetDataFormat (& c_dfDIKeyboard);
Panggilan
harus menerima parameter tipe LPCDIDATAFORMAT, yang merupakan struktur
didefinisikan sebagai:
typedef
struct {DIDATAFORMAT
DWORD
dwSize;
DWORD
dwObjSize;
DWORD
dwFlags;
DWORD
dwDataSize;
DWORD
dwNumObjs;
LPDIOBJECTDATAFORMAT
rgodf;
}
DIDATAFORMAT, * LPDIDATAFORMAT;
typedef
const DIDATAFORMAT * LPCDIDATAFORMAT;
Struktur
ini mengontrol jumlah objek kita akan meminta, format masing-masing, dan
sebagainya. Karena struktur yang kompleks untuk mengisi, DirectInput sudah
dilengkapi dengan beberapa format data yang telah ditetapkan yang dapat kita
gunakan secara langsung. Untuk keyboard, c_dfDIKeyboard Format memberitahu
DirectInput kita akan meminta keyboard lengkap, disimpan dalam array dari 256
byte. Selain itu, kita perlu memberitahu DirectInput tentang tingkat koperasi
akan kita gunakan dengan perangkat ini. Ini dicapai dengan menggunakan garis:
HRESULT
hr = g_pKeyboard-> SetCooperativeLevel (hWnd, DISCL_FOREGROUND |
DISCL_EXCLUSIVE);
Di
sini kita melewati jendela menangani sebagai parameter pertama, dan parameter
kedua adalah ATAU dari serangkaian bendera yang mengontrol tingkat koperasi.
Dalam kasus ini, kita mengatakan DirectInput yang kita inginkan eksklusif mengakses
dan bahwa akses ini seharusnya hanya berlaku jika aplikasi tersebut di latar
depan. Sebagai aplikasi kita bergerak ke latar belakang, perangkat secara
otomatis unacquired. Selain itu, kami perlu mendapatkan keyboard, sehingga kami
dapat mulai query negaranya. Baris berikut akan melakukan bahwa bagi kita:
g_pKeyboard->
Acquire ();
Dan
sekarang kami siap untuk mulai menggunakan keyboard. Berikut adalah potongan
kode yang menyatakan kedua DirectInput dan keyboard, dan memastikan perangkat
siap. Kesalahan pemeriksaan telah dihilangkan untuk kejelasan:
HRESULT
jam;
hr
= DirectInput8Create (GetModuleHandle (NULL), DIRCTINPUT_VERSION,
IID_IDirectInput8,
(VOID **) & g_pDI, NULL);
hr
= g_pDI-> CreateDevice (GUID_SYSKeyboard, & g_pKeyboard, NULL);
hr
= g_pKeyboard-> SetDataFormat (& c_dfDIKeyboard);
hr
= g_pKeyboard-> SetCooperativeLevel (hDlg, dwCoopFlags);
hr
= g_pKeyboard-> Acquire ();
Membaca
keyboard bahkan lebih mudah daripada mempersiapkan itu. Yang harus kita lakukan
adalah mempersiapkan array 256-byte dan menyebarkannya ke DirectInput dengan
keyboard yang diperoleh untuk query negaranya:
Diks
BYTE [256]; / / keyboard DirectInput penyangga negara
ZeroMemory
(diks, sizeof (diks));
hr
= g_pKeyboard-> GetDeviceState (sizeof (diks), diks);
Perhatikan
bagaimana kita menghapus buffer dan kemudian menyebarkannya ke DirectInput.
Seperti GetAsyncKeyState, kunci tertentu Kode harus digunakan setelah membaca
query untuk setiap tombol. Dalam kasus ini, semua kunci yang diwakili oleh
simbolik konstanta, seperti:
DIK_RETURN
Kunci kembali
DIK_SPACE
Tombol spasi
DIK_A
... DIK_Z Tombol abjad
DIK_F1
... DIK_F10 Tombol Fungsi
Sekarang,
untuk query kunci tertentu, kita harus menguji bit yang paling signifikan dari
posisi array yang sesuai. Jika posisi yang diatur ke satu, kuncinya saat ini
sedang ditekan. Dengan demikian, untuk memeriksa apakah tombol Kembali adalah diaktifkan,
kode berikut dapat digunakan:
bool
return_pressed = (buffer [DIK_RETURN] & 0x80) = 0)!;
Seperti
biasa, kita bisa membaca kombinasi, sehingga kami dapat memeriksa apakah
beberapa tombol yang ditekan secara bersamaan. Karena hanya ada satu
DirectInput membaca di awal, ini hanya berbagai pencarian. Membaca keyboard
benar-benar mudah. Tapi kita harus berhati-hati dengan mendapatkan dan
unacquiring yang perangkat, yang dapat membuat kontroler masukan kami
kerusakan. Kadang-kadang, terutama pada beberapa tingkat kooperatif mode, kita
bisa kehilangan kontak dengan keyboard sesaat. Ini disebut unacquiring
perangkat. Yang paling alasan populer untuk ini adalah bahwa aplikasi kita
pindah ke latar belakang, sehingga kehilangan akses keyboard mendukung aplikasi
lain, yang sekarang di latar depan. Beberapa acara lain mungkin membuat kita
kehilangan jejak perangkat kami juga. Jika ini terjadi, kita akan menemukan
dalam panggilan GetDeviceState berikutnya, yang akan gagal. Kami kemudian harus
reacquire keyboard sehingga kami dapat terus query negaranya. Hal ini dicapai
sebagai berikut:
Diks
BYTE [256]; / / keyboard DirectInput penyangga negara
ZeroMemory
(diks, sizeof (diks));
hr
= g_pKeyboard-> GetDeviceState (sizeof (diks), diks);
if
(FAILED (jam))
{
hr
= g_pKeyboard-> Acquire ();
sementara
(hr == DIERR_INPUTLOST | | hr == DIERR_OTHERAPPHASPRIO)
hr
= g_pKeyboard-> Acquire ();
}
Perhatikan
bagaimana kita mendeteksi kesalahan dan terus menelepon Memperoleh sampai kita
memperoleh kembali akses ke perangkat. Setelah kami selesai dengan aplikasi
kita, saatnya untuk melepaskan semua objek DirectInput damai. Melepaskan keyboard
adalah proses dua langkah. Pertama, kita unacquire perangkat, kemudian lepaskan
struktur datanya. Kedua, kita harus menghapus obyek DirectInput utama. Secara
keseluruhan, urutan kehancuran dicapai dengan menggunakan kode berikut:
if
(g_pKeyboard) g_pKeyboard-> Unacquire ();
SAFE_RELEASE
(g_pKeyboard);
SAFE_RELEASE
(g_pDI);
Perhatikan
bahwa kita menggunakan macro SAFE_RELEASE disediakan dengan DirectX untuk memastikan
bahwa semua struktur data dan memori yang dialokasikan akan dihapus.
Mouse
Sejak
awal mereka pada akhir 1960-an sebagai perangkat input CAD, tikus telah disesuaikan
untuk banyak kegunaan termasuk game komputer. Mereka sangat populer di game PC,
tapi game konsol biasanya tidak mendukung mereka. Tidak seperti keyboard atau
joystick, mouse tidak hanya menghasilkan tombol atau tombol yang ditekan, tapi
2D posisi juga. Ini menyediakan pilihan yang lebih banyak masukan pada biaya
kurva belajar yang lebih tinggi untuk pemain.
Tikus
dapat digunakan dalam berbagai skenario, dari unit memetik dalam judul strategi
real-time untuk populer mouselook ditemukan di sebagian besar penembak orang
pertama. Dalam semua kasus, pengoperasian mouse dapat dibagi menjadi transmisi
informasi posisional (berkat sensor tikus internal) dan mengirim tekan tombol
dan pesan rilis. Mari kita periksa bagaimana mouse beroperasi di bawah
DirectInput. Kode sumber ini sangat mirip dengan keyboard meminta karena
DirectInput memperlakukan semua perangkat yang sama. Hal ini menguntungkan bagi
programmer karena rincian paling dalam yang tersembunyi. Mari kita asumsikan
kita memiliki objek DirectInput utama dan berjalan, dan mulai dengan penciptaan
perangkat lulus:
LPDIRECTINPUTDEVICE
g_pMouse;
HRESULT
jam;
hr
= g_pDI-> CreateDevice (GUID_SysMouse, & g_pMouse, NULL);
Seperti
yang Anda lihat, sangat mirip dengan meminta keyboard, satu-satunya perbedaan
menjadi GUID kami lulus untuk meminta perangkat yang diinginkan. Kemudian,
format data diatur sebagai berikut:
hr
= g_pMouse-> SetDataFormat (& c_dfDIMouse);
Dalam
hal ini, parameter c_dfDIMouse memberitahu DirectInput kita akan melewati
struktur DIMOUSESTATE ke IDirectInputDevice :: GetDeviceState. Struktur ini
memiliki tanda tangan berikut:
typedef
struct {DIMOUSESTATE
LONG
lX;
LY
PANJANG;
LONG
lZ;
RgbButtons
BYTE [4];
}
DIMOUSESTATE, * LPDIMOUSESTATE;
Struktur
ini mengembalikan X dan posisi Y, dan Z sumbu opsional, yang biasanya
ditugaskan untuk roda. Kemudian, tombol array bekerja seperti array Keyboard.
Tombol ditekan jika bit high-order diatur. A varian dari struktur ini adalah
DIMOUSESTATE2, ditetapkan oleh c_dfDIMouse2 parameter. Satu-satunya perbedaan
adalah bahwa yang terakhir mendukung delapan tombol bukannya empat didukung oleh
DIMOUSESTATE. Ini terutama berguna dalam tikus tertentu yang digunakan untuk
sistem CAD, misalnya. Setelah format data telah ditetapkan, kita perlu mengatur
level kooperatif. Tidak ada kejutan di sini, karena kode tersebut persis sama
dengan versi Keyboard:
hr
= g_pMouse-> SetCooperativeLevel (hWnd,
DISCL_EXCLUSIVE
| DISCL_FOREGROUND);
Selain
itu, kita perlu untuk mendapatkan siap menggunakan perangkat dengan baris:
g_pMouse->
Acquire ();
Berikut
adalah kode sumber penuh di review:
LPDIRECTINPUTDEVICE
g_pMouse;
HRESULT
hr = g_pDI-> CreateDevice (GUID_SysMouse, & g_pMouse, NULL);
hr
= g_pMouse-> SetDataFormat (& c_dfDIMouse);
hr
= g_pMouse-> SetCooperativeLevel (hWnd,
DISCL_EXCLUSIVE
| DISCL_FOREGROUND);
g_pMouse->
Acquire ();
Membaca
dari mouse ini dicapai dengan panggilan GetDeviceState, yang akan mengembalikan
LPDIMOUSESTATE struktur. Kode sumber akan:
DIMOUSESTATE
dims; / / DirectInput ketatanegaraan tikus
ZeroMemory
(& meredup, sizeof (meredup));
hr
= g_pMouse-> GetDeviceState (sizeof (DIMOUSESTATE), & meredup);
if
(FAILED (jam))
{
hr
= g_pMouse-> Acquire ();
sementara
(hr
== DIERR_INPUTLOST | | hr == DIERR_OTHERAPPHASPRIO | |
hr
== DIERR_NOTACQUIRED)
hr
= g_pMouse-> Acquire ();
}
Perhatikan
bagaimana saya telah menambahkan kode pencegahan unacquiring untuk menghindari
kehilangan jejak mouse kita karena kejadian tak terduga. Selain itu, kode ini
sangat mirip dengan membaca keyboard. Untuk mengakses mouse atribut, yang harus
kita lakukan adalah:
int
MouseX = dims.lX;
int
mousey = dims.lY;
bool
lbutton = (dims.rgbButtons [0] & 0x80) = 0)!;
Biasanya,
tombol 0 ditugaskan untuk tombol kiri mouse, tombol 1 ditugaskan untuk orang yang
tepat, dan tombol 2 adalah ditugaskan untuk tombol tengah (jika tersedia).
Mengenai posisi, ingat bahwa mouse adalah relatif perangkat penunjuk. Ketika
pertama kali diperoleh, posisi mouse adalah ulang ke (0,0). Kemudian, masing-masing
membaca baru akan kembali perpindahan dari yang terakhir. Jadi, jika kita
menggerakkan mouse vertikal, kita akan melihat perpindahan dalam Y arah. Tetapi
ketika kita menghentikan gerakan, nilai tikus membaca akan kembali ke (0,0).
Ingat, mouse tidak bekerja dengan posisi melainkan bekerja dengan perpindahan.
Terakhir, but not least, mouse biasanya dikonfigurasi poin X begitu negatif ke
kiri, dan titik Y positif menjauh dari tubuh kita seperti kita duduk di meja.
Selain
itu, ingatlah untuk melepaskan mouse segera setelah Anda selesai
menggunakannya. Kode ini lagi sangat mirip dengan kode rilis Keyboard:
if
(g_pMouse) g_pMouse-> Unacquire ();
SAFE_RELEASE
(g_pMouse);
SAFE_RELEASE
(g_pDI);
Mouselook
Sebuah
penggunaan populer dari mouse adalah untuk menerapkan mouselook klasik yang
digunakan dalam banyak penembak orang pertama. Itu mouselook mudah untuk kode
setelah Anda memahami bagaimana mouse beroperasi. Yang harus kita lakukan
adalah menggunakan kunci mengubah posisi kami, dan menggunakan mouse untuk
reorientasi sudut pandang kita. Saya akan menjelaskan efek sepenuhnya, sehingga
kita bisa menggabungkan apa yang telah kita pelajari tentang keyboard dan
mouse. Permainan harus memiliki setidaknya empat derajat kebebasan. Kita harus
memiliki posisi yang terdiri dari X dan Z nilai, dan kemudian yaw dan sudut
lapangan. Nilai Y sering ditambahkan ke dalam campuran sehingga kita dapat
mendaki berbeda ketinggian, tapi gulungan umumnya tidak diperlukan. Kami akan
menggunakan pemetaan berikut:
●
Tikus: Mouselook
●
Panah kiri: memberondong kiri
●
Panah kanan: memberondong tepat
●
Panah: Maju
●
Panah bawah: Mundur
Mari
kita fokus pertama pada keyboard dan melupakan orientasi kedua. Dengan asumsi
standar DirectInput Keyboard, kita akan membutuhkan kode berikut untuk
menerapkan perilaku yang diinginkan:
int
memberondong = (buffer [DIK_RIGHT] & 0x80) = 0) - (buffer [DIK_LEFT] &
0x80) = 0)!;
!
int fwd = (buffer [DIK_UP] & 0x80) = 0) - (buffer [DIK_DOWN] & 0x80) =
0)!;
Perhatikan
bagaimana kita telah elegan dikemas kontrol kursor. Dengan mengurangi arah yang
berlawanan, kita mendapatkan dua nomor, memberondong dan fwd, dalam kisaran -1
.. 1. Jumlah ini kemudian digunakan untuk menggerakkan posisi kami memperbarui
rutin:
pos.x + = fwd
* FWDSPEED * berlalu * cos (yaw) +
memberondong
* STRAFESPEED * berlalu * cos (yaw 3,1416 / 2);
pos.z + = fwd
* FWDSPEED * berlalu * sin (yaw) +
memberondong
* STRAFESPEED * berlalu * sin (yaw 3,1416 / 2);
The
fwd dan memberondong variabel mengontrol bagaimana masing-masing anggota
dikalikan dengan -1-, 0, atau 1-untuk melakukan yang diinginkan efek. Sekarang,
mari kita merawat lapangan dan yaw melalui mouse:
yaw + =
YAWSPEED * berlalu * dims.lX;
lapangan + =
PITCHSPEED * berlalu * dims.lY;
Jadi
sekarang kita memiliki pos.x baru kami, pos.z, yaw, dan struktur pemain lapangan
diperbarui. Jelas, kita perlu menjaga dua perangkat hidup, dan kita perlu mendefinisikan
semua konstanta dalam topi untuk mengatur kecepatan yang diinginkan. Perhatikan
bagaimana setiap konstan dikalikan dengan faktor waktu berlalu, yang menyimpan
waktu yang dibutuhkan untuk membuat frame terakhir. Dengan cara ini kita
memastikan perangkat-independen kinerja. Untuk kelengkapan, di sini adalah
source code yang diperlukan untuk menghitung semua parameter kamera spesifik
siap untuk dipasang ke OpenGL atau DirectX pipa:
Titik campos (pos.x,
pos.y, pos.z);
Titik camlookat (pos.x +
cos (yaw) * cos (pitch), pos.y + sin (pitch),
pos.z + sin (yaw) * cos
(pitch));
The
lookat perhitungan koordinat hanya pemetaan bola menggunakan pitch dan yaw.
Tergantung pada bagaimana kapak Anda ditata, tanda mungkin berubah atau Anda
mungkin perlu menambahkan sudut konstan seperti Pi ke lapangan nilai-nilai.
0 komentar:
Posting Komentar