खेल राज्य 'ढेर'?


52

मैं सोच रहा था कि गेम स्टेट्स को अपने गेम में कैसे लागू किया जाए। इसके लिए मुझे मुख्य चीजें चाहिए:

  • अर्ध-पारदर्शी शीर्ष स्थिति-खेल के पीछे एक ठहराव मेनू के माध्यम से देखने में सक्षम है

  • कुछ OO-I को इसके पीछे के सिद्धांत का उपयोग करने और समझने में आसानी होती है, साथ ही साथ इसे व्यवस्थित और अधिक जोड़ने के लिए भी रखा जाता है।



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

states.push_back(new MainMenuState());
states.push_back(new OptionsMenuState());
states.pop_front();

खिलाड़ी लोडिंग का प्रतिनिधित्व करने के लिए, फिर विकल्पों में और फिर मुख्य मेनू पर जाएं।
यह एक अच्छा विचार है, या ...? क्या मुझे कुछ और देखना चाहिए?

धन्यवाद।


क्या आप MainMenuState को OptionsMenuState के पीछे देखना चाहते हैं? या सिर्फ OptionsMenuState के पीछे खेल स्क्रीन?
स्किज़ जूल

योजना यह थी कि राज्यों में एक अस्पष्टता / समसामयिक मूल्य / ध्वज होगा। मैं देखूंगा और देखूंगा कि क्या शीर्ष राज्य के पास यह सच था, और यदि ऐसा है तो इसका क्या मूल्य है। फिर इसे दूसरे राज्य के साथ अधिक अस्पष्टता के साथ प्रस्तुत करें। इस मामले में, नहीं, मैं नहीं।
कम्युनिस्ट डक

मुझे पता है कि यह दिन में देर हो चुकी है, लेकिन भविष्य के पाठकों के लिए: newनमूना कोड में दिखाए गए तरीके से उपयोग न करें , यह सिर्फ मेमोरी लीक या अन्य, अधिक गंभीर त्रुटियों के लिए पूछ रहा है।
चरण

जवाबों:


44

मैंने कोडरंगर के समान इंजन पर काम किया। मेरा एक अलग दृष्टिकोण है। :)

पहले, हमारे पास FSM का ढेर नहीं था - हमारे पास राज्यों का ढेर था। राज्यों का एक स्टैक एकल FSM बनाता है। मुझे नहीं पता कि FSM का स्टैक कैसा दिखेगा। शायद बहुत जटिल के साथ कुछ भी करने के लिए व्यावहारिक।

हमारे ग्लोबल स्टेट मशीन के साथ मेरी सबसे बड़ी समस्या यह थी कि यह राज्यों का एक समूह था, न कि राज्यों का एक समूह। इसका मतलब है, उदाहरण के लिए, ... / MainMenu / Loading अलग था ... / Loading / MainMenu, इस पर निर्भर करता है कि आपको लोडिंग स्क्रीन से पहले या बाद में मुख्य मेनू मिला है (खेल अतुल्यकालिक है और लोडिंग ज्यादातर सर्वर-चालित है )।

चीजों के दो उदाहरण के रूप में यह बदसूरत बना:

  • इसके कारण LoadingGameplay स्थिति उदा।, इसलिए आपके पास आधार / लोड हो रहा था, और Gameplay राज्य के भीतर लोड करने के लिए आधार / गेमप्ले / LoadingGameplay, जिसे सामान्य लोडिंग स्थिति में बहुत कोड को दोहराना था (लेकिन सभी नहीं, और अधिक जोड़ें )।
  • हमारे पास कई कार्य थे जैसे "यदि चरित्र निर्माता गेमप्ले में जाते हैं, यदि गेमप्ले में चरित्र का चयन करते हैं, यदि चरित्र का चयन करें तो लॉगिन पर वापस जाएं", क्योंकि हम अलग-अलग राज्यों में एक ही इंटरफ़ेस विंडो दिखाना चाहते थे, लेकिन बैक / फॉरवर्ड बटन अभी भी काम करते हैं।

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

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

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

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


शानदार जवाब, धन्यवाद! मुझे लगता है कि मैं आपके पोस्ट और आपके पिछले अनुभवों से बहुत कुछ ले सकता हूं। : डी + 1 / टिक।
कम्युनिस्ट डक

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

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

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

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

11

यहाँ एक गेमस्टैट स्टैक का एक उदाहरण कार्यान्वयन है जो मुझे बहुत उपयोगी लगा: http://creators.xna.com/en-US/samples/gamestatemanagement

यह C # में लिखा गया है और इसे संकलित करने के लिए आपको XNA फ्रेमवर्क की आवश्यकता है, हालाँकि आप विचार प्राप्त करने के लिए कोड, प्रलेखन और वीडियो की जांच कर सकते हैं।

