मैं केवल एक बार कोड का एक टुकड़ा कैसे सुनिश्चित कर सकता हूं?


19

मेरा कुछ कोड है जिसे मैं केवल एक बार चलाना चाहता हूं, भले ही उस कोड को ट्रिगर करने वाली परिस्थितियां कई बार हो सकती हैं।

उदाहरण के लिए, जब उपयोगकर्ता माउस पर क्लिक करता है, तो मैं उस चीज पर क्लिक करना चाहता हूं:

void Update() {
    if(mousebuttonpressed) {
        ClickTheThing(); // I only want this to happen on the first click,
                         // then never again.
    }
}

हालांकि, इस कोड के साथ, हर बार जब मैं माउस क्लिक करता हूं, तो चीज क्लिक हो जाती है। मैं इसे केवल एक बार कैसे कर सकता हूं?


7
मुझे वास्तव में इस तरह का मजाकिया लगता है क्योंकि मुझे नहीं लगता कि यह "गेम-विशिष्ट प्रोग्रामिंग मुद्दों" के भीतर आता है। लेकिन मुझे वास्तव में वह नियम पसंद नहीं आया।
क्लासिकथुंडर

3
@ClassicThunder हां, यह निश्चित रूप से चीजों के सामान्य प्रोग्रामिंग पक्ष पर अधिक है। यदि आपको पसंद है तो बंद करने के लिए वोट दें, मैंने प्रश्न को अधिक पोस्ट किया है ताकि हम लोगों को इंगित करने के लिए कुछ करें जब वे इस तरह के प्रश्न पूछें। यह उस उद्देश्य के लिए खुला या बंद किया जा सकता है।
MichaelHouse

जवाबों:


41

बूलियन ध्वज का उपयोग करें।

दिखाए गए उदाहरण में, आप निम्नलिखित की तरह कोड को संशोधित करेंगे:

//a boolean flag that lets us "remember" if this thing has happened already
bool thatThingHappened = false;

void Update() {
    if(!thatThingHappened && mousebuttonpressed) {
        //if that thing hasn't happened yet and the mouse is pressed
        thatThingHappened = true;
        ClickTheThing();
    }
}

इसके अलावा, यदि आप कार्रवाई को दोहराने में सक्षम होना चाहते हैं, लेकिन कार्रवाई की आवृत्ति (यानी प्रत्येक कार्रवाई के बीच न्यूनतम समय) को सीमित करें। आप एक समान दृष्टिकोण का उपयोग करेंगे, लेकिन एक निश्चित समय के बाद ध्वज को रीसेट कर देंगे। उस पर अधिक विचारों के लिए मेरा जवाब यहां देखें ।


1
आपके प्रश्न का स्पष्ट उत्तर :-) मुझे वैकल्पिक दृष्टिकोणों को देखने में दिलचस्पी होगी यदि आप या कोई भी किसी के बारे में जानता है। इसके लिए एक वैश्विक बूलियन का यह उपयोग हमेशा मेरे लिए बदबूदार रहा है।
Evorlor

1
@ हर किसी के लिए स्पष्ट नहीं :)। मुझे वैकल्पिक समाधानों में भी दिलचस्पी है, शायद हम कुछ स्पष्ट नहीं सीख सकते हैं!
MichaelHouse

2
@ एक विकल्प के रूप में, आप प्रतिनिधियों (फ़ंक्शन पॉइंटर्स) का उपयोग कर सकते हैं और बदल सकते हैं कि क्या कार्रवाई की गई है। उदाहरण के लिए onStart() { delegate = doSomething; } ... if(mousebuttonpressed) { delegate.Execute(); }और void doSomething() { doStuff(); delegate = funcDoNothing; }अंत में सभी विकल्पों में कुछ प्रकार का एक झंडा होता है, जिसे आप सेट / अनसेट करते हैं ... और इस मामले में प्रतिनिधि कुछ और नहीं है (सिवाय इसके कि आपके पास दो से अधिक विकल्प हैं तो शायद क्या करें?)।
वंड्रा

2
@wondra हाँ, यह एक तरीका है। इसे जोड़ें। हम इस प्रश्न पर संभावित समाधानों की एक सूची बना सकते हैं।
MichaelHouse

1
@JamesSnell बहु-थ्रेडेड होने पर अधिक संभावना है। लेकिन फिर भी एक अच्छा अभ्यास।
MichaelHouse

