Yoklama ve olay güdümlü giriş


19

Giriş yöntemi için oylama kullanarak bir oyun geliştiriyorum. Ancak, şimdi oyun menülerine ve diğer UI bileşenlerine daha derinlemesine baktığım için, muhtemelen olay güdümlü girdiler olmasını isterim. Belki de her ikisine de sahip olmak, UI için yönlendirilen olayı kullanmak ve "dünya" girdisi için oy kullanmak. En iyi yolun ne olduğunu merak ediyorum.

Yoklamayı şu şekilde tanımlıyorum: her güncelleme döngüsü Hangi tuşların basıldığını, farenin nerede olduğunu, düğmelere basıldığını, sonra bunları çalıştırıp toplanan bilgilere göre eylemler yaptığımı kontrol ediyorum.

Olay tahrik olarak tanımlıyorum: bir olay meydana geldiğinde ve kesme tetiklendiğinde ve bir kod bloğu olaya dayalı olarak çalıştığında, kesme tabanlı olaylar.

Tüm etkinlik odaklı, oylamaya gitmenin en iyisi olduğunu mu düşünüyorsunuz, yoksa her ikisinin de bir kombinasyonu kabul edilebilir mi? Her ikisi için de artıları ve eksileri varsa lütfen bunları listeleyin. Teşekkürler.

DÜZENLE

Oyun Java / OpenGL tabanlıdır, bu nedenle Windows / Mac / Linux'a yayınlanacaktır. Bunu mobil cihazlara genişletme olasılığı düşüktür. Oyun RTS tarzı, 3. kişi 3D.

DÜZENLEME 2

Bunu uygulama şeklimden hala tam olarak memnun değilim, ancak doğru hareket ettiğim şey kullanıcı arayüzümdeki etkinlikleri yakalamak ve kullanıcı arayüzü bileşenlerim tarafından ele alınmazlarsa etkinliği Toplama / seçim için "Dünya". Gibi bir şey:

@Override  
private boolean handleEvent(Event event) {  
    if(hud.handleEvent(event)) {  
        return true;  
    }  
    return WORLD.handleEvent(event);  
}

Bu şekilde, düğmelerin arkasındaki nesneleri seçmek için kullanıcı arayüzünden tıklamalar almıyorum ve ne değil.

Şu anda kamera kontrollerim hala yoklamaya dayanıyor ve şimdilik çalışıyor gibi görünüyor, ancak daha sonra güncelleyebilirim.

Tüm cevapları takdir ediyorum, üzgünüm sadece bir tane seçebilirim!


6
Java'da emin değilim, ancak genel olarak her zaman girişi yoklamak zorundasınız. Daha sonra işler değiştiğinde olaylar gönderebilirsiniz, ancak bu yine de bir yoklama sistemine dayanmaktadır.
James

Bence en alakalı odak noktası girdi toplama dışında herhangi bir yükten arınmış bir olay döngüsü tasarlamaktır. Açıklamama izin verin: işletim sistemi giriş odaklı kesintiyi yapacak ve bunu global "giriş iş parçacığında" işleyecek, daha sonra bu OS iş parçacığı şu anda odaklanmış uygulamaya mesajları yönlendirecek ve intel'i mesaj kuyruğuna yazacaktır. İleti kuyruğu PeekMessage veya GetMessage tarafından sorgulanmalıdır. Bunu almanın en hızlı yolu GetMessage'ı kullanmak ve zamanlayıcının sizi uyandırmasına izin vermektir, daha sonra mesajı çok hassas bir şekilde zaman damgası ekleyebilirsiniz.
v.oddou

Yanıtlar:


17

Oyun ve donanımınızın gereksinimlerine bağlıdır. Çoğu oyun genellikle giriş durumundaki değişikliklerle ilgilenir, yani kullanıcı ateşleme tuşuna basar ve silahı ateşlemeye başlar, kullanıcı ateşleme tuşunu serbest bırakır ve silahları ateşlemeyi durdurur, kullanıcı hareket tuşuna basar ve hareket etmeye başlar, hareket tuşunu serbest bırakır ve hareket etmeyi durdurur Bu nedenle, olay tarafından yönlendirilen bir giriş sistemi, bilgilerin zaten uygun bir formatta olması nedeniyle en mantıklıdır. Ayrıca Windows platformunda, klavye ve fare durumundaki değişiklikler için zaten etkinlikler alıyorsunuz, bu nedenle genellikle düşük seviyeli giriş olaylarından yüksek seviyeli oyun olaylarına 1: 1 dönüşüm. Yoklama ile, sık sık geçerli ve son kare arasındaki durumu karşılaştırarak bu tür olayları manuel olarak oluşturmak zorunda kalırsınız. Temel olarak, "şimdi hangi düğmelere basıldı?"

