Как я могу рассчитать текущий уровень из общего XP, когда каждый уровень требует пропорционально больше XP?

33

В моей игре XP, чтобы достичь следующего уровня, это Текущий уровень × Порог уровня . Учитывая это, как я могу получить свой текущий уровень из общего количества когда-либо заработанных XP ?


Например:

Level Threshold = 50
Current Level = 1

Начиная с уровня 1, мне нужно (1 × 50) = 50 XP, чтобы добраться до уровня 2, и так далее.

Level 1: 50 XP needed to reach level 2
Level 2: 100 more XP needed to reach level 3
Level 3: 150 more XP needed to reach level 4

Другими словами, таблица прогрессии выглядит следующим образом:

Level 1: 0 XP to 49 XP
Level 2: 50 XP to 149 XP 
Level 3: 150 XP to 299 XP
Level 4: 300 XP to 499 XP

Если у меня 300 XP, я только достигну уровня 4. Как я могу рассчитать это вообще?

Джей ван Дийк
источник
Связано с переполнением стека: вычисление треугольного корня без sqrt
Дамиан Йеррик
Количество XP, необходимое для следующего уровня, не увеличивается, чем выше текущий уровень?
Мачта
Итак, первый вопрос, на который вам нужно ответить: каково «пороговое» значение для каждого уровня? Исходя из вашего примера, если мы предполагаем, что 300 XP - это минимум для достижения уровня 4, то ваш порог увеличивается до 75 после уровня 3. Как только вы определите частоту, с которой порог поднимается, вы можете придумать алгоритм для его вычисления. как другие люди пытаются сделать в своих ответах
Taegost
3
Majte дает хороший ответ о том, как рассчитать его, но «лучший» ответ - просто не рассчитать его… сохранить общий опыт, но также сохранить текущий уровень и дельту XP. Сбрасывайте дельту каждый раз, когда вы повышаете уровень, и у вас есть вся необходимая информация (уровень, уровень + 1, общее количество очков опыта, дельта очков опыта), чтобы легко вычислить все, что вам нужно использовать / отображать
Jon Story
@JonStory Действительно. Я подробно остановился на этом в своем ответе, потому что, ну кто же на самом деле рассчитывает уровень динамически все время? Этот вопрос, по сути, всего лишь математический вопрос, поскольку он вообще не учитывает роль уровней в игровой системе.
zxq9

Ответы:

33

Разрабатывая математику и решая задачи на Levelоснове опыта XP, мы получаем:

LеvеLзнак равно1+1+8×Иксп÷502

Например, каков уровень игрока для ?Икспзнак равно300

1+1+8×300÷502знак равно4

Как просили.

Или для чего нужен уровень XP = 100000?

1+1+8×100000÷502=63

В более общем виде для произвольного начального порога на уровне 1:

Level=1+1+8×threshold÷502

Вы также можете сделать обратное и рассчитать XPнеобходимый для любого данного уровня, решив вышеупомянутую формулу для XP.

Икспзнак равно(LеvеL2-LеvеL)×TчасреsчасоLd2

Обратите внимание, что приведенная выше формула работает с дробями, но вам нужно округлить до следующего целочисленного значения. Например, в C ++ / C # вы можете использовать (int) Level.

Чтобы получить приведенную выше формулу замкнутой формы, я использовал разностные уравнения, суммирование Гаусса и квадратную формулу.

Если вы заинтересованы в решении этой формулы шаг за шагом ...

Мы делаем рекурсивный алгоритм, начав наши соображения, которые в конечном итоге Experience(next_level) = Experience(current_level) + current_level*50 .

Например, для получения имеем:ИкспLеvеL3

ИкспLеvеL3знак равноИкспLеvеL2+2×50

Где, 2*50исходя из запроса ОП, опыт, необходимый для достижения следующего уровня, является текущим уровнем * 50.

Теперь подставим в формулу с той же логикой. То есть:ИкспLеvеL2

Подставим в приведенную выше формулу:ИкспLеvеL2знак равноИкспLеvеL1+2×50

ИкспLеvеL3знак равноИкспLеvеL1+1×50+2×50

и составляет всего 50, что является нашей отправной точкой. следовательноИкспLеvеL1

XpLevel3=50+2×50=150

Мы можем распознать схему рекурсивного вычисления более высоких уровней и конечную цепочку суммирования.

XpLevelN=50+2×50+3×50+...+(N1)×50=i=0n1i×50

