
C言語入門|STEP14:魔法とスキルの実装ロジック-Spell構造体と効果分岐処理
はじめに:魔法がRPGの戦略性を生む
STEP13では、経験値とレベルアップによる成長システムを解説しました。
STEP14では、戦闘の幅を一気に広げる 魔法とスキルの実装 を読み解いていきます。
魔法があることで、
- 攻撃一辺倒にならない。
- 回復や強化という選択肢が生まれる。
- 職業ごとの個性がはっきりする。
といった、RPGらしい戦略性が生まれます。
魔法を表す Spell 構造体
まずは、魔法の基本定義から見てみましょう。
typedef enum { SPELL_DMG = 0, SPELL_HEAL = 1, SPELL_BUFF = 2 } SpellType;
typedef struct {
char name[24];
SpellType type;
int mp_cost;
int power;
} Spell;この構造体が表しているもの
| メンバ | 役割 |
|---|---|
| name | 魔法名 |
| type | 効果の種類 |
| mp_cost | 消費MP |
| power | 威力または効果量 |
魔法を「名前・種類・消費・効果量」に分解しているため、
処理の共通化がしやすい設計 になっています。
魔法の種類を enum で管理する理由
SpellType は、魔法の効果を分類するための列挙型です。
| 種類 | 意味 |
|---|---|
| SPELL_DMG | ダメージ魔法 |
| SPELL_HEAL | 回復魔法 |
| SPELL_BUFF | 強化・防御魔法 |
この分類のおかげで、
- 魔法の処理を switch や if で分岐できる。
- 新しい魔法を追加しやすい。
というメリットがあります。
職業ごとの魔法を初期化する仕組み
魔法は init_spells 関数で、
職業ごとに4つずつ設定 されています。
static void init_spells(Character* c) {
if (c->job == HERO) {
c->spells[0] = (Spell){ "ヒール", SPELL_HEAL, 4, 25 };
c->spells[1] = (Spell){ "ホーリーブレード", SPELL_DMG, 5, 2 };
c->spells[2] = (Spell){ "ガードオーラ", SPELL_BUFF, 4, 1 };
c->spells[3] = (Spell){ "スマイト", SPELL_DMG, 7, 3 };
}
// 他職業も同様
}なぜ初期化関数にまとめているのか
- 職業ごとの魔法セットが一目で分かる。
- キャラクター初期化と連動しやすい。
- 魔法バランスの調整が楽。
RPGでは、
「どの職業がどんな魔法を使えるか」
が設計の要になります。
魔法選択と使用処理の流れ
戦闘中に魔法を選ぶと、
cast_spell 関数が呼ばれます。
static int cast_spell(Character* caster, Character party[],
Enemy* enemy, int spell_index)この関数は、
- 魔法の妥当性チェック
- MP消費
- 効果の適用
を一手に引き受けています。
MP不足チェックの重要性
魔法使用の最初に、
MPが足りているかを確認しています。
if (caster->mp < sp.mp_cost) {
printf("MPが足りない!\n");
return 0;
}なぜここでチェックするのか
- MPがマイナスになるのを防ぐ
- 使用失敗を明確に伝える
こうしたチェックを入れておくことで、
ゲームの挙動が安定 します。
ダメージ魔法の計算ロジック
ダメージ魔法では、
魔力と power を組み合わせてダメージを計算しています。
int dmg = char_mag(caster) * sp.power;この設計のポイント
- 魔力が高いほど強くなる。
- 魔法ごとの威力差を power で表現
レベルアップや装備が、
魔法の強さに直接反映される 仕組みです。
回復魔法の対象選択処理
回復魔法では、
回復対象をプレイヤーに選ばせます。
printf("回復対象を選んでください (1-%d): ", PARTY_SIZE);なぜ自動回復にしないのか
- 誰を優先するかが戦略になる。
- パーティ編成の意味が出る。
回復対象を選ばせるだけで、
戦闘の考えどころが一気に増えます。
強化・防御魔法の扱い方
強化系魔法は、
ステータスを直接変更するか、防御フラグを立てます。
caster->defending = 1;フラグで管理するメリット
- 次の攻撃だけ効果を発揮
- 処理がシンプル
- 状態異常の拡張にも使える。
数値を複雑にいじらず、
状態フラグで表現しているのがポイント です。
魔法処理を1つの関数にまとめる理由
cast_spell に処理を集約していることで、
- バトル処理が読みやすい。
- 魔法追加時の修正箇所が少ない。
- バグが入りにくい。
という利点があります。
RPGでは、
魔法処理は必ず一元管理する
という意識が大切です。
STEP14で押さえておきたいポイントまとめ
STEP14で理解しておきたいポイントはこちらです。
- 魔法は Spell 構造体で定義する。
- 効果の種類は enum で分類する。
- 職業ごとに魔法セットを持たせる。
- MPチェックは必須
- 魔法処理は1関数にまとめる。
