पोल-आधारित इनपुट पर मुख्य संयोजन


9

तो मान लीजिए कि आपके पास एक इनपुट सिस्टम है जो मतदान पर आधारित है

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

कहते हैं कि आप 3 से 8 लंबाई के प्रमुख संयोजनों को पहचानने में सक्षम होना चाहते हैं (जैसे नीचे, नीचे-आगे, आगे, ए फॉर हैडो-केन)

तुम कैसे सबसे अच्छा एक सामान्य (आसानी से परिवर्तनीय / प्रोग्राम) कुंजी संयोजन इनपुट पर सिस्टम बनाना होगा सर्वेक्षण में शामिल इनपुट?

जवाबों:


7

मौलिक रूप से, आप नहीं कर सकते । कुंजी संयोजनों के लिए एक आदेश की आवश्यकता होती है, और एक आदेश के लिए घटनाओं की आवश्यकता होती है।

आप जो कुछ भी कर सकते हैं, वह प्रत्येक फ्रेम की कुंजी राज्यों की तुलना करके और अंतर से पोस्ट-हॉक कीप / कीडाउन घटनाओं को उत्पन्न करके घटनाओं में बदल जाता है। यह उतना विश्वसनीय नहीं है क्योंकि आप टाइमस्टैम्पिंग और अन्य इंट्रा-फ्रेम ऑर्डरिंग को खो देते हैं जो "देशी" ईवेंट सिस्टम प्रदान करते हैं, लेकिन यह आपको प्रति फ्रेम कम से कम एक कुंजी का पता लगाने और ऑर्डर करने की अनुमति देगा।

एक बार जब आप उन घटनाओं का आदेश दे देते हैं, तो आप अपनी चाल सूचियों के खिलाफ उन्हें मिलान करने के लिए एक परिमित राज्य मशीन या अन्य उपकरण का उपयोग कर सकते हैं और सही को निष्पादित कर सकते हैं।


यह कहना थोड़ा भ्रामक है कि आप घटनाओं के बिना ऐसा नहीं कर सकते । तकनीकी रूप से, घटनाएं किसी विधि या विधियों की सूची को कॉल करने का एक तरीका है जब कुछ शर्त पूरी होती हैं। उस अर्थ में, आपको घटनाओं की आवश्यकता है। हालांकि, मैं कई प्रोग्रामिंग कार्यों के लिए घटनाओं (अनुचित तरीके से) शब्द को लागू कर सकता हूं जो उस विवरण को फिट करते हैं। मैंने एक उत्तर जोड़ा है जो इस समस्या को हल करता है जिस तरह से मैं आमतौर पर करता हूं, जो कि उपयोग नहीं करता है जो कि अधिकांश प्रोग्रामर "घटनाओं" के रूप में सोचते हैं।
ओल्होव्स्की

2
आपका कोड ठीक वही करता है जो मैंने बिना घटनाओं के कहा था, लेकिन कैविएट्स को अनदेखा करता है - जो कि आप इंट्रा-फ्रेम ऑर्डर को खो देते हैं। जब आप उदाहरण के लिए Win32 संदेश लूप से ईवेंट प्राप्त करते हैं, तो आप उन्हें एक क्रम में एक ग्लोब प्रति फ्रेम से अधिक ग्रैन्युलैरिटी के साथ प्राप्त करते हैं। जब आप अपने आप को डेल्टास गणना करते हैं, तो आप उसे खो देते हैं। एक फाइटिंग गेम के लिए जहां खिलाड़ी एक फ्रेम में कॉम्बो के कई हिस्सों को इनपुट कर सकते हैं, आपको यह जानना होगा कि क्या वे ऑर्डर के अंदर या बाहर थे।

काफी उचित। बशर्ते कि हम 60 हर्ट्ज पर मतदान कर रहे हों, मुझे संदेह है कि हम उन प्रेसों के बीच अंतर करना चाहते हैं जो 16ms से कम हैं इसके अलावा 60 हर्ट्ज मतदान प्रदान करता है (यह मानकर कि हमारे खिलाड़ी मनुष्य हैं)।
ओल्होव्स्की

हम कर। कुशल लड़ खेल खिलाड़ी तीन फ्रेम से भी कम समय में हैडूकेन / शोर्युकन स्टिक कमांड दर्ज कर सकते हैं, जिसका अर्थ है कि हमें उनके बीच अंतर करना चाहिए।

फिर आपको 60hz से अधिक बार मतदान करने की आवश्यकता है।
ओलहोवस्की

3

एक तरीका वर्तमान और पिछले इनपुट राज्यों को संग्रहीत करना है, और हर बार जब आप इनपुट को पोल करते हैं, तो उनकी तुलना करें।

