STEP13:成長システムの実装-経験値・レベルアップ・成長テーブルの仕組み

はじめに:成長があるからRPGは楽しい

RPGの面白さの大きな要素が、
キャラクターが少しずつ強くなっていくこと です。

STEP13では、

  • 経験値の管理
  • レベルアップの判定
  • 職業ごとの成長差

といった 成長システムの実装ロジック を、
実際の rpg1.c のコードを見ながら解説します。

経験値とレベルの基本設計

まず、このRPGでの成長の考え方を整理しましょう。

要素内容
レベルキャラクターの強さの段階
経験値レベルアップのためのポイント
最大レベル20

キャラクターは、

  • 戦闘に勝利すると経験値を獲得
  • 一定量を超えるとレベルアップ

という、王道の仕組みになっています。

次のレベルに必要な経験値の計算

まず登場するのが、必要経験値を返す関数です。

static int need_exp(int level) {
    return level * 20;
}

この式の意味

レベル必要経験値
1 → 220
2 → 340
3 → 460

レベルが上がるほど、
次に必要な経験値も増える という設計です。

シンプルですが、

  • 調整しやすい
  • 分かりやすい

という、学習向きの実装です。

レベルアップ処理の全体像

次に、レベルアップの処理を見てみましょう。

static void level_up(Character* c) {
    if (c->level >= MAX_LEVEL) return;

    c->level++;
    Growth g = g_growth[c->job][c->level];

    c->max_hp += g.hp;
    c->hp += g.hp;
    c->max_mp += g.mp;
    c->mp += g.mp;
    c->base_atk += g.atk;
    c->base_magic += g.mag;
}

何をしている関数か

この関数は、

  • レベルを1上げる。
  • 職業とレベルに応じた成長量を取得
  • ステータスを加算

という処理をまとめています。

成長テーブルを使う理由

成長量は、計算式ではなく
テーブル(配列)で管理 されています。

typedef struct { int hp, mp, atk, mag; } Growth;
static const Growth g_growth[JOB_COUNT][MAX_LEVEL + 1] = {
    /* 職業ごとの成長量 */
};

なぜテーブルなのか

理由内容
バランス調整数値を見て直感的に調整
職業差職業ごとに個性を出せる
拡張性新職業を追加しやすい

RPGでは、
数値調整そのものが設計 になるため、
テーブル管理はとても相性が良い方法です。

職業ごとの成長の違い

成長テーブルを見ると、
職業ごとの差がはっきりしています。

職業成長傾向
勇者全体的にバランス型
戦士HPと攻撃力が大きく伸びる。
魔法使いMPと魔力が大きく伸びる。

これにより、

  • 同じレベルでも役割が違う。
  • パーティの役割分担が生まれる。

というRPGらしさが実現されています。

現在HP・MPも一緒に増やす理由

レベルアップ時に、

c->max_hp += g.hp;
c->hp += g.hp;

と、最大値と現在値を同時に増やしています。

その理由

  • レベルアップ直後に強くなった実感がある。
  • 回復しないと使えない、という不満を防ぐ。

プレイヤー体験を考えた、
やさしい設計 になっています。

経験値をパーティ全員に配る処理

戦闘後の経験値配布は、
add_exp_party 関数で行われます。

static void add_exp_party(Character p[], int exp) {
    for (int i = 0; i < PARTY_SIZE; i++) {
        if (!p[i].alive) continue;

        p[i].exp += exp;
        while (p[i].exp >= need_exp(p[i].level)) {
            p[i].exp -= need_exp(p[i].level);
            level_up(&p[i]);
        }
    }
}

ここで重要なポイント

  • 生存しているキャラだけが対象
  • 余った経験値は次のレベルへ持ち越し
  • 一気に複数レベル上がる可能性もある。

while を使っていることで、
大量の経験値でも正しく処理できます。

MAX_LEVEL を超えない安全設計

レベルアップ関数の冒頭には、
次のチェックがあります。

if (c->level >= MAX_LEVEL) return;

これにより、

  • 配列の範囲外アクセス
  • 想定外の数値増加

を防いでいます。

上限を決めておく ことは、
安定したプログラムの基本です。

成長処理を関数にまとめるメリット

成長処理を level_up にまとめていることで、

  • バトル処理がスッキリする。
  • 修正が1か所で済む。
  • ロジックの再利用ができる。

というメリットがあります。

RPGのような規模のプログラムでは、
成長処理は必ず独立させる のが定石です。

STEP13で押さえておきたいポイントまとめ

STEP13の重要ポイントはこちらです。

  • 経験値とレベルは明確に役割分担する。
  • 必要経験値は関数で計算する。
  • 成長量はテーブルで管理する。
  • 職業ごとの差別化を数値で表現する。
  • レベルアップ処理は安全に設計する。