21

क्या बूल ध्वज को पर्याप्त नहीं होना चाहिए या आप void Update()विधि के कोड की पठनीयता * में सुधार करना चाहते थे , आप विचार कर सकते हैं प्रतिनिधियों (कार्यकर्त्ताओं) का उपयोग करने कर :

public class InputController 
{
  //declare delegate type:
  //<accessbility> delegate <return type> <name> ( <parameter1>, <paramteter2>, ...)
  public delegate void ClickAction();

  //declare a variable of that type
  public ClickAction ClickTheThing { get; set; }

  void onStart()
  {
    //assign it the method you wish to execute on first click
    ClickTheThing = doStuff;
  }

  void Update() {
    if(mousebuttonpressed) {
        //you simply call the delegate here, the currently assigned function will be executed
        ClickTheThing();
     }
  }

  private void doStuff()
  {
    //some logic here
    ClickTheThing = doNothing; //and set the delegate to other(empty) funtion
  }

  //or do something else
  private void doNothing(){}
}

सरल "निष्पादित एक बार" प्रतिनिधियों के लिए ओवरकिल है, इसलिए मैं इसके बजाय बूल ध्वज का उपयोग करने का सुझाव दूंगा।
हालांकि, यदि आपको अधिक जटिल कार्यक्षमता की आवश्यकता है, तो प्रतिनिधि शायद बेहतर विकल्प हैं। उदाहरण के लिए, यदि आप श्रृंखला को और अधिक भिन्न क्रियाओं को अंजाम देना चाहते थे: पहली क्लिक पर, दूसरी पर एक और तीसरी पर एक और जो आप अभी देख सकते हैं:

func1() 
{
  //do logic 1 here
  someDelegate = func2;
}

func2() 
{
  //do logic 2 here
  someDelegate = func3;
}
//etc...

इसके बजाय विभिन्न झंडे के दसियों के साथ अपने कोड को रोकने के।
* कम रखरखाव की लागत पर बाकी कोड


जैसा कि मैंने उम्मीद की थी, मैंने परिणामों के साथ बहुत कुछ किया है:

----------------------------------------
|     Method     |  Unity   |    C++   |
| -------------------------------------|
| positive flag  |  21 ms   |   6 ms   |
| negative flag  |  5 ms    |   7 ms   |
| delegate       |  25 ms   |   14 ms  |
----------------------------------------

पहला परीक्षण यूनिटी 5.1.2 पर चलाया गया था, System.Diagnostics.Stopwatchजिसे 32-बिट निर्मित परियोजना (डिजाइनर में नहीं!) पर मापा गया था। विज़ुअल स्टूडियो 2015 (v140) पर दूसरा / ऑक्स फ्लैग के साथ 32-बिट रिलीज़ मोड में संकलित किया गया है। दोनों परीक्षण इंटेल i5-4670K सीपीयू @ 3.4GHz पर चलाए गए थे, प्रत्येक कार्यान्वयन के लिए 10,000,000 पुनरावृत्तियों के साथ। कोड:

//positive flag
if(flag){
    doClick();
    flag = false;
}
//negative flag
if(!flag){ }
else {
    doClick();
    flag = false;
}
//delegate
action();

निष्कर्ष: जबकि फंक्शन को ऑप्टिमाइज़ करते समय यूनिटी कंपाइलर एक अच्छा काम करता है, जबकि सकारात्मक ध्वज और प्रतिनिधियों (क्रमशः और 21 और 25 एमएस) के लिए लगभग एक ही परिणाम देता है, तो शाखा की गड़बड़ी या फ़ंक्शन कॉल अभी भी काफी महंगा है (नोट: प्रतिनिधि को कैश माना जाना चाहिए इस परीक्षण में)।
दिलचस्प बात यह है एकता संकलक है स्मार्ट पर्याप्त अनुकूलन शाखा जब वहाँ लगातार mispredictions के 99 लाखों, परीक्षण के इतने मैनुअल निष्फल कुछ प्रदर्शन को बढ़ावा देने 5 एमएस का सबसे अच्छा परिणाम दे रही है उपज होती है। सी ++ संस्करण स्थिति को नकारने के लिए कोई प्रदर्शन को बढ़ावा नहीं देता है, हालांकि फ़ंक्शन कॉल का ओवरहेड काफी कम है।
सबसे महत्वपूर्ण: अंतर बहुत अधिक अप्रासंगिक है किसी भी वास्तविक दुनिया के परिदृश्य के लिए


