Bagaimana cara membuat formula yang dapat disesuaikan untuk persyaratan peningkatan level RPG?

43

Saya mencoba membuat formula yang dapat dimodifikasi hanya dengan mengubah dua nilai: number_of_levels, dan last_level_experience. Ini untuk memungkinkan orang memodifikasi game untuk mengubah persyaratan leveling.

Saya sudah mendapatkannya sehingga saya dapat menentukan jumlah XP yang diperlukan untuk level terakhir, tetapi saya ingin dapat mengontrol XP yang diperlukan untuk level pertama, yang dalam kasus ini dapat sangat berbeda. Misalnya, jika saya memiliki 40 level, dan 1.000.000 XP untuk level terakhir, persyaratan level pertama adalah 625. Tetapi jika saya mengubah level menjadi 80, level pertama naik menjadi 156. Dalam kedua kasus, level terakhir membutuhkan 1.000.000.

Pasti ada beberapa cara untuk membuat komputer bekerja dengan kurva yang sesuai mengingat hanya dua nilai dasar ini.

#include <iostream>

int main()
{
    int levels = 40;
    if (levels < 2) levels = 2;

    int experience_for_last_level = 1e6;
    float fraction = 1.0 / levels;

    {
        int i = 0;
        float fraction_counter = fraction;
        int counter = levels;
        int total = 0;

        for (i = 1; i <= levels; ++i, fraction_counter += fraction, --counter)
        {
            int a = static_cast<int>(fraction_counter * experience_for_last_level / counter);

            std::cout <<"Level "<<i<<":  "<<a<<" ("<<counter<<")"<<"\n";

            total += a;
        }

        std::cout << "\nTotal Exp: " << total;
    }
}

Keluaran:

Level 1:  625   (40)      Level 15: 14423  (26)      Level 29: 60416  (12)
Level 2:  1282  (39)      Level 16: 16000  (25)      Level 30: 68181  (11)
Level 3:  1973  (38)      Level 17: 17708  (24)      Level 31: 77499  (10)
Level 4:  2702  (37)      Level 18: 19565  (23)      Level 32: 88888  (9)
Level 5:  3472  (36)      Level 19: 21590  (22)      Level 33: 103124 (8)
Level 6:  4285  (35)      Level 20: 23809  (21)      Level 34: 121428 (7)
Level 7:  5147  (34)      Level 21: 26250  (20)      Level 35: 145833 (6)
Level 8:  6060  (33)      Level 22: 28947  (19)      Level 36: 179999 (5)
Level 9:  7031  (32)      Level 23: 31944  (18)      Level 37: 231249 (4)
Level 10: 8064  (31)      Level 24: 35294  (17)      Level 38: 316666 (3)
Level 11: 9166  (30)      Level 25: 39062  (16)      Level 39: 487499 (2)
Level 12: 10344 (29)      Level 26: 43333  (15)      Level 40: 999999 (1)
Level 13: 11607 (28)      Level 27: 48214  (14)
Level 14: 12962 (27)      Level 28: 53846  (13)
Tongkat polisi
sumber
13
Masalah mendasarnya adalah bahwa ada banyak kurva level XP yang tak terhingga yang akan berakhir dengan level terakhir yang membutuhkan XP sebanyak itu. Anda tidak membatasi dimensi masalah, karena Anda belum menyatakan bagaimana Anda ingin XP berubah dari level ke level. Apakah Anda ingin kurva pertumbuhan eksponensial? Kurva pertumbuhan parabola? Yang linear? Masalah Anda tidak terpecahkan dalam kondisi saat ini. Secara pribadi, jika saya memodifikasi permainan, saya ingin kontrol lebih besar atas kurva XP daripada hanya angka tingkat terakhir dan XP tingkat terakhir. Saya ingin mengendalikan kurva itu sendiri.
Nicol Bolas
Saya dapat mengizinkan modder untuk mengontrol leveling melalui skrip.
Truncheon

Jawaban:

70

Meskipun ada banyak cara untuk memilihnya, sangat umum jika kurva leveling mengikuti aturan kekuasaan seperti yang berikut:

f(level) == A * exp(B * level)

Keuntungan utama dari formula ini dapat dengan mudah dijelaskan: untuk aturan yang diberikan, ada nilai tetap N sehingga setiap tingkat biaya N persen lebih dari yang sebelumnya .

