Tái tạo vật lý theo phong cách retro / NES với sự thiếu quyết đoán có chủ ý


16

Lý lịch:

Tôi đang gặp vấn đề khi điều chỉnh đường cong nhảy cho dự án làm lại nền tảng retro của tôi. Trò chơi ban đầu dành cho NES và vận tốc của người chơi được lưu trữ thành hai phần riêng biệt: một byte cho toàn bộ số và một phần khác cho phần phân số.

Trọng lực được thêm vào tốc độ Y của người chơi với tốc độ 0,25 / khung hình.

Khi người chơi nhảy, tốc độ Y của anh ta được đặt thành -4,64453125. Phần còn lại của đường cong nhảy được để lại trọng lực.

Khi người chơi tăng tốc độ thẳng đứng của mình hội tụ về 0 với tốc độ 0,25 / khung hình. Tuy nhiên, khi vận tốc của người chơi đạt đến một giá trị nhỏ hơn 0, thì vận tốc sẽ thay đổi theo một kiểu khác. Thay vì giảm dần 0,25 mỗi khung hình, nó tuân theo mô hình này:

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

Nó dường như có một cái gì đó để làm với tràn số nguyên.

Dữ liệu:

Đây là một bãi chứa dữ liệu từ bản gốc. Đó là một bảng vận tốc.

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

Vấn đề:

Trong trò chơi của tôi, tôi không thể đạt được hiệu ứng này. Khi vận tốc nhỏ hơn 0, nó tiếp tục giảm thường xuyên 0,25 thay vì mô hình được mô tả ở trên. Thay vì lưu trữ toàn bộ và các phần phân đoạn riêng biệt, tôi đang lưu trữ chúng cùng nhau trong một lần nổi.

Làm thế nào có thể đạt được hiệu ứng này?


1
Thành thật mà nói, tôi chỉ cần chụp ảnh màn hình để tìm ra chiều cao / chiều dài nhảy tối đa của anh ấy bằng pixel và chỉ cần điều chỉnh chức năng hiện tại của bạn để trông giống như có thể. Bạn nói rằng sự thiếu quyết đoán là cố ý, vì vậy điều này không nên gây ra vấn đề?
Jonathan Connell

Tôi nghĩ rằng bạn cần phải đăng phần bạn đang thay đổi vận tốc và mô tả chính xác vấn đề và nhu cầu của bạn về mã.
Ali1S 232

2
@Gajet gì? Ông đã mô tả chính xác vấn đề.
Maik

@maikSemder: Tôi chỉ tò mò về cách anh ấy triển khai công cụ vật lý để đưa ra giải pháp dựa trên mã của mình.
Ali1S232

Hãy cho tôi biết nếu bạn cần thêm chi tiết, tôi không muốn viết một bài đăng khổng lồ vì sợ tôi sẽ nhận được phản hồi.
Zack The Human

Câu trả lời:


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

Về cơ bản, bạn chỉ cần trừ 64 lowđể trừ 0,25, bởi vì giá trị 8 bit có thể có 256 giá trị, vì vậy 256 * 0,25 = 64 Khi có một dòng chảy trong lowcũng trừ đi 1 high.

Tuyên bố từ chối trách nhiệm: Mã này là cố ý sai khi nói đến số âm, nó được cho là mô hình các dị thường số được mô tả trong câu hỏi. Vì lý do so sánh, việc thực hiện một số âm thích hợp xử lý lớp điểm cố định có thể được tìm thấy ở dưới cùng của câu trả lời này.

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();
}

EDIT : Tôi cũng đã thêm chuyển đổi sang float và từ float và đầu ra

Đầu ra được tạo giống như trong bảng của bạn:

 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

Ngược lại, lớp điểm cố định này xử lý đúng các số âm:

#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 có chắc chắn, xem cấu trúc vị trí của tôi, tôi đã thêm một chuyển đổi sang chức năng float mà thực hiện chính xác điều đó.
Maik

1
@Zack cũng đã thêm một chuyển đổi từFloat
Maik Semder

1
@Maik Bạn ơi, là một quý ông. Cảm ơn đã giúp đỡ. Điều này sẽ đưa tôi trở lại theo dõi.
Zack The Human

1
@Zack bạn rất hoan nghênh, rất vui khi được giúp đỡ, đặc biệt là cho một câu hỏi hay như vậy :)
Maik Semder

1
@Zack trong trường hợp bạn quan tâm, tôi đã thêm một lớp điểm cố định xử lý các số âm đúng để so sánh
Maik Semder
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.