4
AFAIK यह प्रदर्शन के दृष्टिकोण से भी बेहतर है। नो-ऑप फ़ंक्शन को कॉल करना, यह मानते हुए कि फ़ंक्शन पहले से ही निर्देश कैश में है, झंडे की जाँच करने की तुलना में बहुत तेज़ है, खासकर जहां उस चेक को अन्य सशर्त के तहत नेस्टेड किया गया है ।
इंजीनियर

2
मुझे लगता है कि नवीन सही है, मुझे बूलियन ध्वज की जांच करने की तुलना में खराब प्रदर्शन की संभावना है - जब तक कि आपका जेआईटी वास्तव में स्मार्ट नहीं है और पूरे फ़ंक्शन को शाब्दिक रूप से कुछ भी नहीं बदलता है। लेकिन जब तक हम परिणामों को प्रोफाइल नहीं करते, हम निश्चित रूप से नहीं जान सकते।
वंड्रा

2
हम्म, यह उत्तर मुझे एक SW इंजीनियर के विकास की याद दिलाता है । एक तरफ मजाक करें, अगर आपको इस प्रदर्शन को बढ़ावा देने की पूरी जरूरत है (और निश्चित है), तो इसके लिए जाएं। यदि नहीं, तो मैं इसे रखने के लिए सुझाव देंगे चुंबन और एक बूलियन ध्वज का उपयोग करें, में प्रस्तावित की तरह एक और जवाब । हालांकि, यहां प्रस्तुत विकल्प के लिए +1!
मुचाहो

1
जहां संभव हो सशर्त बचें। मैं बात कर रहा हूँ कि मशीन के स्तर पर क्या होता है, चाहे वह आपका अपना मूल कोड हो, JIT कंपाइलर हो, या दुभाषिया हो। L1 कैश हिट एक रजिस्टर हिट के समान है, संभवतः थोड़ा धीमा यानी 1 या 2 चक्र, जबकि शाखा गलतफहमी, जो अक्सर कम होती है लेकिन फिर भी औसतन बहुत अधिक होती है, 10-20 चक्रों के ऑर्डर पर खर्च होता है। जलवा का जवाब देखें: stackoverflow.com/questions/289405/… और यह: stackoverflow.com/questions/11227809/…
इंजीनियर

1
इसके अलावा याद रखें कि बाइट 56 के उत्तर में इन शर्तों को आपके कार्यक्रम के जीवनकाल के लिए हर एक अद्यतन कहा जाना चाहिए , और इससे भयावह स्थिति हो सकती है या उनके भीतर नेस्टेड स्थिति हो सकती है, जिससे मामले और भी बदतर हो सकते हैं। फंक्शन पॉइंट / डेलीगेट्स जाने का रास्ता है।
इंजीनियर

3

संपूर्णता के लिए