Bununla birlikte, bazı platformlarda yoklama girişine düşük düzeyde takılıp kalıyorsunuz ve kenarı kendiniz kontrol etmenin bir yolu yok. Bununla birlikte, tüm yüksek seviye mantık için olayları kullanarak her zaman en iyi sonuçları elde ettim, çünkü bu sistemler doğal olarak böyle çalışır.


Teşekkürler, oyunun platformu ve amacı hakkında ek bilgiler ekledim.
MichaelHouse

1
GetAsyncKeyStateWin32 üzerinde yoklama kullanmanın basit bir yolu olduğunu unutmayın .
Macke

Derp, Nate Bross'un burada ele alacağınız yorumlarında bir soru sordum, bu yüzden sanırım onu ​​geliştireceğim. Tüm PC'ler, OS klavye olay ilişkisine 1: 1 donanım kesintisi sunuyor mu ve ne tür platformlar düşük düzeyli yoklama ile sınırlıdır?
michael.bartnett

@Macke: bazen antivirüs, tüm global sistemden tuşa basma alabildikleri için bu API'yı kullanan programları rapor eder, böylece kötü amaçlı keylogging'i etkinleştirir. Tüm internette (biliyorum) en harika makale budur: securelist.com/analysis/publications/36358/…
v.oddou

7

Her ikisini de yapamayacağınız ve her iki dünyanın da en iyisini elde edememeniz için hiçbir neden göremiyorum.

Giriş Olayları yoklama ile oluşturulur (bir düzeyde sürücü hangi durumda olduğunu görmek için donanımı yoklar) ve ana döngünüz tüm giriş cihazlarını yokladığı için kendinizinkini kolayca uygulayabilirsiniz. Aşağıdaki gibi basit bir şey geçmişte kullandığım şey.

mouseInput = GetMouse();
kbInput = GetKeyboard();


// refactor this out to its own method if it makes sense
if menuState == Showing
    if mouseInput.LeftButton == State.Pressed
        LeftButton(mouseInput.X, mouseInput.Y)

// rest of game input code processing

void LeftButton(int x, int y)
{
    // left button event handler
}

Olayları kesintiler olarak tanımladığınızı biliyorum ve buraya koyduğum şey "gerçekten olaya dayalı" değil, ama kesintilerin size verdikleri yukarıdakilerin size ne vermediğini görmüyorum - çoğu kullanıcı fark etmeyecek oyununuz çok düşük kare hızında çalışmadığı sürece tek kare kaybolur.


1
Cihazlardan girdi almanın doğasını merak ediyorum. Klavye olayları işletim sistemi tarafından aygıt sürücüsü düzeyinde yoklama sonucu gönderiliyor mu? Yoksa bir klavye olayı kesmeye karşılık geliyor mu? Yoksa kesinti var mı, ama işletim sistemi onları tamponluyor ve uygun gördüğünde gönderiyor?
michael.bartnett

Bu seviyede nasıl çalıştığı konusunda olumlu değilim, ama en temel, bazı yazılımlar bir döngüde çalışır ve klavye durumunu kontrol eder ve eğer değişmişse değişiklik kabarırsa, önceki durumla karşılaştırır.
Nate

5

Burada iki farklı sorun var:

  1. İşletim sisteminden / donanımdan kullanıcı girişini nasıl okuyorsunuz?

  2. Motorunuzdaki kullanıcı girişini nasıl işliyorsunuz?

Okumak için, bu açıkça platformunuza ve ne tür bir girdi okumak istediğinize bağlıdır. Giriş katmanınızdaki bir şeyi diğerine dönüştürmenin kolay olduğunu unutmayın. (Yani motora olay gönderir ve gönderir veya olayları dinler ve motora durum gönderir.)

İşleme için birkaç farklı seçenek vardır:

  • Oynatıcı hareket kontrolü (ve benzer şemalar) için, her kareyi yeniden hızlandırmanız gerektiğinden yoklama daha basit olabilir. İç döngünüzün yoklama tabanlı olması muhtemeldir:

    yani bir şey speed += 1 if button.down else -1; clamp(speed, 0, 42);

  • Ayrık olaylar için (yangın füzesi, duraklatma oyunu, gezegenin diğer tarafına ışınlanma), olay işleme tercih edilir, aksi takdirde kodunuz maybeLaunchMissile(key_state);çağrılarla doludur ve bu sadece ... kötü, hanımefendi. ;)

Umarım yardımcı olur.

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.