Klavye giriş sistemi kullanımı


13

Not: API sınırlamaları (SFML) nedeniyle geri arama yapmak yerine anket yapmak zorundayım. Ayrıca 'iyi' bir unvanın olmaması nedeniyle özür dilerim.

Sanırım burada iki sorum var; aldığım girişin nasıl kaydedileceği ve ne yapılacağı.

İşleme Girişi

Örneğin, 'A' tuşuna basıldığını ve oradan nasıl yapılacağını kaydettikten sonra bahsediyorum.

Bütün klavye bir dizi gördüm, gibi bir şey:

bool keyboard[256]; //And each input loop check the state of every key on the keyboard

Ama bu verimsiz görünüyor. Örneğin, sadece 'A' anahtarını 'sola hareket eden oyuncuya' bağlamakla kalmaz, aynı zamanda saniyede 30-60 kez her anahtarı kontrol eder.

Daha sonra istediği anahtarları arayan başka bir sistemi denedim.

std::map< unsigned char, Key> keyMap; //Key stores the keycode, and whether it's been pressed. Then, I declare a load of const unsigned char called 'Quit' or 'PlayerLeft'.
input->BindKey(Keys::PlayerLeft, KeyCode::A); //so now you can check if PlayerLeft, rather than if A.

Ancak, bununla ilgili sorun, şimdi her bir anahtarı bağlamak zorunda kalmadan bir ad yazamıyorum.

Sonra, gerçekten iyi bir çözüm düşünemiyorum ikinci sorun var:

Girdi Gönderme

Artık A tuşuna basıldığını veya playerLeft'in doğru olduğunu biliyorum. Ama buradan nasıl gideceğim?

Sadece kontrol if(input->IsKeyDown(Key::PlayerLeft) { player.MoveLeft(); }
etmeyi düşündüm Bu, girişleri büyük ölçüde çiftler ve oldukça dağınık buluyorum. Güncellendiğinde oyuncunun kendi hareketini yapmasını tercih ederim. Bir tür olay sisteminin çalışabileceğini düşündüm, ancak bununla nasıl başa çıkacağımı bilmiyorum. (Sinyallerin ve yuvaların bu tür işler için iyi olduğunu duydum, ama görünüşe göre çok yavaş ve nasıl uyduğunu göremiyorum).

Teşekkürler.

Yanıtlar:


7

Ne yapmak gözlemci desen kullanmak ve geri aramalar veya giriş işleme nesneleri listesini tutan bir giriş sınıfı var. Diğer nesneler, bazı şeyler meydana geldiğinde bildirilmek üzere kendilerini giriş sistemine kaydedebilir. Gözlemcilerin bilgilendirilmek istedikleri giriş olaylarının türüne bağlı olarak, kaydedebileceğiniz farklı geri arama türleri vardır. Bu, 'anahtar x aşağı / yukarı' ya da 'atlama / çekim / hareket olayı' gibi oyuna özgü daha düşük bir seviye olabilir.

Genellikle oyun nesneleri , girdi sınıfına kaydolmaktan ve ilgilendiği olayları işlemek için yöntemler sağlamaktan sorumlu bir girdi işleme bileşenine sahiptir. Hareket için, bir move (x, y) yöntemine sahip bir girdi taşıma bileşenim var. Kendisini giriş sistemine kaydeder ve hareket olayları hakkında bildirim alır (burada sola hareket etmeyi belirtmek için x ve y -1 ve 0 olur), taşıyıcı bileşen daha sonra ana oyun nesne koordinatlarını hareket yönüne ve nesne hızına göre değiştirir.

Bunun iyi bir çözüm olup olmadığını bilmiyorum ama şimdiye kadar benim için çalışıyor. Özellikle, aynı mantıksal oyun etkinliklerine eşlenen farklı türde giriş sistemi sağlamama izin veriyor, böylece gamepad düğmesi x ve klavye alanı, örneğin bir atlama olayı oluşturuyor (bundan biraz daha karmaşık, kullanıcının anahtarı yeniden atamasına izin veriyor) dönüşümler).


Bu kesinlikle beni ilgilendiriyor; giriş bileşeni belirli olaylar için kendisini kaydeder mi (playerInput 'sola', 'sağa' vb. kaydeder) veya kaydedilen her giriş bileşeni tüm iletileri alır mı?
Komünist Ördek

