2011-04-04 8 views
12

मैं वर्तमान में एक छोटी वास्तविक समय रणनीति 2 डी इंजन का निर्माण कर रहा हूं। और मुझे आश्चर्य है कि कितने सदाबहार sprites को संभालने के लिए अंततः मेरी स्क्रीन क्लियर करेगा।क्यूटी: QGraphicsItems को कुशलतापूर्वक संभालते हैं जिनमें "बहुत सारे पिक्समैप्स" हैं? (आरटीएस)

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

http://img263.imageshack.us/img263/1480/footman.png

आप ऊपर देख सकते हैं, यहां तक ​​कि Warcraft द्वितीय के सरल पैदल चलनेवाला अपने एनीमेशन के लिए लगभग 50 स्प्राइट मिल गया है। जो बहुत है और यह अक्सर sprites बदल जाएगा। (ब्लैक लाइन सिर्फ यह जांच रही थी कि मेरा अल्फा चैनल सही था या नहीं)

इस प्रकार, अंतिम प्रश्न: मैं कुशलतापूर्वक एक QGraphicsObject को कैसे कार्यान्वित करता हूं जो बदलता रहता है? मैं एक QGraphicsItem को कुशलतापूर्वक कार्यान्वित कैसे करूं जो बार-बार अपनी उपस्थिति को बदल देता है?

क्या मैं बस Q12raphicsPixmapItem की paint() विधि को अधिभारित करता हूं और स्क्रीन पर उपयोग किए गए पिक्समैप को बदलता रहता हूं? क्या यह कुछ "stuttering" का कारण बन जाएगा? मैंने सुना है कि कभी-कभी, सभी पिक्समैप्स बनाने के लिए बुद्धिमान/संभव है, उन सभी को छुपाएं, और आवश्यकता होने पर उन्हें डुप्लिकेट करें। (कॉपी अन्य परिचालनों की तुलना में कम महंगी है) क्या कोई अन्य बुद्धिमान विचार है?

किसी भी इनपुट के लिए धन्यवाद! (आरटीएस इंजन, जटिलता सामान, आदि ट्यूटोरियल ...)

+0

मैं सुझाव दूंगा कि क्यूटी का उपयोग करना सबसे अच्छी लाइब्रेरी नहीं है जिसे आप एक गेम विकसित करने के लिए चुन सकते हैं। क्या आपने कुछ अन्य विकल्पों की खोज की है? यह माना जाता है कि क्यूटी आपके लिए बहुत कम है, जैसे क्लिपिंग, स्प्राइट्स के आसान परिवर्तन, इत्यादि, लेकिन यह भी बहुत सारी चीजें करता है जो आपको वास्तव में एक ही समय में नहीं चाहिए ... मुझे थोड़ी सी गुगलिंग के बाद मिला है यह: http://www.libsdl.org/ जो आपकी आवश्यकताओं को qgraphics सामग्री – Tom

+0

@Tom से बेहतर तरीके से पूरा कर सकता है: इनपुट के लिए धन्यवाद, वास्तव में, एसडीएल वास्तव में 2 डी अनुप्रयोगों के लिए एक उत्कृष्ट सी लाइब्रेरी है। हालांकि, और आप सही हैं क्योंकि मैंने इसे नहीं बताया है, मैं मशीन लर्निंग और आरटीएस आर्किटेक्चर में खुद को विकसित करने की तुलना में अधिक रुचि रखता हूं। आप मेरे प्रश्न को दोबारा सुधार सकते हैं: अच्छे पुस्तकालय कितने sprites के साथ एक वस्तु को संभालते हैं? (और इस प्रकार, मैं इसे क्यूटी के साथ कैसे कार्यान्वित कर सकता हूं, जो इस परियोजना के लिए पूरी तरह से आवश्यक पुस्तकालय है) – Fezvez

+1

यदि आप अपना व्यूपोर्ट QGLWidget पर सेट करते हैं और मैन्युअल रूप से पिक्चर() पिक्समैप्स सेट करते हैं जिन्हें आपने पहले से ही स्मृति में कैश किया है, तो आपको ठीक होना चाहिए प्रदर्शन के अनुसार। – Chris

उत्तर

15

(मैं सामान्य विचार के साथ शुरू करेंगे पहले, एक संभव क्यूटी कार्यान्वयन का पालन करेंगे)

मैं कैसे संग्रहीत WCII स्प्राइट हैं पता नहीं है , लेकिन आपको एक स्प्राइट शीट का उपयोग करना चाहिए (यदि आवश्यक हो तो इसे स्वयं बनाना)। इस शीट से संबद्ध, आपके पास एनीमेशन की सूची में कम से कम स्प्राइट का कुछ विवरण होगा, और प्रत्येक एनीमेशन के लिए, यह पहचानकर्ता/नाम, साथ ही फ्रेम की एक सूची है।

उन एनीमेशन के फ्रेम का वर्णन करने में आपके द्वारा डाले गए विवरण का स्तर आपके ऊपर है, लेकिन प्रदर्शित करने के लिए स्प्राइट शीट के कम से कम आयत में होना चाहिए।

उदाहरण के तौर पर, this sprite sheet पर एक नज़र डालें (स्पष्ट रूप से अनुकूलित नहीं है, लेकिन उदाहरण के लिए, यह ठीक है :))। यहां संबंधित animations descriptions (लाइन 12 से 3 9) है। सभी एनिमेशन शामिल नहीं हैं, लेकिन आपको विचार मिल जाएगा।