प्रत्येक कुंजी के लिए जिसे दबाया जा सकता है, उस वस्तु को स्टोर करें जिसमें पिछली बार का टाइमस्टैम्प हो जो कुंजी को डाउन स्टेट से अप स्टेट में स्विच करता है।

हर चुनाव में ऐसा करके इन वस्तुओं को अपडेट करें:

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;
        }
    }
}

अब आप पैटर्न को अपने कॉम्बो से मिलान कर सकते हैं keys

प्रत्येक कॉम्बो के लिए एक कॉम्बो ऑब्जेक्ट है, और प्रत्येक पोल पर प्रत्येक कॉम्बो ऑब्जेक्ट पर कॉल अपडेट () करें।

एक कॉम्बो ऑब्जेक्ट का अपडेट () विधि कॉम्बो से मेल खाएगा, अगर इस पोल में कॉम्बो के लिए सभी आवश्यक शर्तें संतुष्ट हैं, तो यह जाँच करेगा। यानी कॉम्बो के लिए सभी कुंजी टाइमस्टैम्प क्रम में हैं, और कॉम्बो को तोड़ने वाली कोई अन्य कुंजी इस फ्रेम को दबाया नहीं गया है। मिले प्रत्येक शर्त के लिए, कॉम्बो ऑब्जेक्ट में एक काउंटर बढ़ाकर अगली स्थिति की जांच करें। जब एक कॉम्बो में सभी शर्तें पूरी होती हैं, तो उस विधि को कॉल करें जिसे कॉम्बो को निष्पादित करना चाहिए। यदि some_key_has_been_pressed == trueलेकिन वह कुंजी जो कॉम्बो के लिए अगली शर्त है उसे दबाया नहीं गया है, तो कॉम्बो की संतुष्ट स्थिति काउंटर को 0 पर रीसेट करें।

उपरोक्त मेरी पसंदीदा विधि है, क्योंकि इसे लागू करना आसान है, बनाए रखना आसान है, कुशल है, और अत्यधिक मॉड्यूलर है।

हालाँकि, एक और अच्छी विधि के लिए, XNA इनपुट अनुक्रम नमूना देखें , जो C # में लिखा गया है, और तर्क संभवतः आपके द्वारा उपयोग की जा रही भाषा के लिए हस्तांतरणीय है।


दूसरे स्टेटमेंट में if(current_input[key].down){, क्या आप यह भी जांचना चाहेंगे कि previous_inputक्या राज्य में कुंजी थी ? जैसा कि लिखा है, मुझे लगता है कि यह लगातार एक आयोजित कुंजी को अपडेट करेगा down_timestamp
webdevkit

लगातार टाइमस्टैम्प को अद्यतन करना अभीष्ट व्यवहार है। यह आपको किसी भी कुंजी के up_timestamp और down_timestamp की तुलना करने की अनुमति देता है, यह जांचने के लिए कि यह कितनी देर तक आयोजित किया गया था। यदि आप लगातार एक कुंजी रखते हैं, तो आप up_timestamp को नहीं बदल रहे हैं, इसलिए (down_timestamp - up_timestamp) अभी भी आपको वह अवधि देता है, जिसके लिए इसे आयोजित किया गया था।
ओल्होवस्की

स्पष्टीकरण के लिए धन्यवाद। मैं इसके विपरीत सोच रहा था, जहां up_timestamp - down_timestamp एक आयोजित कुंजी की अवधि है।
webdevkit

1

अंतिम X कुंजी घटनाओं का एक स्टैक बनाएं, प्रत्येक प्रमुख घटना के लिए प्रेस / रिलीज की कुंजी और समय के साथ एक ऑब्जेक्ट जोड़ें, फिर जांचें कि क्या स्टैक के अंतिम सदस्य एक विशेष पैटर्न से मेल खाते हैं और यदि उन कुंजियों को पर्याप्त तेजी से दबाया गया है एक संयोजन के रूप में गिनें। अंत में स्टैक से सबसे पुरानी वस्तु को हटा दें।


2
एक स्टैक जिसे आप नीचे की वस्तु से हटा सकते हैं वह वास्तव में स्टैक नहीं है;)
ओल्होव्स्की

डेटा संस्थाओं का एक गुच्छा, एक सूची सही शब्द हो सकता है।
आआआआआआआआआआ आआआआआ

deque;) O (1) enq / deq ftw।
michael.bartnett

3
एक क्रमबद्ध क्रम जहां वस्तुओं को एक छोर पर रखा जाता है और दूसरे से हटाया जाता है, को सबसे अच्छी तरह से कतार कहा जाता है ।

1
आप एक रिंग-बफर (BufferLength> = सबसे लंबी कमांड) बना सकते हैं और इसे कुंजियां लिख सकते हैं (स्थिति = संख्या MOD बफरप्लेवृन्द)। कोई जोड़ / हटाने की आवश्यकता नहीं होगी
क्रॉमस्टर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.