(वास्तव में यह अनुशंसा नहीं कर रहा है कि आप ऐसा करते हैं क्योंकि यह वास्तव में बहुत सरल है जैसे कुछ लिखना है if(!already_called), लेकिन यह "ऐसा करने के लिए सही होगा।"

अप्रत्याशित रूप से, C ++ 11 मानक ने एक बार किसी फ़ंक्शन को कॉल करने की बल्कि तुच्छ समस्या को मुहावर किया है, और इसे सुपर स्पष्ट किया है:

#include <mutex>

void Update() {
if(mousebuttonpressed) {
    static std::once_flag f;
    std::call_once(f, ClickTheThing);
}

}

जाहिर है, मानक समाधान कुछ हद तक है थ्रेड की उपस्थिति में तुच्छ से बेहतर है क्योंकि यह अभी भी गारंटी देता है कि हमेशा एक ही कॉल होता है, कभी कुछ अलग नहीं होता है।

हालाँकि, आप सामान्य रूप से एक मल्टीथ्रेड इवेंट लूप नहीं चला रहे हैं और एक ही समय में कई चूहों के बटन दबा रहे हैं, ताकि थ्रेड सेफ्टी आपके मामले के लिए थोड़ा बेहतर हो।

व्यावहारिक रूप से, इसका मतलब है कि स्थानीय बूलियन के थ्रेड-सुरक्षित आरंभीकरण के अलावा (जो C ++ 11 वैसे भी थ्रेड-सुरक्षित होने की गारंटी देता है), मानक संस्करण को कॉल करने या कॉल न करने से पहले एक परमाणु परीक्षण_सेट ऑपरेशन भी करना होगा। कार्यक्रम।

फिर भी, यदि आप स्पष्ट होना पसंद करते हैं, तो समाधान है।

संपादित करें:
हुह। अब जब मैं यहाँ बैठा हूँ, उस कोड को कुछ मिनटों के लिए घूर रहा हूँ, मैं इसकी सिफारिश करने में लगभग असमर्थ हूँ।
वास्तव में यह लगभग उतना मूर्खतापूर्ण नहीं है जितना यह पहले लग सकता है, वास्तव में यह बहुत स्पष्ट रूप से और स्पष्ट रूप से आपके इरादे का संचार करता है ... यकीनन किसी अन्य समाधान की तुलना में बेहतर संरचित और अधिक पठनीय है जिसमें एक ifया ऐसा शामिल है ।


2

वास्तुकला के आधार पर कुछ सुझाव अलग-अलग होंगे।

एक फ़ंक्शन पॉइंटर / वेरिएंट / DLL / so / etc ... के रूप में clickThisThing () बनाएं ... और सुनिश्चित करें कि यह आपके आवश्यक फ़ंक्शन के लिए प्रारंभ किया गया है जब ऑब्जेक्ट / घटक / मॉड्यूल / आदि ... का त्वरित मूल्यांकन किया जाता है।

हैंडलर में जब भी माउस बटन दबाया जाता है, तब क्लिकटाइपिंग () फ़ंक्शन पॉइंटर को कॉल करें और फिर तुरंत पॉइंटर को दूसरे एनओपी (कोई ऑपरेशन) फ़ंक्शन पॉइंटर से बदलें।

किसी को बाद में खराब करने के लिए झंडे और अतिरिक्त तर्क की आवश्यकता नहीं है, बस इसे कॉल करें और इसे हर बार बदलें और चूंकि यह एक एनओपी है और एनओपी कुछ भी नहीं करता है और एनओपी के साथ प्रतिस्थापित हो जाता है।

या आप कॉल को छोड़ने के लिए ध्वज और तर्क का उपयोग कर सकते हैं।

या आप कॉल के बाद अपडेट () फ़ंक्शन को डिस्कनेक्ट कर सकते हैं ताकि बाहरी दुनिया इसके बारे में भूल जाए और इसे फिर से कॉल न करें।

या आपके पास clickThisThing () इन अवधारणाओं में से एक का उपयोग केवल एक बार उपयोगी काम के साथ जवाब देने के लिए करता है। इस तरह से आप एक बेसलाइन क्लिकटाइन्थिंगऑन () ऑब्जेक्ट / कंपोनेंट / मॉड्यूल का उपयोग कर सकते हैं और इसे तुरंत कहीं भी उपयोग कर सकते हैं, आपको इस व्यवहार की आवश्यकता है और आपके किसी भी updaters को सभी जगह विशेष तर्क की आवश्यकता नहीं है।


2

फ़ंक्शन पॉइंटर्स या डेलिगेट्स का उपयोग करें।

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

नेस्टेड कंडिशनल्स, जो कि ये अक्सर बनते हैं, एक फ्रेम की एक भी कंडिशन को चेक करने से ज्यादा महंगा होता है, क्योंकि ब्रांच प्रीडिक्शन अब उस केस में अपना जादू नहीं चला सकता। इसका मतलब है कि साइकिल के 10 एस के क्रम पर नियमित देरी - पाइपलाइन स्टॉल बराबर उत्कृष्टता । घोंसला ऊपर या हो सकता हैइस बूलियन ध्वज के नीचे । मुझे शायद ही पाठकों को यह याद दिलाने की ज़रूरत है कि गेम के जटिल लूप कैसे जल्दी बन सकते हैं।

फ़ंक्शन पॉइंटर्स इस कारण से मौजूद हैं - उनका उपयोग करें!


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

1

कुछ स्क्रिप्ट भाषाओं में जैसे जावास्क्रिप्ट या लुआ को आसानी से फ़ंक्शन संदर्भ का परीक्षण किया जा सकता है। में लुआ ( love2d ):

function ClickTheThing()
      .......
end
....

local ctt = ClickTheThing  --I make a local reference to function

.....

function update(dt)
..
    if ctt then
      ctt()
      ctt=nil
    end
..
end

0

एक में वॉन न्यूमैन आर्किटेक्चर कंप्यूटर, स्मृति जहां अपने कार्यक्रम के निर्देशों और डेटा जमा हो जाती है है। यदि आप कोड को केवल एक बार चलाना चाहते हैं, तो आप विधि के पूर्ण होने के बाद NOP के साथ विधि को अधिलेखित करने की विधि में कोड रख सकते हैं। इस तरह अगर विधि फिर से चलनी होती, तो कुछ नहीं होता।


6
यह कुछ आर्किटेक्चर को तोड़ देगा जो प्रोग्राम मेमोरी की रक्षा करते हैं या ROM से चलते हैं। यह संभवतः यादृच्छिक एंटीवायरस चेतावनियों को भी सेट करेगा, जो कि स्थापित है पर निर्भर करता है।
पैट्रिक ह्यूजेस

0

अजगर में अगर परियोजना पर अन्य लोगों के लिए एक झटका होने पर आपकी योजना:

code = compile('main code'+'del code', '<string>', 'exec')
exec code

यह स्क्रिप्ट कोड का प्रदर्शन करती है:

from time import time as t

code = compile('del code', '<string>', 'exec')

print 'see code object:'
print code

while True:
    try:
        user = compile(raw_input('play with it (variable name is code) (type done to be done:\t'), '<user_input>', 'exec')
        exec user
    except BaseException as e:
        print e
        break

exec code

print 'no more code object:'
try:
    print code
except BaseException as e:
    print e

while True:
    try:
        user = compile(raw_input('try to play with it again (type done to be done:\t'), '<user_input>', 'exec')
        exec user
    except BaseException as e:
        print e
        break

0

यहां एक और योगदान है, यह थोड़ा अधिक सामान्य / पुन: प्रयोज्य है, थोड़ा अधिक पठनीय और बनाए रखने योग्य है, लेकिन अन्य समाधानों की तुलना में कम कुशल है।

चलो एक बार में एक बार हमारे-निष्पादित तर्क को अलग कर देते हैं:

class Once
{
    private Action body;
    public bool HasBeenCalled { get; private set; }
    public Once(Action body)
    {
        this.body = body;
    }
    public void Call()
    {
        if (!HasBeenCalled)
        {
            body();
        }
        HasBeenCalled = true;
    }
    public void Reset() { HasBeenCalled = false; }
}

उदाहरण के रूप में इसका उपयोग इस प्रकार दिखता है:

Once clickTheThingOnce = new Once(ClickTheThing);

void Update() {
    if(mousebuttonpressed) {
        clickTheThingOnce.Call(); // ClickTheThing is only called once
                                  // or until .Reset() is called
    }
}

0

आप स्थैतिक का उपयोग करके एक चर पर विचार कर सकते हैं।

void doOnce()
{
   static bool executed = false;

   if(executed == false)
   {
      ...Your code here
      executed = true;
   }
}

आप इसे ClickTheThing()फ़ंक्शन में स्वयं कर सकते हैं , या कोई अन्य फ़ंक्शन बना सकते हैं और कॉल कर सकते हैंClickTheThing() अगर शरीर में कर सकते हैं।

यह अन्य समाधानों में सुझाए गए ध्वज का उपयोग करने के विचार के समान है, लेकिन ध्वज अन्य कोड से सुरक्षित है और फ़ंक्शन के स्थानीय होने के कारण इसे अन्यत्र नहीं बदला जा सकता है।


1
... लेकिन यह आपको 'ऑब्जेक्ट ऑब्जेक्ट' के अनुसार एक बार कोड चलाने से रोकता है। (अगर वह क्या उपयोगकर्ता की जरूरत है ..;))
Vaillancourt

