의도적으로 부정확 한 레트로 / NES 스타일의 물리 재현


16

배경:

레트로 플랫 포머 리메이크 프로젝트에서 점프 곡선을 올바르게 얻는 데 문제가 있습니다. 원래 게임은 NES를위한 것이며, 플레이어의 속도는 정수의 바이트와 분수의 다른 두 부분으로 저장됩니다.

중력은 플레이어의 Y 속도에 0.25 / 프레임의 속도로 추가됩니다.

플레이어가 점프하면 Y 속도가 -4.64453125로 설정됩니다. 나머지 점프 커브는 중력에 맡겨져 있습니다.

플레이어가 상승함에 따라 그의 수직 속도는 0.25 / 프레임의 속도로 0으로 수렴합니다. 그러나 플레이어의 속도가 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보다 작 으면 위에서 설명한 패턴이 아닌 정기적으로 0.25 씩 계속 감소합니다. 전체 및 분수 부분을 별도로 저장하는 대신 단일 부동으로 함께 저장합니다.

이 효과를 어떻게 얻을 수 있습니까?


1
솔직히 말해서 스크린 샷을 찍어 최대 점프 높이 / 길이를 픽셀 단위로 해결하고 현재 기능을 가능한 한 조정하기 위해 조정했습니다. 당신은 부정확성이 의도적이라고 말하는데 이것이 문제를 일으키지 않아야합니까?
Jonathan Connell 2016 년

속도를 변경하는 부분을 게시하고 문제와 요구 사항을 코드에 정확하게 설명해야한다고 생각합니다.
Ali1S232 2016

2
@Gajet 무엇? 그는 문제를 정확하게 설명했다.
Maik Semder

@maikSemder : 자신의 코드를 기반으로 솔루션을 제공하기 위해 물리 엔진을 어떻게 구현했는지 궁금합니다.
Ali1S232

더 자세한 정보가 필요하면 알려주세요. 나는 tl; dr 응답을 얻을 수 있다는 두려움에 대해 거대한 게시물을 작성하고 싶지 않았습니다.
Zack The Human

답변:


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

low8 비트 값은 256 값을 가질 수 있기 때문에 기본적으로 64에서 빼기 만하면 low됩니다 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
@Zack 예, 내 위치 구조를 보았습니다. 정확히 수행하는 부동 함수로 변환을 추가했습니다.
Maik Semder

1
@Zack은 또한 fromFloat 변환을 추가했습니다
Maik Semder

1
@Maik 선생님, 신사입니다. 도와 주셔서 감사합니다. 이것은 나를 다시 궤도에 올릴 것이다.
Zack The Human

1
@Zack 당신은 매우 환영합니다, 특히 좋은 질문에 도움을 드리겠습니다 :)
Maik Semder

1
@Zack 관심이 있으시다면, 비교를 위해 음수를 올바르게 처리하는 고정 소수점 클래스를 추가했습니다
Maik Semder
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.