एक्सट्रपलेशन टूटने से टकराव का पता चलता है


10

मेरे स्प्राइट के आंदोलन में एक्सट्रपलेशन लगाने से पहले, मेरी टक्कर पूरी तरह से काम करती थी। हालांकि, मेरे स्प्राइट के आंदोलन (चीजों को सुचारू करने के लिए) पर एक्सट्रपलेशन लगाने के बाद, टकराव अब काम नहीं करता है।

यह है कि चीजों को एक्सट्रपलेशन से पहले कैसे काम किया जाता है:

यहाँ छवि विवरण दर्ज करें

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

मैं अपना एक्सट्रपलेशन लागू करने के बाद

यहाँ छवि विवरण दर्ज करें

इस व्यवहार को कैसे सुधारा जाए?

मैंने एक्सट्रपलेशन के ठीक बाद एक अतिरिक्त टक्कर की जांच करने की कोशिश की है - यह बहुत सारी समस्याओं को स्पष्ट करता है लेकिन मैंने इसे खारिज कर दिया है क्योंकि मेरे प्रतिपादन में तर्क देना सवाल से बाहर है।

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

मैं यहाँ पर इसी तरह के सवालों के एक जोड़े को मिला है, लेकिन जवाब मुझे मदद नहीं की है।

यह मेरा एक्सट्रपलेशन कोड है:

public void onDrawFrame(GL10 gl) {


        //Set/Re-set loop back to 0 to start counting again
        loops=0;

        while(System.currentTimeMillis() > nextGameTick && loops < maxFrameskip){

        SceneManager.getInstance().getCurrentScene().updateLogic();
        nextGameTick+=skipTicks;
        timeCorrection += (1000d/ticksPerSecond) % 1;
        nextGameTick+=timeCorrection;
        timeCorrection %=1;
        loops++;
        tics++;

     }

        extrapolation = (float)(System.currentTimeMillis() + skipTicks - nextGameTick) / (float)skipTicks; 

        render(extrapolation);
}

एक्सट्रपलेशन लागू करना

            render(float extrapolation){

            //This example shows extrapolation for X axis only.  Y position (spriteScreenY is assumed to be valid)
            extrapolatedPosX = spriteGridX+(SpriteXVelocity*dt)*extrapolation;
            spriteScreenPosX = extrapolationPosX * screenWidth;

            drawSprite(spriteScreenX, spriteScreenY);           


        }

संपादित करें

जैसा कि मैंने ऊपर उल्लेख किया है, मैंने स्प्राइट के निर्देशांक की एक प्रति बनाने की कोशिश की है, विशेष रूप से इसके साथ आकर्षित करने के लिए .... इसकी अपनी समस्याएं हैं।

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

मैंने बाएं / दाएं के लिए झंडे लगाने की कोशिश की है और यदि इनमें से कोई भी सक्षम है तो केवल एक्सट्रपलेटिंग। मैंने यह देखने के लिए कि क्या कोई अंतर है, यह देखने के लिए अंतिम और वर्तमान स्थितियों को कॉपी करने की कोशिश की है। हालाँकि, जहाँ तक टक्कर होती है, ये मदद नहीं करते हैं।

यदि उपयोगकर्ता कह रहा है कि दायाँ बटन और स्प्राइट सही चल रहा है, जब वह दीवार से टकराता है, यदि उपयोगकर्ता दाहिने बटन को दबाए रखता है, तो स्प्राइट दीवार से रोके जाने के दौरान दाईं ओर स्थित रहेगा; इसलिए वास्तव में नहीं चल रहा है), हालांकि, क्योंकि सही ध्वज अभी भी सेट है और इसलिए भी क्योंकि टक्कर की दिनचर्या दीवार से लगातार स्प्राइट को स्थानांतरित कर रही है, यह अभी भी कोड (खिलाड़ी नहीं) को दिखाई देता है कि स्प्राइट अभी भी चल रहा है, और इसलिए एक्सट्रपलेशन जारी है। तो खिलाड़ी क्या देखेगा, स्प्राइट 'स्टेटिक' है (हाँ, यह एनिमेट कर रहा है, लेकिन यह वास्तव में स्क्रीन के पार नहीं जा रहा है), और हर अब और फिर यह हिंसक रूप से हिलता है क्योंकि एक्सट्रपलेशन यह करने की कोशिश करता है ..... .. उममीद है कि इससे मदद मिलेगी


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

