Kombinasi kunci pada input berbasis jajak pendapat

9

Jadi anggap Anda memiliki sistem input yang didasarkan pada polling

void update()
{
    if( Keyboard[ 'A' ] )
        // A is down
}

Katakanlah Anda ingin dapat mengenali 3 hingga 8 kombinasi tombol panjang (seperti turun, turun-maju, maju, A untuk hado-ken)

Bagaimana cara terbaik Anda membuat sistem input kombinasi tombol generik (mudah dimodifikasi / diprogram) pada input yang disurvei ?

bobobobo
sumber

Jawaban:

7

Pada dasarnya, Anda tidak bisa . Kombinasi kunci memerlukan pemesanan, dan pemesanan membutuhkan acara.

Apa yang dapat Anda lakukan adalah mengubah pemungutan suara menjadi peristiwa dengan membandingkan status kunci setiap frame dan menghasilkan peristiwa keyup / keydown pasca-hoc dari perbedaan. Ini tidak dapat diandalkan karena Anda kehilangan timestamping dan pemesanan intra-frame lainnya yang disediakan oleh sistem acara "asli", tetapi itu akan memungkinkan Anda untuk mendeteksi dan memesan setidaknya satu kunci per frame.

Setelah Anda memesan acara tersebut, Anda dapat menggunakan mesin keadaan terbatas atau alat lain untuk mencocokkannya dengan daftar langkah Anda dan menjalankan yang benar.


sumber
Agak menyesatkan untuk mengatakan bahwa Anda tidak dapat melakukan ini tanpa kejadian. Secara teknis, peristiwa hanyalah cara untuk memanggil metode atau daftar metode ketika beberapa kondisi terpenuhi. Dalam hal itu, Anda perlu acara. Namun, saya dapat menerapkan kata kejadian (tidak benar) pada banyak tugas pemrograman yang sesuai dengan deskripsi itu. Saya telah menambahkan jawaban yang memecahkan masalah dengan cara yang biasanya saya lakukan, yang tidak menggunakan apa yang cenderung dipikirkan oleh kebanyakan programmer sebagai "peristiwa".
Olhovsky
2
Kode Anda melakukan persis apa yang saya katakan harus dilakukan tanpa peristiwa, tetapi mengabaikan peringatan - yang berarti bahwa Anda kehilangan pemesanan intra-frame. Ketika Anda mendapatkan acara dari misal loop pesan Win32, Anda mendapatkannya dalam urutan dengan lebih banyak rincian daripada gumpalan per bingkai. Ketika Anda menghitung delta sendiri, Anda kehilangan itu. Untuk gim pertarungan di mana pemain dapat memasukkan beberapa bagian dari kombo dalam satu frame, Anda perlu tahu apakah itu tidak benar atau salah.
Cukup adil. Asalkan kami melakukan polling pada 60Hz, saya ragu kami ingin membedakan antara mesin press yang jaraknya kurang dari 16ms yang disediakan oleh polling 60Hz (dengan asumsi pemain kami adalah manusia).
Olhovsky
Kami lakukan. Pemain game yang trampil dapat memasukkan perintah tongkat hadouken / shoryuken dalam waktu kurang dari tiga frame, artinya kita harus membedakan di antara mereka.
Maka Anda perlu melakukan polling lebih dari 60 hz.
Olhovsky
3

Salah satu caranya adalah menyimpan status input saat ini dan sebelumnya, dan membandingkannya setiap kali Anda polling input.

Untuk setiap tombol yang dapat ditekan, simpan objek yang memiliki stempel waktu terakhir kali bahwa tombol tersebut beralih dari keadaan turun ke keadaan naik.

Perbarui objek-objek ini dengan melakukan ini di setiap jajak pendapat:

void update(){
    some_key_has_been_pressed = false;
    foreach(key in keys){
        if(previous_input[key].Down && current_input[key].Up){
            keys[key].up_timestamp = current_time();
        }

        if(current_input[key].Down){
            keys[key].down_timestamp = current_time();
            some_key_has_been_pressed = true;
        }
    }
}

Sekarang Anda dapat mencocokkan pola kombo Anda dengan konten keys.

Memiliki objek kombo untuk setiap kombo, dan panggilan pembaruan () pada setiap objek kombo di setiap jajak pendapat.

Metode pembaruan objek kombo () akan berpola sesuai dengan kombo, memeriksa apakah semua kondisi yang diperlukan untuk kombo puas pada jajak pendapat ini. Yaitu semua cap waktu tombol untuk kombo sejauh ini dalam urutan, dan tidak ada tombol lain yang akan merusak kombo telah menekan bingkai ini. Untuk setiap kondisi yang dipenuhi, tambahkan penghitung di objek kombo ke kondisi berikutnya untuk diperiksa. Ketika semua kondisi dipenuhi dalam sebuah kombo, panggil metode yang kombo harus lakukan. Jika some_key_has_been_pressed == truetetapi tombol yang merupakan kondisi berikutnya untuk kombo belum ditekan, maka setel ulang penghitung kondisi puas kombo ke 0.

Di atas adalah metode yang saya sukai, karena mudah diimplementasikan, mudah dipelihara, efisien, dan sangat modular.

Namun untuk metode lain yang bagus, periksa sampel urutan input XNA , yang ditulis dalam C #, dan logikanya kemungkinan ditransfer ke bahasa yang Anda gunakan.

Olhovsky
sumber
Dalam pernyataan if kedua if(current_input[key].down){,, tidakkah Anda juga ingin memeriksa apakah kunci di previous_inputnegara bagian? Seperti yang tertulis, saya pikir itu akan terus memperbarui kunci yang ditahan down_timestamp.
webdevkit
Terus memperbarui cap waktu turun adalah perilaku yang dimaksud. Ini memungkinkan Anda untuk membandingkan up_timestamp dan down_timestamp dari sembarang tombol, untuk memeriksa berapa lama ditahan. Jika Anda terus-menerus memegang kunci, Anda tidak mengubah up_timestamp, jadi (down_timestamp - up_timestamp) masih memberi Anda durasi waktu ditahan.
Olhovsky
terimakasih atas klarifikasinya. Saya berpikir sebaliknya, di mana up_timestamp - down_timestamp adalah durasi kunci yang ditahan.
webdevkit
1

Buat tumpukan peristiwa kunci X terakhir, untuk setiap peristiwa kunci tambahkan objek dengan tombol dan waktu pers / lepaskan, lalu periksa apakah anggota terakhir tumpukan cocok dengan pola khusus dan jika tombol itu cukup cepat ditekan untuk dihitung sebagai kombinasi. Akhirnya, hapus objek tertua dari tumpukan.

aaaaaaaaaaaa
sumber
2
Tumpukan yang dapat Anda hapus dari objek bawah sebenarnya bukan tumpukan;)
Olhovsky
Sekumpulan entitas data yang dipesan, daftar mungkin istilah yang benar.
aaaaaaaaaaaa
deque;) O (1) enq / deq ftw.
michael.bartnett
3
Urutan berurutan di mana objek diletakkan di satu ujung dan dihapus dari yang lain paling tepat disebut antrian .
1
Anda dapat membuat buffer-cincin (BufferLength> = perintah terpanjang) dan menulis kunci untuk itu (Posisi = Nomor MOD BufferLength). Tidak ada penambahan / penghapusan yang diperlukan sama sekali
Kromster