Где N - уровень, который должен быть достигнут. Чтобы получить XP для уровня N, нам нужно решить для N.

XpLevelN÷50=i=0n1i

Теперь правая рука просто суммирование от 1 до N-1, которое может быть выражено известным гауссова суммирования . следовательноN×(N+1)÷2N

ИкспLеvеLN÷50знак равноN(N+1)÷2-N

или просто

2(XpLevelN50)÷50=N(N+1)2N

Наконец, все на одной стороне:

0=N2N2×XpLevelN÷50

Теперь это квадратичная формула, дающая отрицательное и положительное решение, из которых важен только положительный, поскольку нет отрицательных уровней. Теперь мы получаем:

N=1+1+4×2×XpLevelN502

The current level conditional on XP and linear threshold is therefore:

Level=1+1+8×XP÷threshold2

Note Knowing these steps can be useful to solve for even more complex progressions. In the RPG realm you will see besides a linear progression as here, the actually more common fractional power or square relationship, e.g. Level=XP5.0. However, for game implementation itself, I believe this solution to be less optimal as ideally you should know all your level progressions beforehand instead of calculating them at runtime. For my own engine, I use therefore pre-processed experience tables, which are more flexible and often faster. However, to write those tables first, or, to just merely ask yourself what XP is needed to, let's say, obtain Level 100, this formula provides the quickest way aimed at answering the OP's specific question.

Edit: This formula is fully working as it should and it outputs correctly the current level conditional on XP with a linear threshold progression as requested by the OP. (The previous formula outputted "level+1" by assuming the player started from Level 0, which was my erring--I had solved it on my lunch break by writing on a small tissue! :)

Majte
источник
Comments are not for extended discussion; this conversation has been moved to chat.
Josh
@JoshPetrie The problem for us who just saw this question later, is that the chat link is broken. Any way of recovering it?
MAnd
@MAnd I undeleted it, but it will go away again on its own in another eight days or so.
Josh
25

The simple and generic solution, if you don't need to repeat this calculation millions of times per second (and if you do, you're probably doing something wrong), is just to use a loop:

expLeft = playerExp
level = 1
while level < levelCap and expLeft >= 0:
    expLeft = expLeft - expToAdvanceFrom(level)
    level = level + 1

if expLeft < 0: level = level - 1     # correct overshoot

The big advantage of this method, besides requiring no complicated mathematics, is that it works for any arbitrary exp-per-level function. If you like, you can even just make up arbitrary exp values per level, and store them in a table.

If you do (for some strange reason) need an even faster solution, you can also precalculate the total amount of exp needed to reach each level, store this in a table, and use a binary search to find the player's level. The precalculation still takes time proportional to the total number of levels, but the lookup then requires only time proportional to the logarithm of the number of levels.

Ilmari Karonen
источник
4
Most flexible solution. And since speed doesn't matter for a one-time computation, best one i guess.
GameAlchemist
4
@Majte: Perhaps I wasn't clear enough. I'm not suggesting that any of the posted solutions would require "millions of iterations". What I meant to say is that, unless you somehow need to calculate the player's level millions of times per second, my (naïve brute-force) solution is more than fast enough. The other solutions, based on algebraically deriving a closed-form formula for the level as a function of exp, may be even faster -- but for code that's only rarely called (and anything less than, say, 1,000 times a second surely counts as "rare" here), it'll make no noticeable difference.
Ilmari Karonen
2
Ohh, I see now, sorry. I fully agree with you and you offer a great alternative for user defined advancement steps per level. But then, probably use preprocessed tables after all.
Majte
2
The simplicity of this solution makes it a clear winner. Do not discount the value of readability and maintainability.
Mauser
1
Computers are good at doing menial tasks, not people. You want to simplify the persons life, the programmer, at the expense of the computer if necessary. Using this solution, you only have to write one method, the forward, not the forward and reverse. The simplest solution is not the one he has in code, but building that lookup table. Ram is cheap, use it.
Mauser
11

The question has been answered with code, but I think it should be answered with math. Someone might want to understand instead of just copy and paste.

Your system is easily described by a recurrence relation:

XPLevel+1=XPLevel+LevelThreshold

Which offers a nice simple closed form solution for XP:

XPLevel=(Level1)LevelThreshold2

Which we can solve for Level:

Level=Threshold2+8XPThreshold2Threshold+12

(truncate to integer, because the player needs all the required XP to get any of the level-up bonus)