आप देख सकते हैं कि "निष्क्रिय" एनीमेशन 3 फ्रेम से बना है, जो स्प्राइट शीट में पहले 3 फ्रेमों से उप-रीक्ट करता है। उप-रेक्ट से संबद्ध, इस नमूने में 2 और जानकारी हैं:

  • अवधि: अगली बार जाने से पहले फ्रेम को कब प्रदर्शित किया जाना चाहिए?
  • उत्पत्ति: फ्रेम का लंगर बिंदु क्या है?

अब, आप क्यूटी में इसे लागू करने के तरीके पर कैसे जायेंगे?

एनिमेशन 'वर्णन फ़ाइल प्रारूप पूरी तरह से आपके ऊपर है, लेकिन मैं कुछ पदानुक्रम फ़ाइल प्रारूप की अनुशंसा करता हूं। चूंकि क्यूटी एक्सएमएल पार्सर प्रदान करता है, यह सही हो सकता है। यदि आप जेएसओएन जैसे हल्के प्रारूप को बढ़ावा देने और पसंद करने के लिए उपयोग करते हैं, तो आप बूस्ट का उपयोग कर सकते हैं।उदासीन रूप से एक्सएमएल/जेएसओएन फाइलों को पार्स करने के लिए ptree और उनमें से डेटा निकालने के लिए एक आम इंटरफ़ेस है।

  • QPixmap: जहाँ से हम एनिमेशन 'फ्रेम मिलान उप आयतों आकर्षित होगा,
  • एक QTimer को

    ग्राफिक्स प्रतिनिधित्व के लिए, आप कुछ वर्गों का उपयोग करना होगा अपने स्प्राइट,

  • आपके बहुत ही प्रदर्शन वर्ग अद्यतन करते हैं, कहते हैं कि AnimatedSprite (एक QGraphicsObject से ली गई है, तो आप संकेत/स्लॉट रों की आवश्यकता होगी अपपोर्ट),
  • और एक समर्थन वर्ग, टाइमरप्रॉक्सी (क्यूओब्जेक्ट से व्युत्पन्न) कहें।

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

तो यह 2 भूमिकाओं को पूरा:

  • दृश्य के निर्माण समय: सभी AnimatedSprite एक संकेत यह प्रदान करता है के लिए खुद को पंजीकृत करेंगे, चलो इसे नाम updateTime (msecs पूर्णांक) करते हैं,
  • दृश्य रनटाइम पर, यह एक क्यूटीमर शुरू करेगा जो टाइमआउट आपको आवश्यक ग्रैन्युलरिटी पर सेट किया गया है (आप अनुमानित 60 एफपीएस के लिए 16 एमएमएस के साथ जा सकते हैं)। क्यूटीमर का सिग्नल टाइमआउट() एक निजी स्लॉट से जुड़ा होगा जो अपडेटटाइम (int msecs) पर आग लगाएगा जहां msecs आपके द्वारा सेट किए गए टाइमर की ग्रैन्युलरिटी पर सेट है।

अब समाधान के मूल के लिए: एनिमेटेडस्प्रिट। शुरू & रोक एनिमेशन

  • QGraphicScene
  • पर सक्रिय स्प्राइट के फ्रेम ड्राइंग को अद्यतन करने

    • & पढ़ने भंडारण एनिमेशन 'विवरण इसकी आवश्यकता होगी,
    • : इस वर्ग निम्नलिखित भूमिकाओं है

      प्रारंभ में, आपको इसे निम्नलिखित जानकारी देना चाहिए:

      • टाइमरप्रॉक्सी (आपके दृश्य के स्वामित्व वाले, या दृश्य के मालिक के वर्ग) का एक उदाहरण।जब इस उदाहरण प्रदान की है, तो आप सिर्फ कनेक्ट जो वर्तमान एनीमेशन अद्यतन करेगा एक निजी स्लॉट TimerProxy :: updateTime (int) संकेत,
      • QPixmap spritesheet पकड़े,
      • और एनिमेशन विवरण

      रनटाइम के दौरान, अद्यतन तरीकों दिखेगा की तरह:

      • एक निजी timeUpdated (int) स्लॉट जो जांच करेगा कि वर्तमान एनीमेशन के फ्रेम चाहिए अद्यतन हो, और तदनुसार अद्यतन करते हैं,
      • सार्वजनिक एनिमेशन विधि, जैसे startAnim (स्थिरांक QString & animName) है, जो वर्तमान एनीमेशन बदल जाएगा, बीता हुआ समय काउंटर रीसेट करें, और अद्यतन वर्तमान उप रेक्ट आकर्षित करने के लिए मैच के लिए नई एनीमेशन का पहला फ्रेम।

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

      अन्त में, प्रस्तुत करने के लिए, तो आप सिर्फ reimplement QGraphicsItem :: रंग (...) विधि वर्तमान subrect, जो कैसा लग सकता है आकर्षित करने के लिए:

      void AnimatedSprite::paint(QPainter *painter, 
                const QStyleOptionGraphicsItem * /*option*/, 
                QWidget * /*widget*/) 
      { 
          painter->drawImage(mCurrentAnim.mCurrentFrame->mOrigin, 
               mSpriteSheet, 
               mCurrentAnim.mCurrentFrame->mSubRect); 
      } 
      

      आशा है कि मदद करता है (और नहीं है बहुत बड़ा, वाह: एस)

    +3

    वाह! धन्यवाद! यही वह ढांचा है जो मैं चाहता था! – Fezvez

    संबंधित मुद्दे