यह राज्य के संक्रमण, पारदर्शी राज्यों (जैसे मोडल संदेश बॉक्स) और लोडिंग राज्यों (मौजूदा राज्यों के उतारने और अगले राज्य के लोडिंग का प्रबंधन) का समर्थन कर सकता है।

मैं अपनी (गैर-सी #) हॉबी परियोजनाओं में अब समान अवधारणाओं का उपयोग करता हूं (दी गई है, यह बड़ी परियोजनाओं के लिए उपयुक्त नहीं हो सकता है) और छोटे / शौक वाली परियोजनाओं के लिए मैं निश्चित रूप से दृष्टिकोण की सिफारिश कर सकता हूं।


5

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


3

"गेम प्रोग्रामिंग गम्स" संस्करणों में से एक में गेम स्टेट्स के लिए एक राज्य मशीन कार्यान्वयन था; http://emergent.net/Global/Documents/textbook/Chapter1_GameAppFramework.pdf में एक छोटे से खेल के लिए इसका उपयोग करने का एक उदाहरण है, और पठनीय होने के लिए गेमबायो-विशिष्ट भी नहीं होना चाहिए।


"प्रोग्रामिंग रोल प्लेइंग गेम्स विथ डायरेक्टएक्स" का पहला खंड भी एक राज्य प्रणाली (और एक प्रक्रिया प्रणाली - बहुत दिलचस्प अंतर) को लागू करता है।
R

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

3

बस चर्चा में थोड़ा मानकीकरण जोड़ने के लिए, इस तरह के डेटा संरचनाओं के लिए क्लासिक सीएस शब्द एक पुशडाउन ऑटोमेटन है


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

1
"मुझे यकीन नहीं है कि राज्य के ढेर के किसी भी वास्तविक दुनिया कार्यान्वयन लगभग एक pushdown automaton के बराबर है।" क्या फर्क पड़ता है? दोनों में राज्यों का एक सीमित सेट, राज्यों का एक इतिहास और धक्का और पॉप राज्यों के लिए आदिम संचालन हैं। आपके द्वारा उल्लिखित अन्य कार्यों में से कोई भी इससे अलग नहीं है। "पॉप टू स्टेट्स" केवल दो बार पॉपिंग है। "स्वैप" एक पॉप और एक धक्का है। डेटा पास करना मुख्य विचार से बाहर है, लेकिन हर गेम जो "FSM" का उपयोग करता है, अतिरिक्त डेटा पर भी बिना नाम की तरह महसूस किए टिक जाता है।
मुम्बई

एक पुशडाउन ऑटोमेटन में, आपके संक्रमण को प्रभावित करने वाला एकमात्र राज्य शीर्ष पर स्थित राज्य है। बीच में दो राज्यों की अदला-बदली की अनुमति नहीं है; यहां तक ​​कि बीच में राज्यों को देखने की अनुमति नहीं है। मुझे लगता है कि "FSM" शब्द का शब्दार्थ विस्तार उचित है और इसके लाभ हैं (और हमारे पास अभी भी "DFA" और "NFA" सबसे अधिक प्रतिबंधित अर्थ हैं), लेकिन "पुशडाउन ऑटोमेटन" कड़ाई से एक कंप्यूटर विज्ञान शब्द है। अगर हम इसे हर एक स्टैक-आधारित सिस्टम पर लागू करते हैं तो केवल भ्रम की प्रतीक्षा है।

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

1
अच्छी बात है, तय!
उदार

1

मुझे यकीन नहीं है कि राज्य प्रणाली की कार्यक्षमता को सीमित करने के साथ-साथ एक स्टैक पूरी तरह से आवश्यक है। स्टैक का उपयोग करते हुए, आप कई संभावनाओं में से एक के लिए एक राज्य से बाहर नहीं निकल सकते। कहते हैं कि आप "मेन मेनू" में शुरू करते हैं, फिर "लोड गेम" पर जाएं, आप सहेजे गए गेम को सफलतापूर्वक लोड करने के बाद "पॉज़" स्थिति में जा सकते हैं और यदि उपयोगकर्ता लोड को रद्द करता है तो "मेन मेनू" पर वापस आ सकता है।

मेरे पास यह होगा कि राज्य से बाहर निकलने पर राज्य का पालन करें।

उन उदाहरणों के लिए जहां आप वर्तमान स्थिति से पहले की स्थिति में वापस आना चाहते हैं, उदाहरण के लिए "मुख्य मेनू-> विकल्प-> मुख्य मेनू" और "रोकें-> विकल्प-> रोकें", बस राज्य के लिए एक स्टार्टअप पैरामीटर के रूप में पास करें वापस जाने के लिए राज्य।


शायद मैं सवाल गलत समझ गया?
स्किज़ जूल

नहीं, तुमने नहीं किया। मुझे लगता है कि डाउन-वोटर ने किया।
कम्युनिस्ट डक

स्टैक का उपयोग करने से स्पष्ट राज्य संक्रमण का उपयोग नहीं होता है।
डैश-टॉम-बैंग

1

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

class StateMachine
{
public:
    StateMachine(Engine *);
    void Push(State *);
    State *Pop();
    void Update();
    Engine *GetEngine();

private:
    std::stack<State *> _states;
    Engine *_engine;
};

राज्यों को वर्तमान स्थिति और मशीन के मापदंडों के रूप में धकेल दिया जाता है।

void StateMachine::Push(State *state)
{
    State *from = 0;
    if (!_states.empty()) from = _states.top();
    _states.push(state);
    state->Enter(this, from);
}

राज्यों को एक ही फैशन में popped हैं। चाहे आप Enter()निचले पर कॉल करें Stateएक कार्यान्वयन प्रश्न है।

State *StateMachine::Pop()
{
    _ASSERT(!_states.empty());
    State *state = _states.top();
    State *to = 0;
    _states.pop();
    if (!_states.empty()) to = _states.top();
    state->Exit(this, to);
    return state;
}

प्रवेश करते समय, अपडेट करते या बाहर निकलते समय, Stateसभी आवश्यक जानकारी प्राप्त करता है।

void SomeGameState::Enter(StateMachine *sm, State *from)
{
    Engine *eng = sm->GetEngine();
    eng->GetKeyboard()->KeyDown.Bind(this, &SomeGameState::KeyDown);
    LoadLevelState *state = new LoadLevelState();
    state->SetLevel(eng->GetSaveGame()->GetLevelName());
    state->Load.Bind(this, &SomeGameState::OnLevelLoaded);
    sm->Push(state);
}

void SomeGameState::Update(StateMachine *sm)
{
    Engine *eng = sm->GetEngine();
    float time = eng->GetFrameTime();
    if (shouldExit)
        sm->Pop();
}

void SomeGameState::Exit(StateMachine *sm, State *from)
{
    Engine *eng = sm->GetEngine();
    eng->GetKeyboard()->KeyDown.UnsubscribeAll(this);
}

0

मैंने कई खेलों में एक समान प्रणाली का उपयोग किया है और पाया है कि कुछ अपवादों के साथ, यह एक उत्कृष्ट यूआई मॉडल के रूप में कार्य करता है।

हमने जिन मुद्दों का सामना किया, वे ऐसे मामले थे, जिनमें नए राज्य को आगे बढ़ाने से पहले कई राज्यों को वापस करने के लिए कुछ मामलों में वांछित था (आवश्यकता को हटाने के लिए हमने यूआई को फिर से प्रवाहित किया, क्योंकि यह आमतौर पर खराब यूआई का संकेत था) और विज़ार्ड-शैली बनाना रैखिक प्रवाह (अगले राज्य के साथ डेटा को आसानी से हल करके)।

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

कुछ सहायक कार्यों को सामान्य कार्यों को सरल बनाने के लिए जोड़ा गया था, जैसे कि स्वैप (पॉप और पुश, रैखिक प्रवाह के लिए) और रीसेट (मुख्य मेनू में वापस जाने के लिए, या प्रवाह को समाप्त करने के लिए)।


UI मॉडल के रूप में यह कुछ समझ में आता है। मैं उन्हें स्टेट्स कहने में संकोच करूंगा, क्योंकि मेरे सिर में मैं मुख्य गेम इंजन के इंटर्नल के साथ जुड़ूंगा, जबकि "मेन मेन्यू", "ऑप्शन मेन्यू", "गेम स्क्रीन", और "पॉज स्क्रीन" उच्च स्तर के हैं, और अक्सर कोर गेम की आंतरिक स्थिति के साथ कोई बातचीत नहीं होती है, और बस "पॉज़", "अनपॉज़", "लोड लेवल 1", "स्टार्ट लेवल", "रीस्टार्ट लेवल", के रूप में कोर इंजन को कमांड भेजते हैं। "सहेजें", और "पुनर्स्थापना", "वॉल्यूम स्तर 57 सेट करें", आदि जाहिर है, हालांकि यह खेल द्वारा महत्वपूर्ण रूप से भिन्न हो सकता है।
केविन कैथकार्ट

0

यह वह दृष्टिकोण है जो मैं अपनी लगभग सभी परियोजनाओं के लिए लेता हूं, क्योंकि यह अविश्वसनीय रूप से अच्छी तरह से काम करता है और बेहद सरल है।

मेरा सबसे हालिया प्रोजेक्ट, शार्पलाइक , इस सटीक तरीके से नियंत्रण प्रवाह को संभालता है। हमारे राज्य सभी इवेंट फ़ंक्शन के एक सेट के साथ वायर्ड होते हैं, जिन्हें राज्यों के बदलने पर कहा जाता है, और इसमें एक "नामित स्टैक" अवधारणा होती है जिसमें आप एक ही राज्य मशीन और उनके बीच शाखा के कई राज्य हो सकते हैं - एक वैचारिक उपकरण, और आवश्यक नहीं है, लेकिन आसान है।

मैं "यह बताता हूं कि नियंत्रक को यह बताना चाहिए कि स्किज़ द्वारा सुझाए गए प्रतिमान" समाप्त होने पर यह किस राज्य का अनुसरण करना चाहिए: यह संरचनात्मक रूप से ध्वनि नहीं है, और यह संवाद बॉक्स (जो मानक स्टैक-स्टेट प्रतिमान में सिर्फ एक नया बनाने के लिए सामान बनाता है) नए सदस्यों के साथ राज्य उपवर्ग, तब इसे पढ़ना जब आप आह्वान की स्थिति में लौटते हैं) बहुत कठिन है जितना कि यह होना चाहिए।