0

मैं वास्तव में Xbox नियंत्रक इनपुट के साथ इस दुविधा में आया था। हालांकि नहीं बिल्कुल वही है जो बहुत समान है। आप अपनी आवश्यकताओं के अनुरूप मेरे उदाहरण में कोड बदल सकते हैं।

संपादित करें: आपकी स्थिति इसका उपयोग करेगी ->

https://docs.microsoft.com/en-us/windows/desktop/api/winuser/ns-winuser-tagrawmouse

और आप सीख सकते हैं कि कैसे - के माध्यम से एक कच्चा इनपुट वर्ग बनाया जाए

https://docs.microsoft.com/en-us/windows/desktop/inputdev/raw-input

लेकिन .. अब सुपर भयानक एल्गोरिथ्म पर ... वास्तव में नहीं, लेकिन हे .. यह बहुत अच्छा है :)

* तो: हम हर बटन के स्टेट्स को स्टोर कर सकते हैं और जो दबाए गए, जारी किए गए हैं, और हेल्ड डाउन !!! हम होल्डिंग टाइम की भी जांच कर सकते हैं, लेकिन यदि स्टेटमेंट के लिए सिंगल की आवश्यकता हो और किसी भी बटन की जांच कर सकते हैं, लेकिन इस जानकारी के नीचे कुछ नियम हैं।

