Zum Inhalt springen
Michael Malura
570 Github Stars 5810 npm Downloads 53 Projekte

XP-Kurven

Wie viel Erfahrung braucht man fürs nächste Level? Klingt nach einer Zahl, die man sich einfach ausdenkt, und genau so fängt es meistens an: Level 2 kostet 100, Level 3 kostet 200, dann sieht man weiter. Spätestens bei Level 40 merkt man, dass die Kurve das eigentliche Spieldesign ist. Sie entscheidet, wie lange sich ein Level anfühlt und wann ein Spieler aufgibt.

Oben stehen zwei Kurven: in Orange, was das nächste Level kostet, in Teal die Summe, die man insgesamt für ein Level braucht. Chips wechseln zwischen fünf Kurventypen, die Regler a und b verändern sie. Mit "Log y" wird die y-Achse logarithmisch, sonst sieht man bei den steilen Kurven nur einen flachen Strich und am Ende einen Haken. Darunter steht dieselbe Kurve als Spielzeit, wenn man eine bestimmte Menge XP pro Stunde verdient. Fährst du mit der Maus drüber, zeigt eine Karte Level, Kosten, Gesamt-XP und Stunden. Ein kleiner Spieler sammelt die ganze Zeit XP und klettert die Kurve hoch, mit x10 oder x100 geht das schneller.

Kosten und Summe

Ich rechne immer mit zwei Funktionen. step(L) sind die XP, um von Level L auf L+1 zu kommen. total(L) ist die Summe aller Schritte davor, also die XP, die man haben muss, um Level L zu sein. Level 1 hat 0.

Bei der linearen Kurve ist step(L) = a * L, bei der polynomialen a * L^b, bei der exponentiellen a * b^L. Die Tabelle hat elf von Hand gesetzte Stützwerte, dazwischen wird geometrisch interpoliert und auf Zehner gerundet, so wie man es in einer Tabellenkalkulation hinschreiben würde.

Die lineare Kurve fühlt sich am Anfang vernünftig an. Mit a = 2500 und 100.000 XP pro Stunde dauert Level 1 anderthalb Minuten und Level 98 knapp zweieinhalb Stunden. Das wächst gleichmäßig, und genau da liegt das Problem: Verdient der Spieler mit besserer Ausrüstung und stärkeren Gegnern schneller, laufen die Level irgendwann an ihm vorbei. Wer ungefähr gleich lange pro Level brauchen soll, braucht Kosten, die so schnell wachsen wie seine Verdienstrate. Die Demo hält die Rate fest, deshalb zeigt die gestrichelte Linie unten, wie die Gesamtzeit verliefe, wenn jedes Level gleich lange dauert. Alle Kurven hier liegen darunter und biegen am Ende steil nach oben.

Der RuneScape-Trick

Die bekannteste Kurve ist die von RuneScape. Pro Level gibt es einen Punktewert, die XP sind die Summe davon durch 4:

inline double runescapePoints(int l) { return std::floor(static_cast<double>(l) + 300.0 * std::exp2(static_cast<double>(l) / 7.0)); }

sum += static_cast<std::int64_t>(detail::runescapePoints(l));
totals_[static_cast<std::size_t>(l)] = sum / 4;

Das 2^(l/7) ist der Kern. Pro Level wächst der Schritt um den Faktor 2^(1/7), das sind rund 10,4 Prozent, und alle 7 Level hat er sich verdoppelt. Level 92 braucht deshalb 6.517.253 XP und Level 99 fast genau doppelt so viel, 13.034.431. Der halbe Weg zu 99 ist Level 92. Bei 100.000 XP pro Stunde stehst du nach einer guten Stunde auf Level 50 und nach 65 Stunden auf Level 92. Das letzte Level kostet 1.228.825 XP, also gut 12 Stunden. Level 1 zu 2 sind 83 XP, ein paar Sekunden.

Die Formel hab ich nachgerechnet. Der Test prüft Level 2 (83), Level 10 (1.154), Level 50 (101.333) und Level 99 (13.034.431), und alle stimmen.

Vom XP-Wert zum Level

Die Gegenrichtung braucht jedes Spiel ständig: Der Spieler hat 3,2 Millionen XP, welches Level ist das? Man könnte total(L) für jedes L durchprobieren. Ich lege die Schwellwerte einmal in ein Array und suche per Binärsuche:

const auto it = std::upper_bound(first, last, xp);
return std::max(1, static_cast<int>(it - first));

upper_bound liefert das erste Level, dessen Schwelle über den XP liegt. Eins davor ist das Level des Spielers. Exakt auf der Schwelle ist es schon das neue Level, eine XP darunter noch das alte, und 0 XP sind Level 1. Das steht genau so im Test. Eine Formel für die Umkehrung gibt es bei der Exponentialkurve zwar (ein Logarithmus), aber bei einer Tabelle, bei den abgerundeten RuneScape-Werten oder sobald jemand an der Kurve dreht, ist die Lookup-Tabelle mit Binärsuche der Weg, der immer funktioniert. Bei 99 Einträgen sind das sieben Vergleiche.

Stolperfallen

Abgerundet wird erst am Ende. Rundet man jeden Punktewert einzeln durch 4 ab und addiert dann, landet Level 10 bei 1.151 statt 1.154 und Level 99 bei 13.034.394. Erst die ganzen Punkte aufsummieren, dann durch 4.

Exponentielle Kurven sprengen 64 Bit schneller, als man denkt. 10 * 2^99 hat über dreißig Stellen. Jeder Schritt wird deshalb bei 4 Billiarden gekappt, 98 solcher Schritte passen mit 3,9e17 noch locker in einen int64 (Maximum 9,2e18), die Summe läuft also nie über:

inline std::int64_t toStep(double raw) {
    if (std::isnan(raw) || raw < 1.0) return 1;
    if (!(raw < static_cast<double>(kMaxStep))) return kMaxStep;
    return static_cast<std::int64_t>(std::llround(raw));
}

Das raw < 1.0 hat noch einen zweiten Zweck. Mit a = 0 wäre jedes Level kostenlos, alle Schwellen wären 0 und die Binärsuche hätte keine eindeutige Antwort. Also kostet jeder Schritt mindestens 1 XP. Bei der exponentiellen Kurve zählt ein b kleiner oder gleich 1 als 1, sonst würden die Schritte schrumpfen.

Der kleine Spieler läuft in festen Schritten von einer sechzigstel Sekunde, wie bei Fixed Timestep. Bei x100 passieren dabei viele Level pro Sekunde, deshalb vergleicht jeder Schritt Level vor und nach dem Zuwachs und löst den Impuls aus, wenn es mehr geworden sind. Die Zahlen mit Tausendertrennzeichen baue ich selbst zusammen, snprintf mit Locale würde je nach System Punkte oder Kommas setzen.

Den Code findest du im Repo unter xp-curves. Alle Demos der Serie sammelt das Projekt Game Dev Snippets.

23.10.2026 aktualisiert 06.11.2026
Teilen X Reddit Hacker News LinkedIn E-Mail
Neue Beiträge abonnieren RSS JSON