जानबूझकर अभेद्यता के साथ रेट्रो / एनईएस शैली भौतिकी को फिर से बनाना


16

पृष्ठभूमि:

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

गुरुत्वाकर्षण को खिलाड़ी की वाई गति में 0.25 / फ्रेम की दर से जोड़ा जाता है।

जब खिलाड़ी कूदता है, तो उसकी वाई गति -4.64453125 पर सेट होती है। जंप वक्र के बाकी गुरुत्वाकर्षण के लिए छोड़ दिया जाता है।

जैसा कि खिलाड़ी चढ़ता है उसका ऊर्ध्वाधर वेग 0.25 / फ्रेम की दर से 0 में परिवर्तित हो जाता है। जब खिलाड़ी का वेग शून्य से कम मूल्य पर पहुंचता है, हालांकि, वेग एक अलग पैटर्न का अनुसरण करता है। हर फ्रेम में 0.25 की कमी के बजाय, यह इस पैटर्न का अनुसरण करता है:

[1.75, -0.25, -0.25, -0.25, 1.75, -0.25, -0.25, -0.25, 1.75, ...]

यह पूर्णांक अतिप्रवाह के साथ कुछ करने के लिए प्रतीत होता है।

डेटा:

यहाँ मूल से डेटा का एक डंप है। यह वेग की एक तालिका है।

Jump Curve

Y-Hi Y-Lo    Decimal        Change/Frame
4    165     4.64453125     ?
4    101     4.39453125     -0.25
4    37      4.14453125     -0.25
3    229     3.89453125     -0.25
3    165     3.64453125     -0.25
3    101     3.39453125     -0.25
3    37      3.14453125     -0.25
2    229     2.89453125     -0.25
2    165     2.64453125     -0.25
2    101     2.39453125     -0.25
2    37      2.14453125     -0.25
1    229     1.89453125     -0.25
1    165     1.64453125     -0.25
1    101     1.39453125     -0.25
1    37      1.14453125     -0.25
0    229     0.89453125     -0.25
0    165     0.64453125     -0.25
0    101     0.39453125     -0.25
0    37      0.14453125     -0.25
-1   229     -1.89453125    1.75
-1   165     -1.64453125    -0.25
-1   101     -1.39453125    -0.25
-1   37      -1.14453125    -0.25
-2   229     -2.89453125    1.75
-2   165     -2.64453125    -0.25
-2   101     -2.39453125    -0.25
-2   37      -2.14453125    -0.25
-3   229     -3.89453125    1.75
-3   165     -3.64453125    -0.25
-3   101     -3.39453125    -0.25
-3   37      -3.14453125    -0.25
-4   229     -4.89453125    1.75
-4   165     -4.64453125    -0.25
-4   101     -4.39453125    -0.25
-4   37      -4.14453125    -0.25
-5   229     -5.89453125    1.75
-5   165     -5.64453125    -0.25
-5   101     -5.39453125    -0.25
-5   37      -5.14453125    -0.25
-6   229     -6.89453125    1.75

मुसीबत:

अपने खेल में मैं इस प्रभाव को प्राप्त करने में सक्षम नहीं रहा हूं। जब वेग शून्य से कम होता है तो यह ऊपर वर्णित पैटर्न के बजाय 0.25 तक नियमित रूप से कम होता रहता है। पूरे और भिन्नात्मक भागों को अलग-अलग संग्रहीत करने के बजाय, मैं उन्हें एक ही फ्लोट में एक साथ संग्रहीत कर रहा हूं।

यह प्रभाव कैसे प्राप्त किया जा सकता है?


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

मुझे लगता है कि आपको उस हिस्से को पोस्ट करने की आवश्यकता है जिसे आप वेग बदल रहे हैं और कोड पर समस्या और आपकी आवश्यकता का सटीक वर्णन करें।
अली

2
@ गजीत क्या? उन्होंने समस्या का सटीक वर्णन किया।
माईक सेमर

@maikSemder: मैं सिर्फ इस बारे में उत्सुक हूं कि उन्होंने अपने कोड के आधार पर समाधान देने के लिए भौतिकी इंजन को कैसे लागू किया।
अली

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

जवाबों:


16
one byte for the whole number and another for the fractional part

मूल रूप से आपको बस low0.25 को घटाने के लिए 64 से घटाना होगा, क्योंकि एक 8 बिट मूल्य में 256 मान हो सकते हैं, इसलिए 256 * 0.25 = 64 जब low1 से भी घटाना होता है high

डिस्क्लेमर: यह कोड जानबूझकर गलत है जब नकारात्मक संख्या की बात आती है, तो यह प्रश्न में वर्णित संख्यात्मक विसंगतियों को मॉडल करना है। तुलनात्मक कारणों से निश्चित उत्तर वर्ग को संभालने वाले एक उचित ऋणात्मक संख्याओं के कार्यान्वयन को इस उत्तर के तल पर पाया जा सकता है।