जाहिर है अगर हम जांचना चाहते हैं कि क्या कुछ दबाया गया है, जारी किया गया है, आदि .. आप "अगर (यह) {}" करेंगे, लेकिन यह दिखा रहा है कि हम कैसे प्रेस राज्य प्राप्त कर सकते हैं और फिर इसे अगले फ्रेम से बंद कर सकते हैं ताकि आपका " ismousepressed "वास्तव में अगली बार जब आप चेक करेंगे तो गलत होगा।

पूरा कोड यहां: https://github.com/JeremyDX/DX_B/blob/master/DX_B/XGameInput.cpp

यह काम किस प्रकार करता है..

इसलिए मुझे यकीन नहीं है कि जब आप एक बटन दबाते हैं या नहीं, तो आप जो मान प्राप्त करते हैं, वह मूल रूप से होता है, लेकिन मूल रूप से जब मैं XInput में लोड करता हूं तो मुझे 0 और 65535 के बीच 16 बिट मूल्य मिलता है। इसमें "दबाए गए" के लिए 15 बिट्स संभव अवस्थाएं हैं।

समस्या हर बार जब मैंने यह जाँच की तो यह मुझे सूचना की वर्तमान स्थिति बताएगी। मुझे वर्तमान स्थिति को दबाने, विमोचित करने और होल्ड वैल्यू में बदलने का एक तरीका चाहिए था।

तो मैंने जो किया वह निम्नलिखित है।

पहले हम एक "CURRENT" वैरिएबल बनाते हैं। हर बार जब हम इस डेटा की जाँच करते हैं तो हम "CURRENT" को "PREVIOUS" वैरिएबल पर सेट करते हैं और फिर नए डेटा को "Current" में स्टोर करते हैं जैसा कि यहाँ देखा गया है ->

uint64_t LAST = CURRENT;
CURRENT = gamepad.wButtons;

इस जानकारी के साथ यहाँ कहाँ रोमांचक है !!

अगर बटन दबाया जा रहा है तो हम अब पता लगा सकते हैं!

BUTTONS_HOLD = LAST & CURRENT;

यह क्या करता है यह मूल रूप से दो मूल्यों की तुलना करता है और दोनों में दिखाए गए किसी भी बटन प्रेस 1 और बाकी सब कुछ 0 पर सेट होगा।

Ie (1 | 2 | 4) और (2 | 4 | 8) की उपज होगी (2 | 4)।

अब हमारे पास कौन से बटन हैं जो "नीचे" हैं। हमें आराम मिल सकता है।

दबाया सरल है .. हम अपने "CURRENT" स्थिति को लेते हैं और किसी भी आयोजित बटन को हटा देते हैं।

BUTTONS_PRESSED = CURRENT ^ BUTTONS_HOLD;

विमोचन वही है जो हम इसकी तुलना अपने लास्ट स्टेट से करते हैं।

BUTTONS_RELEASED = LAST ^ BUTTONS_HOLD;

इसलिए दबाए गए हालात को देख रहे हैं। अगर मान लें कि वर्तमान में हमारे पास 2 | 4 | 8 दबाया। हमने पाया कि 2 | 4 जहां आयोजित किया गया। जब हम हेल्ड बिट्स को हटाते हैं तो हम केवल 8 के साथ रह जाते हैं। यह इस चक्र के लिए नया दबाया हुआ बिट है।