MickLH
источник
2
I like this answer. Clear and concise.
Almo
Привет, Мик; Прошло много времени с тех пор, как я установил повторные отношения Не могли бы мы также указать базовый вариант, XP_Level(0) = 50и тогда мы можем просто избежать решения? Есть ли плюсы, плюсы, минусы? Я думаю, что было бы хорошо затронуть этот ответ. +1
Вон Хилтс
@VaughanHilts I'm not sure how your notation works or what you're asking, feel free to ping me in gamedev chat?
MickLH
I understood the code answer much easier than this.
Pharap
Keep working at it @Pharap. When I was a teenager I also understood code more easily than math, but with experience and knowledge the math will become obvious everywhere in life.
MickLH
10

Here's one approach to solving the problem using basic algebra. If you don't care about the steps, skip to the bottom.

An easy thing to come up with is, given a level n, the total experience e needed to obtain that level:

e = sum from k=1 to n of (t(k-1))

The t term stands for the increase in XP needed per level - 50, in the example.

We can solve the above using the formula for arithmetic sequences (sum identity):

e = t/2 * n(n-1)

However, we want the opposite formula - the player's level given their total experience. What we really want to do is solve for the level, n. First, let's group the terms:

n^2 - n - 2e/t = 0

Now we can use the quadratic formula:

n = (1 + sqrt(1+8e/t))/2

Final equation:

level = 0.5 + sqrt(1 + 8*(total experience)/(threshold)) / 2
Chaosed0
источник
1
Thanks for the answer. But what if I want to change the Threshold to other variable? Instead of 50 I would like to use 50000 or 1000 0for that matter. How should I modify the equation?
JayVDiyk
2
Yes, the solutions should be the same. I wanted to lay out the steps to the solution in case anyone was interested. @JayVDiyk - will edit post.
Chaosed0
Это было немного дерзко с вашей стороны, так как я прокомментировал, что выложу полное решение после работы;) все в порядке, я не против. Обычно нужно ответить со ссылкой на правильный ответ и записать расширение. Нервный ум, любил, чтобы решить это. Желаю больше вопросов, как это было размещено здесь.
Majte
Извините, должно быть, пропустил этот комментарий. Не хотел выкрасть это из-под тебя или что-то в этом роде - я буду помнить об этом в следующий раз. Ваш ответ определенно более тщательный, чем мой после редактирования!
Chaposed0
1
+1; без обид на @Majte, я лично нахожу ваше объяснение более читабельным.
Ильмари Каронен
3

Весь математический анализ здесь очень важен по разным причинам, некоторые из которых применимы к разработке игр.

НО

Это сайт по разработке игр, а не сайт по математике. Итак, давайте обсудим, как эти вещи работают не как алгоритмические ряды, а как наборы , потому что это та математика, которая применима к прокачке в играх, которые вы действительно можете разработать для продажи, и именно эта система лежит в основе большинства (но не всех) прокачки системы (по крайней мере, исторически).

Игроки, как правило, предпочитают красивые круглые числа, которые легко запомнить и визуализировать, и нигде это не является более важным, чем в игровой системе, основанной на уровнях, где игроку требуется X сумм очков опыта, чтобы перейти к уровню Y.

Есть две веские причины для выбора круглых чисел:

  • Сам уровень опыта - это хорошее круглое число «100; 200; 1 000 000; и т. Д.»
  • Дельта между уровнями имеет тенденцию быть еще одним хорошим круглым числом, на которое игрок может взглянуть и вычислить в своей голове.

Круглые числа приятны. Цель игр - быть приятным. Приятность очень важна, тем более что игровые дилеммы зачастую не очень приятны по дизайну.

Почему это важно иметь в виду?

Большинство алгоритмов составных рядов не дают хороших круглых чисел

Большинство серий не останавливаются на красивой точке (каждый ответ, который я видел здесь до сих пор, продолжается вечно). Так что же нам делать? Мы приближаемся, а затем определяем, какой набор уровней должен применяться к игровой системе .

Как мы узнаем, какие приближения являются подходящими? Мы рассмотрим, в чем смысл прокачки игровой системы.

