Java

オブジェクト指向でRPGを作ってみる – 魔法を使えるようにする

更新日:

新機能として、魔法を使えるようにしてみましょう。

実際のRPGでは、経験値をためてレベルが上がったりするタイミングで魔法を覚えたりしますが、ここではシンプルにするためにアイテムや装備と同様に「魔法の巻物」をフィールドで拾うことで、魔法を覚えられるようにしましょう。

巻物は英語で Scroll なので、ホイミの巻物として HealScroll を作成しましょう。

巻物の親クラスとしてScrollを用意しておきましょう。

package rpg.model.scroll;

public class Scroll {
  private String name;
  public Scroll(String name)  {
    this.name = name;
  }
  public String getName() {
    return name;
  }
}

HealScrollはScrollを継承して作成します。

package rpg.model.scroll;

public class HealScroll extends Scroll {
  public HealScroll() {
    super("ホイミ");
  }
}

ホイミの巻物を作ったので、フィールドで移動したときに確率で拾えるようにしましょう。

RpgFrameの中に巻物を拾う処理を追加します。

    } else if (isArmsFound()) {
      // 装備を拾う処理
      Arms arms = rpg.getArms();
      Brave brave = rpg.getBrave();
      brave.addArms(arms);
      String msg = arms.getName() + "を見つけた!";
      JOptionPane.showMessageDialog(
        this, msg,
        "アイテム", JOptionPane.INFORMATION_MESSAGE);
    } else if (isScrollFound()) {
      Scroll scroll = rpg.getScroll();
      System.out.println(scroll.getName());
    }
  }
  private boolean isScrollFound() {
    double v = Math.random();
    return v < 0.05;
  }
  private boolean isArmsFound() {
    double v = Math.random();
    return v < 0.05;
  }

RpgにgetScroll()メソッドを追加して巻物を生成してもらいます。

  public Arms getArms() {
    ArmsCreator ac = new ArmsCreator();
    return ac.createArms();
  }
  public Scroll getScroll() {
    ScrollCreator sc = new ScrollCreator();
    return sc.createScroll();
  }
}

ScrollCreatorのところでエラーが出ているので、ScrollCreatorを作成します。

ScrollCreator

package rpg.model.scroll;

public class ScrollCreator {

  public Scroll createScroll() {
    return new HealScroll();
  }

}

勇者が複数の巻物を所持できるようにします。

public class Brave extends Chara {
  private int exp = 0;
  private int level = 1;
  private int gold = 0;
  private List<Arms> armses = new ArrayList<>();
  private List<Item> items = new ArrayList<>();
  private List<Scroll> scrolls = new ArrayList<>();
  private Arms arms; //現在装備している武器
  private Statuses statuses = new Statuses();
  public Brave() {
    hp = 10;
    setName("ヨシヒコ");
  }
  public int getExp() {
    return exp;
  }
  public void addExp(int p) {
    exp += p;
  }
  public void addItem(Item item) {
    System.out.println(item.getName() + "を入手した。");
    items.add(item);
  }
  public void addArms(Arms arms) {
    System.out.println(arms.getName() + "を入手した。");
    armses.add(arms);
  }
  public void addScroll(Scroll scroll) {
    System.out.println(scroll.getName() + "を入手した。");
    scrolls.add(scroll);
  }

RpgFrameで巻物を拾ったら勇者に持たせるようにします。
ダイアログの表示も追加します。

    } else if (isScrollFound()) {
      Scroll scroll = rpg.getScroll();
      System.out.println(scroll.getName());
      Brave brave = rpg.getBrave();
      brave.addScroll(scroll);
      String msg = scroll.getName() + "を見つけた!";
      JOptionPane.showMessageDialog(
        this, msg,
        "アイテム", JOptionPane.INFORMATION_MESSAGE);
    }

戦闘の画面で所持している巻物に対応した呪文を使えるようにします。

    JButton armsButton = new JButton("装備");
    armsButton.addActionListener(new ArmsAction(this));
    buttonsPanel.add(armsButton);
    JButton scrollButton = new JButton("呪文");
    scrollButton.addActionListener(new ScrollAction(this));
    buttonsPanel.add(scrollButton);

ScrollActionを作ります。他のActionと似たように書きます。

package rpg.contoller;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import rpg.view.BattleFrame;

public class ScrollAction implements ActionListener {
  private BattleFrame battleFrame;
  public ScrollAction(BattleFrame bf) {
    battleFrame = bf;
  }
  @Override
  public void actionPerformed(ActionEvent e) {
    System.out.println("呪文を使う");
  }

}

戦闘画面で「呪文」ボタンを押すと、コンソールに「呪文を使う」とメッセージが出るようになります。