वही जारी के लिए आवेदन किया जा सकता है। इस परिदृश्य में "LAST" को 1 पर सेट किया गया था 2 | 4. इसलिए जब हम 2 हटाते हैं | 4 बिट्स। हम 1 के साथ बचे हैं। इसलिए अंतिम फ्रेम के बाद से बटन 1 जारी किया गया था।

यह उपरोक्त परिदृश्य शायद सबसे आदर्श स्थिति है जिसे आप बिट तुलना के लिए पेश कर सकते हैं और यह 3 स्तर डेटा प्रदान करता है यदि कोई कथन नहीं है या केवल 3 त्वरित बिट गणना के लिए है।

मैं डेटा होल्ड करना भी चाहता था, हालांकि मेरी स्थिति सही नहीं है ... यह क्या है कि हम मूल रूप से वे होल्डबिट सेट कर रहे हैं जिन्हें हम जांचना चाहते हैं।

इसलिए हर बार जब हम अपना प्रेस / रिलीज़ / होल्ड डेटा सेट करते हैं तो हम चेक करते हैं कि होल्ड डेटा अभी भी वर्तमान होल्ड बिट चेक के बराबर है या नहीं। यदि यह रीसेट नहीं करता है तो यह वर्तमान समय का समय है। मेरे मामले में मैं इसे इंडेक्स फ्रेम करने के लिए सेट कर रहा हूं इसलिए मुझे पता है कि इसके लिए कितने फ्रेम रखे गए हैं।

इस दृष्टिकोण के नकारात्मक पक्ष यह है कि मैं अलग-अलग होल्ड समय प्राप्त नहीं कर सकता, लेकिन आप एक साथ कई बिट्स की जांच कर सकते हैं। Ie अगर मैं पकड़ को 1 पर सेट करता हूँ | 16 या तो 1 या 16 आयोजित नहीं किया जाता है तो यह विफल हो जाएगा। इसलिए यह आवश्यक है कि टिकिंग जारी रखने के लिए उन सभी बटन को दबाए रखा जाए।

फिर यदि आप कोड में देखते हैं तो आपको सभी नीट फ़ंक्शन कॉल दिखाई देंगे।

इसलिए आपका उदाहरण केवल जाँचने के लिए कम हो जाएगा यदि एक बटन प्रेस हुआ और एक बटन प्रेस केवल इस एल्गोरिथ्म के साथ एक बार हो सकता है। प्रेस करने के लिए अगले चेक पर यह मौजूद नहीं होगा क्योंकि आप अधिक प्रेस नहीं कर सकते हैं, फिर एक बार आपको प्रेस करने से पहले जारी करना होगा।


तो आप मूल रूप से एक बूल के बजाय बिटफील्ड का उपयोग करते हैं जैसा कि अन्य उत्तरों में कहा गया है?
Vaillancourt

हाँ बहुत बहुत ..
जेरेमी Trifilo

यह उसकी आवश्यकताओं के लिए इस्तेमाल किया जा सकता है, हालांकि नीचे msdn संरचना के साथ "usButtonFlags" में सभी बटन राज्यों का एक ही मूल्य शामिल है। docs.microsoft.com/en-us/windows/desktop/api/winuser/…
जेरेमी ट्रिफ़िलो

मुझे यकीन नहीं है कि नियंत्रक बटन के बारे में यह सब कहने की आवश्यकता कहां से है, हालांकि। उत्तर की मुख्य सामग्री बहुत ध्यान भंग करने वाले पाठ के नीचे छिपी हुई है।
Vaillancourt

हाँ, मैं सिर्फ एक संबंधित व्यक्तिगत परिदृश्य दे रहा था और मैंने इसे पूरा करने के लिए क्या किया। मैं बाद में इसे साफ कर दूंगा हालांकि यकीन है और हो सकता है कि मैं कीबोर्ड और माउस इनपुट जोड़ दूंगा और उस ओर एक दृष्टिकोण दूंगा।
जेरेमी ट्रिफ़िलो

-3

सस्ते तरीके से बाहर निकलें लेकिन आप लूप के लिए उपयोग कर सकते हैं

for (int i = 0; i < 1; i++)
{
    //code here
}

लूप चलाने के दौरान लूप में कोड हमेशा निष्पादित किया जाएगा। वहाँ कुछ भी नहीं है एक बार कोड निष्पादित होने से रोक रहा है। लूप या नो लूप बिल्कुल समान परिणाम देता है।
वेलनकोर्ट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.