Bagaimana cara mendapatkan waktu penekanan tombol yang telah terlewati?


8

Saya harus dapat menentukan berapa lama kunci telah ditekan dengan akurasi tinggi. Misalnya, jika tombol yang diketuk sangat cepat dapat melaporkan waktu yang kurang dari waktu untuk setiap bingkai pembaruan.


Berdasarkan komentar Anda yang lain, saya harus bertanya, apakah akurasi ~ 16ms sebenarnya merugikan game Anda? Hampir setiap game yang pernah saya lakukan tidak terganggu dengan input pada skala sub-frame. Mungkin ada beberapa hal lain yang menyebabkan permainan terasa buruk (yang saya asumsikan memang demikian, jika tidak, mengapa Anda bertanya?)
Tetrad

1
Anda tahu, game Mario tidak membutuhkan akurasi sub-frame untuk melakukan "tab cepat untuk lompat rendah, pers penuh untuk lompat tinggi". Lebih baik menambahkan vektor percepatan untuk 2-3 frame pertama lompatan.
Kyte


@Andrew Russel: itu seharusnya jawabannya.
Michael Coleman

Jawaban:


4

Anda bisa menangkap input dengan menggunakan kelas System.Windows.Forms.NativeWindow. Anda akan mendapatkan notifikasi ketika suatu peristiwa input terjadi. Dengan begitu Anda akan diberitahu secepat mungkin tepat saat itu terjadi, memungkinkan Anda merekam waktu dengan presisi yang lebih tinggi. Itu menjadi agak berantakan (kode asli / tidak aman), tetapi berfungsi.

Saya pikir ini hanya bekerja di windows, tapi saya pikir itu adalah platform penargetan Anda (tidak perlu untuk ini di Xbox dan WP7).

Berikut ini adalah contoh yang baik (dari nuclex framework): WindowInputCapturer (catatan: kode ini mungkin telah diperbarui baru-baru ini dan saya tidak mengkodekannya)

Sunting: Ini juga memungkinkan Anda untuk mendapatkan kode karakter dari tombol yang ditekan. Ini bisa berguna untuk mengambil input teks (terutama hal-hal seperti karakter latin) Saya tidak yakin mengapa Anda perlu mendapatkan input dengan ketelitian yang tinggi, tetapi ini akan menjadi cara yang baik untuk melakukannya menurut pendapat saya.


2

XNA adalah kerangka kerja berbasis loop, bukan kerangka kerja berbasis peristiwa. Jika Anda membutuhkan waktu yang tepat suatu peristiwa terjadi, pertimbangkan proyek winforms (proyek berbasis peristiwa) dan sambungkan XNA ke kontrol jika perlu untuk rendering.


1

Simpan status kunci ke dalam variabel dan bandingkan pada loop berikutnya dengan status kunci saat ini. Buat DateTimeobjek untuk menahan awal dan Anda dapat membandingkan dengan DateTime.Nowketika kondisi kunci sebelumnya tidak cocok.

Contoh yang sangat sederhana tentang apa yang saya maksud:

   if(currentKeyboardState.IsKeyDown(Keys.Space)
      && !previousKeyboardState.IsKeyDown(Key.Space))
      { DateTime startTime = DateTime.Now; }
    ...
    if(!currentKeyboardState.IsKeyDown(Keys.Space)
      && previousKeyboardState.IsKeyDown(Key.Space))
      { TimeSpan elapsedTime = DateTime.Now - startTime; }

Saya secara khusus meminta sesuatu yang dapat memberi saya waktu yang kurang dari waktu untuk setiap pembaruan. Jawaban Anda hanya akan memberi saya waktu dengan peningkatan 16ms.
AttackingHobo

1
Jadi jalankan itu di utasnya sendiri. XNA tidak memiliki pengendali acara untuk perubahan keyboard.
riv_rec

DateTime.Now memiliki resolusi lebih buruk daripada pembaruan. Coba Stopwatch.
Kyte

0

Saya tidak mengetahui adanya cara resmi untuk melakukan ini, Anda dapat menjalankan utas kedua dalam loop yang sangat ketat hanya untuk memeriksa input dan mengirimkannya ke buffer bundar yang cukup besar sehingga memerlukan sedikit sinkronisasi antara utas.

(Simpan beberapa jenis angka yang meningkat di setiap slot buffer dan perbarui bahwa SETELAH utas menulis semua data, kemudian lanjutkan membaca slot dengan data dari buffer hingga jumlahnya berkurang (jangan lupa memeriksa jumlah yang melimpah!))


0

Jika Anda memperbarui tiga puluh kali per detik, manusia tidak akan dapat menekan tombol lebih cepat daripada Anda dapat mencicipi kondisi keyboard. Jika Anda memperbarui lebih lambat dari yang dapat diketik manusia, maka Anda mungkin perlu satu utas untuk merender gambar, dan utas lainnya untuk membaca dan merespons keyboard / mouse.

Tetapi, jika Anda memperbarui lebih lambat dari yang dapat diketik manusia, maka Anda tidak dapat memberikan umpan balik visual untuk setiap penekanan tombol. Ini tidak masalah jika idenya adalah untuk menampilkan umpan balik agregat, seperti waktu rata-rata di antara penekanan tombol.


Saya tidak pernah mengatakan apa pun tentang mengetik. Saya ingin tahu waktu tombol telah ditekan, milidetik yang tepat.
AttackingHobo

Dan sebenarnya manusia dapat mengetik dengan kecepatan lebih dari 30 kunci per detik tetapi hanya dalam ledakan beberapa kunci, bukan kecepatan berkelanjutan.
AttackingHobo

Jika Anda memperbarui enam puluh kali per detik, Anda mendapatkan akurasi hingga 16 ms. Akurasi apa yang Anda butuhkan, dan mengapa?
bmcnett

Untuk pergerakan pemain, saya ingin pengguna dapat mengetuk sekali dengan cepat dan meminta pemain untuk bergerak kurang dari 1 tekan penuh.
AttackingHobo

@AttackingHobo Bisakah Anda memanfaatkan persamaan gerak untuk ini? Sementara itu ditekan menerapkan vektor percepatan ke vektor kecepatan? Semakin lama ditahan, semakin tinggi kecepatannya?
Ray Dey
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.