Gerçekten gereksiniminize ve onu nasıl uygulamak istediğinize bağlıdır. Benim durumumda dinleyiciler kendilerini belirli olaylar için kaydederler ve uygun girdi işleyici arabirimini uygularlar. Her girdi bileşeninin tüm iletileri alması gerekir, ancak ileti biçiminin sahip olduğumdan daha genel olması gerekir.
Firas Assaad

6

OP'nin tartışmasının bir sürü şeyi bir araya getirdiğini ve sorunun biraz parçalanarak basitleştirilebileceğini düşünüyorum.

Benim önerim:

Anahtar dizilerinizin durumlarını koruyun. Tüm klavye durumunu aynı anda almak için bir API çağrısı yok mu? (İşlerimin çoğu konsollarda ve hatta bağlı bir denetleyici için Windows'ta bile tüm denetleyici durumunu bir kerede alırsınız.) Anahtar durumlarınız klavyenin tuşlarında "sabit" bir haritadır. Çevrilmemiş en iyisidir, ancak API'lerden en kolay şekilde elde edersiniz.

Ardından, anahtarın bu kareyi yukarı çıkıp çıkmadığını gösteren başka bir paralel dizi, diğerinin aşağıya indiğini ve üçüncüsünün de anahtarın "aşağı" olduğunu belirtmek için tutun. Anahtarın geçerli durumunda ne kadar süre kaldığını takip edebilmeniz için bir zamanlayıcı atın.

Ardından, eylemlerin anahtarlarının eşlenmesini oluşturmak için bir yöntem oluşturun. Bunu birkaç kez yapmak isteyeceksiniz. Kullanıcı arabirimi öğeleri için bir kez (ve Windows eşlemelerini sorgulamaya dikkat edin, çünkü 'A' tuşuna bastığınızda tarama kodunu kullanıcının bilgisayarına A verecektir. Her oyun içi "mod" için başka. Bunlar, anahtar kodların eylemlerle eşleştirilmesidir. Bunu birkaç yolla yapabilirsiniz, biri alıcı sistem tarafından kullanılan bir enum tutmak, diğeri durum değişikliğinde çağrılacak işlevi gösteren bir işlev işaretçisi olacaktır. Belki hedeflerinize ve ihtiyaçlarınıza bağlı olarak ikisinin bir melezi. Bu "modlar" ile bunları yok sayılan girişin yığının aşağısında veya her neyse devam etmesini sağlayan bayraklarla bir denetleyici modu yığınına itebilir ve pop yapabilirsiniz.

Son olarak, bu önemli eylemleri bir şekilde ele alın. Hareket için zor bir şey yapmak isteyebilirsiniz, "W" yi aşağı çevirerek "ileri doğru hareket et" anlamına gelebilir, ancak bunun ikili bir çözüm olması gerekmez; "W kapalı" demek "maksimum Y olana kadar hızı X kadar arttırmak" ve "W yukarı", "sıfıra kadar Z hızını azaltmak" olabilir. Genel olarak konuşursak, "oyun sistemlerinde oyun kumandası kullanma arayüzü" nün oldukça dar olmasını istiyorsunuz; tüm anahtar çeviriyi tek bir yerde yapın ve daha sonra bunun sonuçlarını her yerde kullanın. Bu, Spacebar'ın kodda rastgele herhangi bir yere basılıp basılmadığını doğrudan kontrol etmenin aksine, çünkü rastgele bir noktada olursa, istemediğinizde muhtemelen rastgele bir zamanda vurulacak ve sadece bununla uğraşmak istemiyorum ...

Deseni tasarımdan gerçekten vazgeçiyorum ve bence bileşenler iyi olandan daha fazla geliştirme maliyeti getiriyor, bu yüzden ikisinden de bahsetmedim. Desenler, bileşenler gibi hedeflendiklerinde ortaya çıkacaktır, ancak başlangıçtan itibaren yapmak için yola çıkmak sadece hayatınızı zorlaştıracaktır.


Olayları grafik karelere bağlamak biraz kirli değil mi? Bunun ayrılması gerektiğini düşünüyorum.
Jo Yani

Demek istediğim, hemen hemen her durumda, oyuncunun giriş kartlarına grafik kartının kareleri yayacağından daha yavaş olacağını düşünüyorum, ama gerçekten bağımsız olmalılar ve aslında ağdan alınanlar gibi diğer etkinlik türleri için .
Jo Yani

Aslında; klavyeyi (veya başka bir giriş aygıtını) sorgulamanın ekrandan farklı bir hızda çalıştırılamamasının bir nedeni yoktur. Gerçekten, girişleri 100Hz'de yoklarsanız, video donanımı güncelleme sıklığından bağımsız olarak gerçekten tutarlı bir kullanıcı kontrolü deneyimi sağlayabilirsiniz. Verilerinizi nasıl ele aldığınız konusunda biraz daha zeki olmanız gerekir (mandallama vb.), Ancak hareketler gibi şeyleri tutarlı hale getirmenin daha kolay hale getirecektir.
dash-tom-bang

3

SFML'de, anahtarlar KeyPressed olay türü ile basıldıkları sırayla kullanılır. Her anahtarı bir süre sonra işlersiniz (getNextEvent ()).

Dolayısıyla, basılan tuş Key-> Action haritanızdaysa, karşılık gelen eylemi çalıştırın ve eğer değilse, ihtiyaç duyabilecek herhangi bir widget / öğeye iletin.

İkinci sorunuzla ilgili olarak, bu şekilde kalmanızı tavsiye ederim çünkü oyununuzu düzenlemeyi kolaylaştırır. Eğer sinyal veya benzeri bir şey kullanırsanız, "RunKeyDown" için bir yuva ve "JumpKeySlot" için bir yuva yapmanız gerekecektir. Ama oyunda, her ikisine de basıldığında özel bir eylem yapılırsa ne olur?

Giriş ve objeleri dekorla ilişkilendirmek istiyorsanız, girişinizi bir Durum (RunKey = true, FireKey = false, ...) yapabilir ve AI'larınıza başka bir olay gönderir gibi oynatıcıya gönderebilirsiniz.


Gerçek zamanlı algılama IIRC olduğundan, sf :: Event yerine sf :: Input ile klavye olaylarını işlemiyorum. Mümkün olduğunca API-agnostik tutmaya çalıştım. : P (Soru, yani)
Komünist Ördek

1
Ancak, Calvin1602'nin belirttiği nokta, "API sınırlamaları (SFML) nedeniyle geri arama yapmak yerine anket yapmak zorundayım" sorusundaki orijinal ifadenizin doğru olmadığıdır; etkinlikleriniz vardır, bu nedenle bir etkinliği işlerken geri arama yapabilirsiniz.
Kylotan

3

Doğru çözüm genellikle tartıştığınız iki yöntemin birleşimidir:

Önceden tanımlanmış bir anahtar kümesine sahip oyun oynama işlevselliği için, her çerçeveyi yoklamak tamamen uygundur ve yalnızca bir şeye bağlı olan anahtarlar için anket yapmanız gerekir. Bu aslında bir konsol oyununda denetleyici girişini nasıl sorgulayacağınıza benzer, özellikle analog giriş aygıtları söz konusu olduğunda tamamen yok olacak. Genel oyun sırasında muhtemelen tuşa basma olaylarını görmezden gelmek ve sadece yoklama kullanmak istersiniz.

İsimler gibi şeyler için girdi yazmak söz konusu olduğunda, oyunu farklı bir giriş işleme moduna geçirmelisiniz. Örneğin, "adınızı girin" istemi gelir gelmez, giriş kodunuzun ne yaptığını değiştirebilirsiniz. Bazı geri arama arabirimleri aracılığıyla tuşa basma olaylarını dinleyebilir veya gerekirse her tuş için yoklama başlatabilirsiniz. Olayları yazarken genellikle performansla ilgili o kadar da umursamadığınız ortaya çıkıyor, bu nedenle yoklama o kadar da kötü olmayacak.

Bu nedenle, oyun girişi için seçici yoklama ve ad yazma girişleri için (veya olay işleme yoksa tüm klavye yoklama) kullanmak istiyorsunuz.


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.