एनिमेशन को अभी भी तर्क और प्रतिपादन के बीच पूरी तरह से विभाजित किया जा सकता है। एनीमेशन की सार डेटा स्थिति वह जानकारी होगी जो आपके ग्राफिक्स एपीआई के लिए एनीमेशन को रेंडर करने के लिए आवश्यक है।
उदाहरण के लिए 2 डी गेम में, यह एक आयत क्षेत्र हो सकता है जो उस क्षेत्र को चिह्नित करता है जो आपकी स्प्राइट शीट के वर्तमान भाग को प्रदर्शित करता है जिसे खींचने की आवश्यकता होती है (जब आपके पास एक शीट होती है जिसमें 30 से 808080 चित्र होते हैं, जिसमें आपके चरित्र के विभिन्न चरण होते हैं कूदना, बैठना, आगे बढ़ना आदि)। यह किसी भी प्रकार का डेटा भी हो सकता है जिसे आपको रेंडर करने की आवश्यकता नहीं है, लेकिन शायद एनीमेशन के प्रबंधन के लिए खुद को बताता है, जैसे कि वर्तमान एनीमेशन चरण समाप्त होने तक का समय बचा है या एनीमेशन का नाम ("चलना", "खड़ा है") आदि) उस सभी का प्रतिनिधित्व किसी भी तरह से आप चाहते हैं। यही लॉजिक पार्ट है।
रेंडरिंग भाग में, आप इसे हमेशा की तरह करते हैं, अपने मॉडल से उस आयत को प्राप्त करें और ग्राफिक्स रेंडर को वास्तव में कॉल करने के लिए अपने रेंडरर का उपयोग करें।
कोड में (C ++ सिंटैक्स का उपयोग करके):
class Sprite //Model
{
private:
Rectangle subrect;
Vector2f position;
//etc.
public:
Rectangle GetSubrect()
{
return subrect;
}
//etc.
};
class AnimatedSprite : public Sprite, public Updatable //arbitrary interface for classes that need to change their state on a regular basis
{
AnimationController animation_controller;
//etc.
public:
void Update()
{
animation_controller.Update(); //Good OOP design ;) It will take control of changing animations in time etc. for you
this.SetSubrect(animation_controller.GetCurrentAnimation().GetRect());
}
//etc.
};
वह डेटा है। आपका रेंडरर उस डेटा को ले जाएगा और उसे आकर्षित करेगा। चूंकि सामान्य स्प्राइट्स और एनिमेटेड दोनों समान हैं, इसलिए आप यहां बहुरूपता का उपयोग कर सकते हैं!
class Renderer
{
//etc.
public:
void Draw(const Sprite &spr)
{
graphics_api_pointer->Draw(spr.GetAllTheDataThatINeed());
}
};
TMV:
मैं एक और उदाहरण लेकर आया हूं। कहते हैं कि आपके पास एक आरपीजी है। उदाहरण के लिए, आपका मॉडल जो दुनिया के नक्शे का प्रतिनिधित्व करता है, उसे संभवतः दुनिया में चरित्र की स्थिति को संग्रहीत करने की आवश्यकता होगी क्योंकि मानचित्र पर टाइल निर्देशांक। हालाँकि, जब आप वर्ण को आगे बढ़ाते हैं, तो वे एक बार में अगले वर्ग में कुछ पिक्सेल चलते हैं। क्या आप एनीमेशन ऑब्जेक्ट में "टाइल्स के बीच" स्थिति को स्टोर करते हैं? जब मॉडल अगले टाइल पर "समन्वयित" हो जाता है, तो आप मॉडल को कैसे अपडेट करते हैं?
दुनिया का नक्शा सीधे खिलाड़ियों की स्थिति के बारे में नहीं जानता है (इसमें वेक्टर 2 एफ या ऐसा कुछ नहीं है जो सीधे खिलाड़ियों की स्थिति को स्टोर करता है =, इसके बजाय इसका सीधा संदर्भ खिलाड़ी ऑब्जेक्ट के लिए है, जो बदले में एनिमेटेडड्रेसप्रिट से प्राप्त होता है। इसलिए आप इसे रेंडरर को आसानी से पास कर सकते हैं, और इससे सभी आवश्यक डेटा प्राप्त कर सकते हैं।
हालांकि सामान्य तौर पर, आपके टीलमैप को सब कुछ करने में सक्षम नहीं होना चाहिए - मेरे पास एक वर्ग "टाइल मैप" होगा जो सभी टाइलों के प्रबंधन का ख्याल रखता है, और शायद यह उन वस्तुओं के बीच टकराव का भी पता लगाता है जो मैं इसे सौंपता हूं और नक्शे पर टाइल्स। फिर, मेरे पास एक और "RPGMap" वर्ग होगा, या फिर आप इसे कॉल करना चाहेंगे, जिसमें आपके तिलमैप और खिलाड़ी के संदर्भ दोनों का संदर्भ हो और वास्तविक अपडेट () आपके खिलाड़ी को और आपके कॉल को करता है tilemap।
जब खिलाड़ी चलता है तो आप मॉडल को कैसे अपडेट करना चाहते हैं यह इस बात पर निर्भर करता है कि आप क्या करना चाहते हैं।
क्या आपके खिलाड़ी को स्वतंत्र रूप से टाइलों (ज़ेल्डा शैली) के बीच जाने की अनुमति है? बस इनपुट को संभालें और खिलाड़ी को हर फ्रेम के अनुसार आगे बढ़ाएं। या क्या आप चाहते हैं कि खिलाड़ी "दाएं" दबाए और आपका चरित्र स्वचालित रूप से एक टाइल को दाईं ओर ले जाए? अपने RPGMap वर्ग को अपने पद पर पहुंचने तक खिलाड़ियों की स्थिति को अलग करने दें और इस बीच सभी आंदोलन-कुंजी इनपुट हैंडलिंग को लॉक करें।
किसी भी तरह से, यदि आप इसे अपने आप पर आसान बनाना चाहते हैं, तो आपके सभी मॉडलों में अपडेट () तरीके होंगे यदि उन्हें वास्तव में खुद को अपडेट करने के लिए कुछ तर्क की आवश्यकता है (केवल चर के मूल्यों को बदलने के बजाय) - आप नियंत्रक को दूर नहीं करते हैं इस तरह से एमवीसी पैटर्न में, आप कोड को "एक कदम ऊपर" (नियंत्रक) से मॉडल में नीचे ले जाते हैं, और सभी नियंत्रक इस अद्यतन को कॉल करते हैं मॉडल का तरीका (हमारे मामले में नियंत्रक होगा) The RPGMap)। आप अभी भी लॉगिक्स कोड को आसानी से स्वैप कर सकते हैं - आप सीधे कक्षा के कोड को बदल सकते हैं या यदि आपको पूरी तरह से अलग व्यवहार की आवश्यकता है, तो आप केवल अपने मॉडल वर्ग से प्राप्त कर सकते हैं और केवल अपडेट () विधि को ओवरराइड कर सकते हैं।
यह तरीका मेथड कॉल और उस तरह की चीजों को कम करता है - जो कि शुद्ध MVC पैटर्न के मुख्य नुकसानों में से एक हुआ करता था (आप GetThis () GetThat () बहुत बार कॉल करना समाप्त करते हैं) - यह कोड को लंबा और एक दोनों बनाता है पढ़ने में थोड़ा कठिन और धीमा भी - भले ही आपके कंपाइलर द्वारा इस बात का ध्यान रखा जाए जो इस तरह के बहुत सारे सामान का अनुकूलन करता है।