ItemActionを参考にしながら、ScrollActionを作っていきましょう。

  @Override
  public void actionPerformed(ActionEvent e) {
    System.out.println("呪文を使う");
    Object[] scrolls = createScrollArray();
    if (scrolls.length == 0) {
      JOptionPane.showMessageDialog(battleFrame, "巻物を持ってません");
      return;
    }
  }
  private Object[] createScrollArray() {
    Brave brave = battleFrame.getBrave();
    List<Scroll> scrolls = brave.getScrolls();
    List<String> list = new ArrayList<>();
    for (Scroll s : scrolls) {
      if (!list.contains(s.getName())) {
        list.add(s.getName());
      }
    }
    return list.toArray();
  }

クイックフィックスでBraveにgetScrolls()を追加します。
Braveクラスの最後に追加されているので、return を修正します。

  public List<Scroll> getScrolls() {
    return scrolls;
  }

次はItemActionの続きの部分をコピーしてItemをScrollに変更します。

  @Override
  public void actionPerformed(ActionEvent e) {
    System.out.println("呪文を使う");
    Object[] scrolls = createScrollArray();
    if (scrolls.length == 0) {
      JOptionPane.showMessageDialog(battleFrame, "巻物を持ってません");
      return;
    }
    Object scrollName = JOptionPane.showInputDialog(
      battleFrame,
      "巻物を選択してください",
      "巻物",
      JOptionPane.PLAIN_MESSAGE,
      null,
      scrolls,
      scrolls[0]);
    System.out.println(scrollName);
    if (scrollName == null) return;
    Brave brave = battleFrame.getBrave();
    Scroll scroll = brave.getScroll((String)scrollName);
    brave.useScroll(scroll);
    BraveLabel bl = battleFrame.getBraveLabel();
    bl.setText("HP: " + brave.getHp());
  }

BraveにgetScroll(String)が無いというエラーが出ているので、クイックフィックスで作成します。

BraveのgetItem(String)を参考にして実装します。

  public List<Scroll> getScrolls() {
    return scrolls;
  }
  public Scroll getScroll(String scrollName) {
    Scroll scroll = null;
    for (Scroll s : scrolls) {
      if (s.getName().equals(scrollName)) {
        scroll = s;
        break;
      }
    }
    return scroll;
  }

ScrollActionでは、BraveにuseScroll(Scroll)が無いというエラーが出ているので、クイックフィックスで作成します。

useScroll()の実装は、useItem()を参考にしつつ作ります。

  public void useScroll(Scroll scroll) {
    if (scrolls.contains(scroll)) {
      System.out.println(scroll.getName() + " を使った。");
      scroll.effect(this);
    } else {
      System.out.println(scroll.getName() + " を持ってなかった。");
    }
  }

scroll.effect(this)でエラーが出ているので、Scrollクラスにeffect(Brave)を作成します。Scrollクラスは巻物の親クラスなので、メソッドを定義するだけです。

package rpg.model.scroll;

import rpg.model.Brave;

public class Scroll {
  private String name;
  public Scroll(String name)  {
    this.name = name;
  }
  public String getName() {
    return name;
  }
  public void effect(Brave brave) {
  }
}

Scrollを継承したHealScrollクラスでは、巻物の効果を実装します。

package rpg.model.scroll;

import rpg.model.Brave;

public class HealScroll extends Scroll {
  public HealScroll() {
    super("ホイミ");
  }
  @Override
  public void effect(Brave brave) {
    brave.recoverHp(20);
  }
}

ホイミが使えるようになったので、次にベホイミを使えるようにしてみましょう。

ホイミはHealScrollクラスで作ったので、ベホイミはBetterHealScrollで作ります。

package rpg.model.scroll;

import rpg.model.Brave;

public class BetterHealScroll extends Scroll {

  public BetterHealScroll() {
    super("ベホイミ");
  }
  @Override
  public void effect(Brave brave) {
    brave.recoverHp(40);
  }
}

確率でベホイミの巻物を拾うように変更します。

ScrollCreatorクラスを修正します。

package rpg.model.scroll;

public class ScrollCreator {

  public Scroll createScroll() {
    double v = Math.random();
    Scroll scroll = null;
    if (v < 0.8) {
      scroll = new HealScroll();
    } else {
      scroll = new BetterHealScroll();
    }
    return scroll;
  }

}

魔法を使ったらMPを消費するようにする。

HPはCharaクラスで定義していたので、MPも同様にCharaクラスに追加する。

package rpg.model;
public class Chara {
  protected int hp;
  protected int mp;
  private String name;
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  public int getHp() {
    return hp;
  }
  public void damage(int damage) {
    hp -= damage;
  }
  public int getMp() {
    return mp;
  }
  public void consumeMp(int mp) {
    this.mp -= mp;
  }
}

