Làm thế nào để tạo công thức điều chỉnh cho các yêu cầu tăng cấp RPG?


44

Tôi đang cố gắng tạo một công thức có thể được sửa đổi chỉ bằng cách thay đổi hai giá trị: number_of_levels và last_level_experience. Điều này là để cho phép mọi người điều chỉnh trò chơi để thay đổi các yêu cầu lên cấp.

Tôi đã có nó để tôi có thể chỉ định số lượng XP cần thiết cho lần tăng cấp cuối cùng, nhưng tôi muốn có thể kiểm soát XP cần thiết cho cấp độ đầu tiên, trong trường hợp này có thể khác nhau rất nhiều. Ví dụ: nếu tôi có 40 cấp độ và 1.000.000 XP cho cấp độ cuối cùng, yêu cầu tăng cấp độ đầu tiên là 625. Nhưng nếu tôi thay đổi cấp độ thành 80, cấp độ đầu tiên trở thành 156. Trong cả hai trường hợp, cấp độ cuối cùng cần 1.000.000.

Phải có một số cách để làm cho máy tính tìm ra một đường cong phù hợp chỉ với hai giá trị cơ bản này.

#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;
    }
}

Đầu ra:

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)

13
Vấn đề cơ bản là có số đường cong cấp XP sẽ kết thúc với cấp độ cuối cùng cần nhiều XP. Bạn không bị hạn chế kích thước của vấn đề, bởi vì bạn chưa nói rõ bạn muốn XP thay đổi từ cấp này sang cấp khác như thế nào . Bạn có muốn một đường cong tăng trưởng theo cấp số nhân? Một đường cong tăng trưởng parabol? Một tuyến tính? Vấn đề của bạn là không thể giải quyết trong trạng thái hiện tại của nó. Cá nhân, nếu tôi đang điều chỉnh trò chơi, tôi muốn kiểm soát nhiều hơn đối với đường cong XP hơn là chỉ số cấp cuối cùng và cấp XP cuối cùng. Tôi muốn kiểm soát đường cong thực tế.
Nicol Bolas

Tôi có thể cho phép các modder kiểm soát việc cân bằng thông qua một tập lệnh.
Truncheon

Câu trả lời:


71

Mặc dù có vô số cách để chọn chúng, nhưng thông thường các đường cong cân bằng tuân theo quy tắc sức mạnh, chẳng hạn như sau:

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

Ưu điểm chính của công thức này có thể dễ dàng giải thích: đối với một quy tắc nhất định, có một giá trị N cố định sao cho mỗi cấp có giá N phần trăm nhiều hơn so với quy tắc trước .

Các biến ban đầu của bạn thêm các hạn chế sau:

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

Hai phương trình, hai ẩn số. Nhìn có vẻ tốt. Toán đơn giản cho AB:

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

Kết quả trong mã sau đây:

#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;
    }
}

Và đầu ra sau:

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

12
Nếu chỉ có tất cả các câu trả lời đã được lên kế hoạch tốt và nghĩ ra.
Nate

Các đường cong ở đây là ngon miệng hơn nhiều.
Truncheon

Câu trả lời tốt. Đây có thể là một câu hỏi ngu ngốc, nhưng làm thế nào để bạn tính toán Nmà bạn mô tả ở trên? Điều gì nếu bạn muốn làm cho Nbiến pluggable? Hãy cho tôi biết nếu tôi nên hỏi một câu hỏi riêng cho việc này.
Daniel Kaplan

1
@tieTYT mối quan hệ giữa NBexp(B) = 1 + N, hoặc B = log(1 + N). Vì vậy, nếu bạn muốn mỗi cấp để yêu cầu ví dụ như 15% nhiều hơn so với trước đó, bạn sẽ cần B = log(1 + 0.15) = 0.13976.
sam hocevar

18

Đừng quên làm tròn số sau khi bạn tìm ra đường cong của mình. Sẽ không có ý nghĩa gì khi nói với người chơi anh ta cần 119.378 điểm kinh nghiệm để đạt cấp độ tiếp theo - bởi vì người đó sẽ luôn hiểu nó là "khoảng 120.000". Do đó, bạn sẽ tốt hơn khi tự làm tròn số và trình bày kết quả "sạch" cho người chơi của mình. Ví dụ, đoạn mã sau (mở rộng theo Sam Hocevar) sẽ cố gắng làm tròn đến .22,2 chữ số có nghĩa (rõ ràng là hằng số có thể được điều chỉnh theo ý muốn):

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)) )

Đầu ra là:

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
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.