В большинстве игр есть ограничения уровня, которые в какой-то момент вступают в силу. Есть несколько способов, которыми это может сыграть:

  • Ограничение встречается относительно рано, когда система уровней существует только для того, чтобы помочь игрокам пройти первый этап игры целенаправленным образом, чтобы заставить их изучить полную игровую систему. Как только они «полностью выросли», начинается длинная игра.
  • Усиление XP против уровня сложности имеет определенную экономию, где да, есть ограничение уровня, но оно настолько далеко, что мы ожидаем, что игроки завершат игру примерно на полпути через график уровней. В ролевых играх в стиле DQ / FF с несколькими персонажами / классами более распространено сделать так, чтобы разные персонажи / классы делались более легкими, получая опыт с разными скоростями, чем изменяя требуемое количество очков опыта для каждого уровня для каждого класса символов . Таким образом, игроки могут легко запомнить милые маленькие круглые числа как универсальные цели и знать, что каждый персонаж движется к ним с некоторой произвольной скоростью, установленной игровой системой ( XP + (XP * Modifier)или чем-то еще).
  • Ограничения уровня основаны на категории внешних персонажей. То есть какой-то фактор вне игровой системы диктует, как выглядит система уровней. Это становится все более распространенным, так как многие игры платные, но бесплатные. Бесплатный игрок может быть ограничен до 70-го уровня, подписчик может быть ограничен до 80-го уровня, одноразовая покупка может продвинуть кого-то на уровень выше некоторого универсального предела и т. Д.
  • Ограничения уровня универсальны и так или иначе связаны с игровым миром. Эта система была популяризирована WoW.
  • Любая другая система ограничения уровней, которую вы могли бы придумать, которая улучшает игровой процесс более умным способом, чем просто вознаграждение игроков за то, что они потратили больше времени на жизнь в вымышленном мире, чем другие игроки.

Там являются некоторыми игровыми системами , где нет никакого максимального уровня и система алгоритмический определяется. Обычно системы, подобные этой, используют какую-то систему X-powers-of-Y, чтобы числа быстро взрывались. Это позволяет очень легко добраться до уровня L-1, при этом разумно ожидается, что большинство игроков попадут на уровень L, чрезмерно трудно добраться до уровня L + 1, а игроки постареют и умрут до достижения уровня L + 2. В этом случае «L» - это уровень, который, как вы решили, является целевым уровнем, подходящим для игры, и на котором, как правило, он ограничил бы систему, но оставил бы возможность для людей ввести себя в заблуждение, думая, что это хорошая идея для XP навсегда. (Зловещий!) В такой системе математика, найденная здесь, имеет смысл. Но это очень узкий и редко встречающийся случай в реальных играх.

Так что же нам делать?

Рассчитать уровни и XP? Нет . Определить уровни и XP? Да.

Вы определяете, что означают уровни, а затем решаете, какой доступный набор уровней должен быть доступен. Это решение сводится либо к гранулярности в игровой системе (есть ли огромная разница в силе между уровнями? Каждый уровень дает новую способность? И т. Д.), А также используются ли уровни в качестве системы гейтинга («Не могу» ходите в следующий город, пока не достигнете 10-го уровня, детка. ", или в соревновательной лестничной системе применяются уровни на уровне и т. д.).

Код для этого довольно прост, и это просто определение диапазона:

level(XP) when XP < 100  -> 1;
level(XP) when XP < 200  -> 2;
level(XP) when XP < 500  -> 3;
level(XP) when XP < 1000 -> 4;
% ...more levels...
level(XP) when XP > 1000000 -> 70. % level cap

Или с оператором if, или case, или цепочкой if / elif, или с тем языком, который вы используете, поддерживает (эта часть является наименее интересным элементом любой игровой системы, я просто предоставляю два пути, потому что я случайно прямо сейчас в режиме Erlang, и приведенный выше синтаксис может быть не очевиден для всех.):

level(XP) ->
    if
        XP < 100  -> 1;
        XP < 200  -> 2;
        XP < 500  -> 3;
        XP < 1000 -> 4;
        % ...more levels...
        XP > 1000000 -> 70 % level cap
    end.

Это удивительная математика? Нет, совсем нет. Это ручная реализация определения заданного элемента? Ага. Это все , что есть, и это в значительной степени так , как я видел , что это на самом деле сделано в большинстве игр на протяжении многих лет.

Как примечание стороны, это не должно быть сделано каждый раз, когда игрок получает опыт. Обычно вы отслеживаете «XP to go» как одно значение, и как только игрок исчерпывает или превосходит «to go» значение (в зависимости от того, как вы это делаете), вы вычисляете это один раз, чтобы выяснить, где игрок на самом деле at, сохраните это, вычислите следующее «идти» минус остаток (если перенос XP вперед разрешен) и повторите.

zxq9
источник