Variabel awal Anda menambahkan batasan berikut:

f(1) - f(0) == experience_for_first_level
f(levels) - f(levels - 1) == experience_for_last_level

Dua persamaan, dua tidak diketahui. Ini terlihat bagus. Matematika sederhana memberi Adan B:

B = log(experience_for_last_level / experience_for_first_level) / (levels - 1);
A = experience_for_first_level / (exp(B) - 1);

Menghasilkan kode berikut:

#include <cmath>
#include <iostream>

int main(void)
{
    int levels = 40;
    int xp_for_first_level = 1000;
    int xp_for_last_level = 1000000;

    double B = log((double)xp_for_last_level / xp_for_first_level) / (levels - 1);
    double A = (double)xp_for_first_level / (exp(B) - 1.0);

    for (int i = 1; i <= levels; i++)
    {
        int old_xp = round(A * exp(B * (i - 1)));
        int new_xp = round(A * exp(B * i));
        std::cout << i << " " << (new_xp - old_xp) << std::endl;
    }
}

Dan output berikut:

1 1000          9 4125          17 17012        25 70170        33 289427
2 1193          10 4924         18 20309        26 83768        34 345511
3 1425          11 5878         19 24245        27 100000       35 412462
4 1702          12 7017         20 28943        28 119378       36 492389
5 2031          13 8377         21 34551        29 142510       37 587801
6 2424          14 10000        22 41246        30 170125       38 701704
7 2894          15 11938        23 49239        31 203092       39 837678
8 3455          16 14251        24 58780        32 242446       40 1000000
sam hocevar
sumber
12
Kalau saja semua jawaban ini direncanakan dan dipikirkan dengan baik.
Nate
Kurva di sini jauh lebih enak.
Truncheon
Jawaban yang bagus. Ini mungkin pertanyaan yang bodoh, tetapi bagaimana Anda menghitung Nyang Anda jelaskan di atas? Bagaimana jika Anda ingin membuat Nvariabel pluggable? Beri tahu saya jika saya harus mengajukan pertanyaan terpisah untuk ini.
Daniel Kaplan
1
@tTyT hubungan antara Ndan Badalah exp(B) = 1 + N, atau B = log(1 + N). Jadi jika Anda ingin setiap level membutuhkan mis. 15% lebih tinggi dari yang sebelumnya, Anda perlu B = log(1 + 0.15) = 0.13976.
sam hocevar
17

Jangan lupa untuk membulatkan angka setelah Anda mengetahui kurva Anda. Tidak masuk akal untuk mengatakan pada pemain bahwa ia membutuhkan 119.378 poin pengalaman untuk mencapai level berikutnya - karena orang itu akan selalu memahaminya sebagai "sekitar 120.000". Dengan demikian Anda akan lebih baik melakukan pembulatan diri sendiri, dan menyajikan hasil "bersih" kepada pemain Anda. Misalnya kode berikut (yang meluas pada Sam Hocevar) akan berusaha untuk membulatkan ≈2,2 angka signifikan (jelas bahwa konstanta dapat diubah sesuai keinginan Anda):

from math import exp, log

levels = 40
xp_for_first_level = 1000
xp_for_last_level = 1000000

B = log(1.0 * xp_for_last_level / xp_for_first_level) / (levels - 1)
A = 1.0 * xp_for_first_level / (exp(B) - 1.0)

def xp_for_level(i):
    x = int(A * exp(B * i))
    y = 10**int(log(x) / log(10) - 2.2)
    return int(x / y) * y

for i in range(1, levels+1):
    print( "%d:  %d" % (i, xp_for_level(i) - xp_for_level(i-1)) )

Outputnya adalah:

1:  1000     9:  4200     17:  17100    25:  70000     33:  287000
2:  1190    10:  4900     18:  20300    26:  84000     34:  340000
3:  1420    11:  5900     19:  24200    27:  100000    35:  420000
4:  1710    12:  7000     20:  28700    28:  119000    36:  490000
5:  2030    13:  8400     21:  34000    29:  142000    37:  590000
6:  2420    14:  10000    22:  42000    30:  171000    38:  700000
7:  2870    15:  11900    23:  49000    31:  203000    39:  840000
8:  3400    16:  14200    24:  59000    32:  242000    40:  1000000
Pasha
sumber