0

मैंने मूल रूप से कई प्रणालियों में मूल रूप से इस सटीक प्रणाली का उपयोग किया था; उदाहरण के लिए, दृश्य और खेल मेनू (उर्फ "विराम") में कहा गया है, अपने राज्य के ढेर थे। इन-गेम यूआई ने भी कुछ इस तरह का उपयोग किया, हालांकि इसमें "वैश्विक" पहलू (जैसे कि स्वास्थ्यवर्धक और मानचित्र / रडार) थे कि राज्य स्विचिंग टिंट हो सकता है लेकिन जो पूरे राज्यों में एक सामान्य तरीके से अद्यतन किया गया है।

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

इन अन्य प्रणालियों में से कुछ में "शीर्ष राज्य को प्रतिस्थापित" कार्यक्षमता भी थी, लेकिन इसे आमतौर पर StatePop()इसके बाद लागू किया गया था StatePush(x);

मेमोरी कार्ड से निपटने के समान था क्योंकि मैंने वास्तव में "ऑपरेशन" का एक टन ऑपरेशन कतार में धकेल दिया था (जो कार्यात्मक रूप से स्टैक के समान काम करता था, जैसे कि LIFO के बजाय FIFO); एक बार जब आप इस तरह की संरचना का उपयोग करना शुरू कर देते हैं ("अब एक चीज हो रही है, और जब यह अपने आप हो जाता है") तो यह कोड के हर क्षेत्र को संक्रमित करना शुरू कर देता है। यहां तक ​​कि एआई ने कुछ इस तरह से उपयोग करना शुरू कर दिया; एआई "क्लूलेस" था, फिर "सावधान" में बदल गया जब खिलाड़ी ने शोर किया, लेकिन देखा नहीं गया, और फिर अंत में "सक्रिय" तक बढ़ गया जब उन्होंने खिलाड़ी को देखा (और उस समय के कम गेम के विपरीत, आप छिपा नहीं सके। एक कार्डबोर्ड बॉक्स में और दुश्मन को आपके बारे में भूल जाते हैं! ऐसा नहीं है कि मैं कड़वा हूँ ...)।