हाय @StevenStadnicki, बहुत धन्यवाद अपनी टिप्पणी के लिए, वहाँ एक प्रक्षेप मूल्य दिखा रेंडरर में पारित किया जा रहा उदाहरण के एक भीड़ हैं, कृपया इस देखें: mysecretroom.com/www/programming-and-software/... जो मैं कहाँ अनुकूलित से है मेरी कोड। मेरी सीमित समझ यह है कि यह अंतिम और अगले अपडेट के बीच की स्थिति को अंतिम अपडेट के बाद से समय की मात्रा के आधार पर प्रक्षेपित करता है - मैं मानता हूं कि यह एक बुरा सपना है! मैं आभारी रहूंगा यदि आप प्रस्ताव और विकल्प दे सकते हैं कि मेरे साथ काम करने में आसान हो - चियर्स :-)
BungleBonce

6
ठीक है, मैं कहता हूँ 'सिर्फ इसलिए कि आप कुछ के लिए कोड पा सकते हैं यह एक सर्वोत्तम अभ्यास नहीं है'। :-) इस मामले में, हालांकि, मुझे संदेह है कि जिस पृष्ठ को आपने लिंक किया है, वह प्रक्षेपित मूल्य का उपयोग करके यह पता लगाने के लिए करता है कि उसकी वस्तुओं को कहाँ प्रदर्शित किया जाए, लेकिन यह वास्तव में उनके साथ वस्तु स्थिति को अपडेट नहीं करता है; आप यह भी कर सकते हैं, बस एक ड्रॉ-स्पेसिफिक पोजिशन होने से जो हर फ्रेम की गणना करती है, लेकिन उस पोजिशन को ऑब्जेक्ट की वास्तविक 'फिजिकल' पोजिशन से अलग रखती है।
स्टीवन स्टैडनिक

हाय @StevenStadnicki, जैसा कि मेरे प्रश्न में उल्लिखित है (पैराग्राफ़ शुरू करना ("मैंने भी एक प्रतिलिपि बनाने की कोशिश की है"), मैं वास्तव में पहले से ही एक 'ड्रा केवल' स्थिति का उपयोग करने का प्रयास कर चुका हूं :-) क्या आप प्रक्षेप की एक विधि का प्रस्ताव कर सकते हैं I प्रस्तुत करना दिनचर्या के भीतर स्प्राइट की स्थिति में समायोजन करने की आवश्यकता नहीं है? धन्यवाद!
वनबोन्स

आपके कोड को देखकर ऐसा लगता है कि आप प्रक्षेप के बजाय एक्सट्रपलेशन कर रहे हैं।
दूर्जा ००।

जवाबों:


1

मैं अभी तक एक टिप्पणी पोस्ट नहीं कर सकता, इसलिए मैं इसे उत्तर के रूप में पोस्ट करूंगा।

अगर मैं समस्या को सही ढंग से समझता हूं, तो यह कुछ इस तरह है:

  1. पहले आप एक टक्कर है
  2. तब वस्तु की स्थिति को सही किया जाता है (संभवतः टक्कर का पता लगाने की दिनचर्या द्वारा)
  3. ऑब्जेक्ट की अद्यतन स्थिति रेंडर फ़ंक्शन को भेजी जाती है
  4. रेंडर फ़ंक्शन तब एक्सट्रपलेशन का उपयोग करके ऑब्जेक्ट के स्थान को अपडेट करता है
  5. अतिरिक्त वस्तु की स्थिति अब टकराव का पता लगाने वाली दिनचर्या को तोड़ देती है

मैं 3 संभावित समाधानों के बारे में सोच सकता हूं। मैं उन्हें उस क्रम में सूचीबद्ध करूंगा जो कम से कम IMHO के लिए सबसे अधिक वांछनीय है।

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

# 2 के लिए उदाहरण कोड।

if (collisionHasOccured)
    extrpolation = 0.0f;