struct velocity
{
    char high;
    unsigned char low;

    // fall -0.25
    void fall()
    {
        if(low < 64) --high;
        low -= 64;;
    }

    // convert to a float
    float toFloat() const
    {
        float ret = high;
        float frac = (float)low / 256.0f;
        if(high >= 0) ret += frac;
        else ret -= frac;
        return ret;
    }

    // convert from float
    void fromFloat(float f)
    {
        high = (char)f;
        float frac = f - high;
        low = (unsigned char)(frac * 256.0f);
    }
};

velocity v;
v.high = 4;
v.low = 165;    
for(int i = 0; i < 30; ++i)
{
    printf("%2d     %3d   %f\n", v.high, v.low, v.toFloat());
    v.fall();
}

संपादित करें : मैंने फ्लोट और आउटपुट से फ्लोट और आउटपुट में रूपांतरण जोड़ा है

उत्पन्न आउटपुट आपकी तालिका के समान है:

 4     165   4.644531
 4     101   4.394531
 4      37   4.144531
 3     229   3.894531
 3     165   3.644531
 3     101   3.394531
 3      37   3.144531
 2     229   2.894531
 2     165   2.644531
 2     101   2.394531
 2      37   2.144531
 1     229   1.894531
 1     165   1.644531
 1     101   1.394531
 1      37   1.144531
 0     229   0.894531
 0     165   0.644531
 0     101   0.394531
 0      37   0.144531
-1     229   -1.894531
-1     165   -1.644531
-1     101   -1.394531
-1      37   -1.144531
-2     229   -2.894531
-2     165   -2.644531
-2     101   -2.394531
-2      37   -2.144531
-3     229   -3.894531
-3     165   -3.644531
-3     101   -3.394531
-3      37   -3.144531
-4     229   -4.894531
-4     165   -4.644531
-4     101   -4.394531
-4      37   -4.144531
-5     229   -5.894531
-5     165   -5.644531
-5     101   -5.394531
-5      37   -5.144531
-6     229   -6.894531

इसके विपरीत यह निश्चित बिंदु वर्ग ऋणात्मक संख्याओं को ठीक से संभालता है:

#include <iomanip>
#include <iostream>

struct fixed_point
{
    union
    {
        struct
        {
            unsigned char low;
            signed char high;
        };
        short s;
    };

    float toFloat() const
    {
        fixed_point tmp;
        if(high < 0) tmp.s = ~s;
        else tmp.s = s;

        float ret = tmp.high;
        float frac = (float)tmp.low / 256.0f;
        ret += frac;
        if(high < 0) ret = 0 - ret;
        return ret;
    }

    void fromFloat(float f)
    {
        float tmp;
        if(f < 0.0f) tmp = -f;
        else tmp = f;

        high = (char)tmp;
        float frac = tmp - high;
        low = (unsigned char)(frac * 256.0f);

        if(f < 0.0f) s = ~s;
    }

    fixed_point operator+(const fixed_point &fp) const
    {
        fixed_point ret;
        ret.s = s + fp.s;
        return ret;
    }

    fixed_point operator-(const fixed_point &fp) const
    {
        fixed_point ret;
        ret.s = s - fp.s;
        return ret;
    }

    void print(const char *msg) const
    {
        std::cout << msg << ":" << std::endl;
        std::cout << std::hex << std::uppercase;
        // cout'ing the hex value for a char is kind of a pain ..
        unsigned int _high = 0;
        memcpy(&_high, &high, 1);
        std::cout << "  high : 0x" << std::setfill('0') << std::setw(2) << _high << std::endl;
        unsigned int _low = 0;
        memcpy(&_low, &low, 1);
        std::cout << "  low  : 0x" << std::setfill('0') << std::setw(2) << _low << std::endl;
        std::cout << "  all  : 0x" << std::setfill('0') << std::setw(4) << s << std::endl;
        std::cout << "  float: " << toFloat() << std::endl;
        std::cout << std::endl;
    }
};

1
@ ज़ैक हाँ सुनिश्चित करें, मेरी स्थिति संरचना देखें, मैंने फ्लोट फ़ंक्शन में रूपांतरण जोड़ा है जो वास्तव में ऐसा करता है।
मिक सेमर

1
@Zack ने एक onFloat रूपांतरण भी जोड़ा
Maik Semder

1
@ माईक यू सर, एक सज्जन हैं। सहायता के लिए धन्यवाद। यह मुझे पटरी पर लौटा देगा।
ज़ैक द ह्यूमन

1
@ आप बहुत स्वागत करते हैं, ख़ुशी से मदद करने के लिए, विशेष रूप से इस तरह के एक अच्छे सवाल के लिए :)
Maik Semder

1
@ यदि आप रुचि रखते हैं, तो मैंने एक निश्चित बिंदु वर्ग जोड़ा है जो तुलना के लिए नकारात्मक संख्या को ठीक से संभालता है
Maik Semder
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.