GameState.h:

enum GameState
{
   k_frontend,
   k_gameplay,
   k_inGameMenu,
   k_moviePlayback,
   k_numStates
};

void GameStatePush(GameState);
void GameStatePop();
void GameStateUpdate();

GameState.cpp:

// k_maxNumStates could be bigger, but we don't need more than
// one of each state on the stack.
static const int k_maxNumStates = k_numStates;
static GameState s_states[k_maxNumStates] = { k_frontEnd };
static int s_numStates = 1;

static void (*s_startupFunctions)()[] =
   { FrontEndStart, GameplayStart, InGameMenuStart, MovieStart };
static void (*s_shutdownFunctions)()[] =
   { FrontEndStop, GameplayStop, InGameMenuStop, MovieStop };
static void (*s_updateFunctions)()[] =
   { FrontEndUpdate, GameplayUpdate, InGameMenuUpdate, MovieUpdate };

static void GameStateStart(GameState);
static void GameStateStop(GameState);

void GameStatePush(GameState gs)
{
   Assert(s_numStates < k_maxNumStates);
   GameStateStop(s_states[s_numStates - 1])
   s_states[s_numStates] = gs;
   s_numStates++;
   GameStateStart(gs);
}

void GameStatePop()
{
   Assert(s_numStates > 1);  // can't pop last state
   s_numStates--;
   GameStateStop(s_states[s_numStates]);
   GameStateStart(s_states[s_numStates - 1]);
}

void GameStateUpdate()
{
   GameState current = s_states[s_numStates - 1];
   s_updateFunctions[current]();
}

void GameStateStart(GameState gs)
{
   s_startupFunctions[gs]();
}

void GameStateStop(GameState gs)
{
   s_shutdownFunctions[gs]();
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.