else
    extrapolation = (float)(System.currentTimeMillis() + skipTicks - nextGameTick) / (float)skipTicks;

मुझे लगता है कि # 2 शायद सबसे तेज और सबसे आसान होगा, एक दौड़ने के लिए, हालांकि # 1 अधिक तार्किक रूप से सटीक समाधान लगता है। इस बात पर निर्भर करता है कि आप अपने डेल्टा समय समाधान को कैसे संभालते हैं # 1 को एक बड़े डेल्टा द्वारा उसी तरह से तोड़ा जा सकता है, इस स्थिति में आपको # 1 और # 2 दोनों का एक साथ उपयोग करना पड़ सकता है।

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

यह कहा जा रहा है, एकमात्र समस्या यह है कि वस्तु टकराव के बाद बढ़ रही है। यदि टकराव होता है तो वस्तु को उस दिशा में बढ़ना बंद कर देना चाहिए। तो, अगर कोई टक्कर है, तो इसे 0 पर सेट करें। यह रेंडर फ़ंक्शन को ऑब्जेक्ट को आगे बढ़ने से रोकना चाहिए।


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

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

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

मेरे उत्तर को अपडेट किया। आशा है कि मदद करता है
Aholio

धन्यवाद, मेरे मूल क्यू में देखें "जब यह बंद हो जाता है, तो यह थोड़ा बाएं / दाएं घूम रहा है" - इसलिए भले ही मैं अपने स्प्राइट को रोक देता हूं, एक्सट्रपलेशन अभी भी स्प्राइट को 'चलती' रखता है (वोबलिंग) - ऐसा इसलिए होता है क्योंकि मैं इसका उपयोग कर रहा हूं। " स्प्राइट के पुराने और वर्तमान पदों पर मेरे एक्सट्रपलेशन को काम करने के लिए, इसलिए भले ही स्प्राइट स्थिर हो, फिर भी यह अतिरिक्त प्रभाव 'एक्सट्रपलेशन' मान पर आधारित होता है, जो प्रत्येक फ़्रेम पुनरावृत्ति पर काम करता है। मैंने यह भी कहने की कोशिश की है कि 'अगर पुराना और वर्तमान पोज़ एक जैसा है तो एक्सट्रापोलेट न करें' लेकिन यह अभी भी काम नहीं कर रहा है, मैं वापस जाऊंगा और दूसरा लुक लूंगा!
जंगलबोन्स

0

ऐसा लगता है कि आपको पूरी तरह से भौतिकी के प्रतिपादन और अद्यतन को अलग करने की आवश्यकता है। आमतौर पर अंतर्निहित सिमुलेशन असतत समय-चरणों में चलेगा, और आवृत्ति कभी नहीं बदलेगी। उदाहरण के लिए, आप प्रत्येक सेकंड के 1/60 वें हिस्से में अपनी गेंद की गति को अनुकरण कर सकते हैं, और यह बात है।

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

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

यदि आप कार्यान्वयन के कुछ विवरणों को देखना चाहते हैं, तो मैंने इस लेख के बारे में एक लेख में पहले ही एक छोटा खंड यहाँ लिखा है । कृपया "टिमस्टैपिंग" नामक अनुभाग देखें।

यहाँ लेख से महत्वपूर्ण कोड है:

const float fps = 100
const float dt = 1 / fps
float accumulator = 0

// In units seconds
float frameStart = GetCurrentTime( )

// main loop
while(true)
  const float currentTime = GetCurrentTime( )

  // Store the time elapsed since the last frame began
  accumulator += currentTime - frameStart( )

  // Record the starting of this frame
  frameStart = currentTime

  // Avoid spiral of death and clamp dt, thus clamping
  // how many times the UpdatePhysics can be called in
  // a single game loop.
  if(accumulator > 0.2f)
    accumulator = 0.2f

  while(accumulator > dt)
    UpdatePhysics( dt )
    accumulator -= dt

  const float alpha = accumulator / dt;

  RenderGame( alpha )

void RenderGame( float alpha )
  for shape in game do
    // calculate an interpolated transform for rendering
    Transform i = shape.previous * alpha + shape.current * (1.0f - alpha)
    shape.previous = shape.current
    shape.Render( i )

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

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