Braveクラスのコンストラクタでhpの初期値を与えているので、mpも同様に初期値を与えます。

  public Brave() {
    hp = 10;
    mp = 10;
    setName("ヨシヒコ");
  }

Scrollクラスで必要なMPを取得できるメソッドを用意しておきます。

package rpg.model.scroll;

import rpg.model.Brave;

public class Scroll {
  private String name;
  public Scroll(String name)  {
    this.name = name;
  }
  public String getName() {
    return name;
  }
  public void effect(Brave brave) {
  }
  public int needMp() {
    return 0;
  }
}
package rpg.model.scroll;

import rpg.model.Brave;

public class HealScroll extends Scroll {
  public HealScroll() {
    super("ホイミ");
  }
  @Override
  public void effect(Brave brave) {
    brave.recoverHp(20);
  }
  @Override
  public int needMp() {
    return 3;
  }
}
package rpg.model.scroll;

import rpg.model.Brave;

public class BetterHealScroll extends Scroll {

  public BetterHealScroll() {
    super("ベホイミ");
  }
  @Override
  public void effect(Brave brave) {
    brave.recoverHp(40);
  }
  @Override
  public int needMp() {
    return 10;
  }
}

ScrollActionでMPが足りているかを調べて、足りていれば呪文を使うようにします。

  @Override
  public void actionPerformed(ActionEvent e) {
    System.out.println("呪文を使う");
    Object[] scrolls = createScrollArray();
    if (scrolls.length == 0) {
      JOptionPane.showMessageDialog(battleFrame, "巻物を持ってません");
      return;
    }
    Object scrollName = JOptionPane.showInputDialog(
      battleFrame,
      "巻物を選択してください",
      "巻物",
      JOptionPane.PLAIN_MESSAGE,
      null,
      scrolls,
      scrolls[0]);
    System.out.println(scrollName);
    if (scrollName == null) return;
    Brave brave = battleFrame.getBrave();
    Scroll scroll = brave.getScroll((String)scrollName);
    // MPが足りているか調べる
    if (brave.getMp() < scroll.needMp()) {
      JOptionPane.showMessageDialog(battleFrame, "MPが足りません。");
      return;
    }
    brave.consumeMp(scroll.needMp());
    brave.useScroll(scroll);
    BraveLabel bl = battleFrame.getBraveLabel();
    bl.setText("HP: " + brave.getHp() + "\n MP: " + brave.getMp());
  }

呪文を使うとMPが減ってしまうので、MPを回復するアイテム「せいすい」を追加します。

package rpg.model.item;

public class HolyWater extends Item {
  public HolyWater() {
    super("せいすい");
  }
}

ItemCreator では、確率で「せいすい」を生成してフィールドで拾えるようにします。

package rpg.model.item;
public class ItemCreator {

  public Item createItem() {
    double v = Math.random();
    Item item = null;
    if (v < 0.8) {
      item = new Herb();
    } else if (v < 0.9) {
      item = new BetterHerb();
    } else {
      item = new HolyWater();
    }
    return item;
  }

}

せいすいを使ったらMPを回復するコードを追加します。
勇者にはMPを回復するメソッドが無いので、追加します。

  public void useItem(Item item) {
    if (items.contains(item)) {
      System.out.println(item.getName() + " を使った。");
      item.effect(this);
      items.remove(item);
    } else {
      System.out.println(item.getName() + "を持ってなかった!");
    }
  }
  public void recoverHp(int hp) {
    this.hp += hp;
    if (this.hp > maxHp()) {
      this.hp = maxHp();
    }
  }
  public void recoverMp(int mp) {
    this.mp += mp;
    if (this.mp > maxMp()) {
      this.mp = maxMp();
    }
  }
  private int maxHp() {
    return statuses.getMaxHp(level);
  }
  private int maxMp() {
    return statuses.getMaxMp(level);
  }

StatusesクラスにgetMaxMp()を追加します。

package rpg;
public class Statuses {
  public int getMaxHp(int level) {
    if (level == 1) return 30;
    if (level == 2) return 50;
    if (level == 3) return 80;
    return 100;
  }

  public int getMaxMp(int level) {
    if (level == 1) return 30;
    if (level == 2) return 50;
    if (level == 3) return 80;
    return 100;
  }
}

HolyWaterにMPを回復する効果を実装します。

package rpg.model.item;

import rpg.model.Brave;

public class HolyWater extends Item {
  public HolyWater() {
    super("せいすい");
  }
  @Override
  public void effect(Brave brave) {
    System.out.println("MPが15回復した。");
    brave.recoverMp(15);
  }
}

-Java
-, , ,

Copyright© UMLとJavaで学ぶオブジェクト指向プログラミング入門 , 2026 All Rights Reserved Powered by STINGER.