मैं कक्षाओं के बीच डेटा और निर्भरता को कैसे साफ और सुरुचिपूर्ण ढंग से संभाल सकता हूं


12

मैं एसएफएमएल 2 में 2 डी टॉपडाउन गेम पर काम कर रहा हूं, और एक सुंदर तरीका खोजने की जरूरत है जिसमें सब कुछ काम करेगा और एक साथ फिट होगा।

मुझे समझाने की अनुमति दें। मेरे पास कई कक्षाएं हैं जो एक सार आधार से विरासत में मिली हैं जो सभी वर्गों के लिए एक ड्रा विधि और एक अपडेट विधि प्रदान करता है।

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

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

यह अधिकांश भाग के लिए ठीक काम करता है, लेकिन मेरा मानना ​​है कि यह बेहतर किया जा सकता है, मुझे यकीन नहीं है कि कैसे।

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

  • जांचें कि क्या खिलाड़ी की-बोर्ड पर किसी लूटे गए आइटम की सीमा में है, अन्यथा आगे न बढ़ें।
  • आइटम का पता लगाएं।
  • आइटम पर स्प्राइट बनावट को उसकी डिफ़ॉल्ट बनावट से "लूट" बनावट में अपडेट करें।
  • आइटम के लिए टकराव को अपडेट करें: यह आकार बदल सकता है या पूरी तरह से हटा दिया गया है।
  • जोड़ा आइटम के साथ सूची को अद्यतन करने की आवश्यकता है।

मैं सब कुछ कैसे संवाद करूं? अपनी वर्तमान प्रणाली के साथ मैं अपनी कक्षाओं को दायरे से बाहर जाकर समाप्त कर दूंगा, और विधि सभी जगह एक दूसरे को कॉल कर देगी। मैं सभी कक्षाओं को एक बड़े प्रबंधक में बाँध सकता था और प्रत्येक को मूल प्रबंधक वर्ग के संदर्भ में दे सकता था, लेकिन यह केवल थोड़ा बेहतर लगता है।

किसी भी मदद / सलाह बहुत सराहना की जाएगी! अगर कुछ भी स्पष्ट नहीं है, तो मैं चीजों पर विस्तार करने के लिए खुश हूं।


1
आप विरासत के बजाय रचना पर विचार कर सकते हैं। रचना उदाहरण के लिए चारों ओर एक नज़र है और यह आपको कुछ विचार दे सकता है। पिंपल मुहावरा चीजों को छांटने में भी मदद कर सकता है।
OriginalDaemon

5
रचना पर कैनन के लेखों में से एक: अपने पदानुक्रम का विकास करें
doppelgreener

बहुत स्थानीय लगता है। कोड की समीक्षा एसई की कोशिश करो?
एको

जवाबों:


5

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

पेशेवरों: आपने अपनी कुछ कक्षाओं को अस्वीकृत कर दिया है

विपक्ष: इवेंट क्लासेस जोड़े, शायद अनावश्यक कोड ओवरहेड।

यह कैसे दिख सकता है इसके संभावित तरीकों में से एक है:

case LOOT_KEY:
   OnLoot(PLayer->getPos(), &inventoryItems);
....

// note onLoot do not needs to know anything about InvItem class (forward decl in enough)
int onLoot(vec3 pos, InvItems& pitems)
{
    InvItem* pitem = findInRange(pos, pitems, LOOT_RANGE);
    if(pitem)
     EventManager::Instance->post( Event::makeLootEvent(pitem));
}
....

// knows only about EventManager
InvItem::processEvents()
{
    while(!events.empty())
    {
        Event* pev = events.pop();
        ...
        case LOOT_EVENT:
            // in case you broadcasted it, but better is to sort all posted/sent events and add them only if they addressed to particular item 
            if(pev->item == this && handleLoot((LootEvent)pev))
            {
                EventManager::Instance->post(Event::makeLootSuccessEvent(this));
            }
    }
}

int handleLoot(LootEvent* plootev)
{
    InvItem* pi = plootev->item;
    if(pi->canLoot())
    {
        updateTexture(pi->icon, LOOTED_ICON_RES);
        return true;
    }
    return false; 
}


...
// knows only LootSuccessEvent and player
Inventory::processEvents()
{
    while(!events.empty())
    {
        Event* pev = events.pop();
        ...
        case LOOT_SUCCESS_EVENT:
             player->GetInventory()->add( ((LootSuccessEvent*)pev)->item );
        ...
}

यह संभव तरीकों में से एक है। संभवतः आपको इतने आयोजनों की आवश्यकता नहीं है। और मुझे यकीन है कि आप अपने डेटा को बेहतर तरीके से जान सकते हैं, यह केवल कई तरीकों में से एक है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.