JavaJavaコンソールアプリ

【Java】テキストベースのRPGゲーム開発|キャラクター作成

JavaRPGキャラクター作成解説ページのアイキャッチ画像 Java

この記事では、Javaを使用してテキストベースのRPGゲームを構築する過程を通じて、オブジェクト指向プログラミングの基本概念を学ぶことができます。テキスト装飾、ゲームエンジンの設計、コマンド処理、プレイヤーの管理など、RPGゲーム開発の主要コンポーネントを段階的に解説しています。

はじめに

この記事のコードをコピペしてEclipseで出力結果を確認してみよう

※ゲームの開発過程はクリックすると表示されます。

キャラクター作成

以下の機能を実装していきます。

キャラクター作成
  • プレイヤーキャラクターのクラス設計
  • 基本ステータス(HP、MP、攻撃力など)の実装
  • レベルアップシステムの導入
  • その他の実装
    • テキストの色設定
    • 複数クラスに分割

※クリックするとコードが表示されます。

ANSIColors.java:テキストの色を定義するクラス

Java
/**
 * ANSIカラーコードを定義するクラス
 * このクラスは、コンソール出力時に使用できる ANSI エスケープコードを定数として提供します。
 */
public class ANSIColors {
    public static final String RESET = "\u001B[0m";
    public static final String RED = "\u001B[31m";
    public static final String GREEN = "\u001B[32m";
    public static final String YELLOW = "\u001B[33m";
    public static final String CYAN = "\u001B[36m";
    public static final String BRIGHT_PINK = "\u001B[95m";
}

RPGGame.java:テキストベースRPGゲームの開始点

Java
/**
 * テキストベースRPGゲームのメインクラス
 * このクラスはゲームの開始点となり、ゲームエンジンを初期化して起動します。
 */
public class RPGGame {
    public static void main(String[] args) {
        // ゲーム開始メッセージをシアン色で表示
        System.out.println(ANSIColors.CYAN + "テキストベースRPGを開始します..." + ANSIColors.RESET);      
        // ゲームエンジンのインスタンス作成と起動
        GameEngine gameEngine = new GameEngine();
        gameEngine.start();
    }
}

GameEngine.java:ゲームのメイン処理を管理するクラス

Java
import java.util.Scanner;

/**
 * ゲームの中核となるエンジンクラス
 * ゲームのメインループ、入力処理、初期化、終了処理を管理します。
 */
public class GameEngine {
    private static final String EXIT_COMMAND = "exit";
    private final Scanner scanner;
    private final CommandProcessor commandProcessor;
    private final Player player;
    private boolean isRunning;

    /**
     * GameEngineのコンストラクタ
     * 必要なオブジェクトの初期化を行います。
     */
    public GameEngine() {
        this.scanner = new Scanner(System.in);
        this.player = new Player("勇者");
        this.commandProcessor = new CommandProcessor(player);
        this.isRunning = true;
    }

    /**
     * ゲームを開始するメソッド
     * 初期化、メインループ、終了処理の順に実行します。
     */
    public void start() {
        init();
        gameLoop();
        cleanup();
    }

    /**
     * ゲームの初期化を行うメソッド
     * ウェルカムメッセージと操作方法を表示します。
     */
    private void init() {
        System.out.println(ANSIColors.GREEN + "テキストベースRPGへようこそ!" + ANSIColors.RESET);
        System.out.println(ANSIColors.YELLOW + "ゲームの操作方法:'help' と入力してください。" + ANSIColors.RESET);
    }

    /**
     * ゲームのメインループ
     * ユーザーからの入力を受け付け、処理を行います。
     */
    private void gameLoop() {
        while (isRunning) {
            System.out.print("> ");
            String input = scanner.nextLine().trim().toLowerCase();
            processInput(input);
        }
    }

    /**
     * ユーザー入力を処理するメソッド
     * 終了コマンドの場合はゲームを終了し、それ以外はCommandProcessorに処理を委譲します。
     *
     * @param input ユーザーからの入力文字列
     */
    private void processInput(String input) {
        if (EXIT_COMMAND.equals(input)) {
            isRunning = false;
            System.out.println(ANSIColors.YELLOW + "ゲームを終了します..." + ANSIColors.RESET);
        } else {
            commandProcessor.processCommand(input);
        }
    }

    /**
     * ゲーム終了時の後処理を行うメソッド
     * リソースの解放とお別れメッセージの表示を行います。
     */
    private void cleanup() {
        scanner.close();
        System.out.println(ANSIColors.GREEN + "プレイしていただきありがとうございました!" + ANSIColors.RESET);
    }
}

CommandProcessor.java:ユーザーコマンドを処理するクラス

Java
/**
 * ユーザーコマンドを処理するクラス
 * 入力されたコマンドに応じて適切な処理を実行します。
 */
public class CommandProcessor {
    private final Player player;

    /**
     * CommandProcessorのコンストラクタ
     * @param player 操作対象のPlayerオブジェクト
     */
    public CommandProcessor(Player player) {
        this.player = player;
    }

    /**
     * 入力されたコマンドを処理するメソッド
     * @param command ユーザーが入力したコマンド文字列
     */
    public void processCommand(String command) {
        switch (command) {
            case "help" -> displayHelp();
            case "status" -> player.displayStatus();
            case "train" -> trainPlayer();
            default -> System.out.println(ANSIColors.RED + "不明なコマンドです。'help' と入力してコマンドのリストを表示してください。" + ANSIColors.RESET);
        }
    }

    /**
     * ヘルプメッセージを表示するメソッド
     * 利用可能なコマンドとその説明を表示します。
     */
    private void displayHelp() {
        System.out.println(ANSIColors.CYAN + "利用可能なコマンド:" + ANSIColors.RESET);
        System.out.println(ANSIColors.YELLOW + "help   - このヘルプメッセージを表示" + ANSIColors.RESET);
        System.out.println(ANSIColors.YELLOW + "status - キャラクターのステータスを表示" + ANSIColors.RESET);
        System.out.println(ANSIColors.YELLOW + "train  - トレーニングを行い経験値を獲得" + ANSIColors.RESET);
        System.out.println(ANSIColors.YELLOW + "exit   - ゲームを終了" + ANSIColors.RESET);
    }

    /**
     * プレイヤーのトレーニングを実行するメソッド
     * ランダムな経験値を獲得し、プレイヤーのステータスを更新・表示します。
     */
    private void trainPlayer() {
        int expGained = (int) (Math.random() * 50) + 10; // 10から59の間でランダムな経験値を生成
        player.gainExp(expGained);
        player.displayStatus();
    }
}

Player.java:プレイヤーを管理するクラス

Java
import java.util.EnumMap;
import java.util.Map;

/**
 * プレイヤーキャラクターを表すクラス
 * プレイヤーの属性、レベル、経験値、ステータスを管理します。
 */
public class Player {
    private final String name;
    private int level;
    private int exp;
    private final Map<Stat, Integer> stats;

    /**
     * プレイヤーのステータスを表す列挙型
     */
    public enum Stat {
        HP, MAX_HP, MP, MAX_MP, ATTACK, DEFENSE, SPEED
    }

    /**
     * Playerのコンストラクタ
     * @param name プレイヤーの名前
     */
    public Player(String name) {
        this.name = name;
        this.level = 1;
        this.exp = 0;
        this.stats = new EnumMap<>(Stat.class);
        initializeStats();
    }

    /**
     * 初期ステータスを設定するメソッド
     */
    private void initializeStats() {
        stats.put(Stat.HP, 100);
        stats.put(Stat.MAX_HP, 100);
        stats.put(Stat.MP, 50);
        stats.put(Stat.MAX_MP, 50);
        stats.put(Stat.ATTACK, 10);
        stats.put(Stat.DEFENSE, 5);
        stats.put(Stat.SPEED, 5);
    }

    /**
     * 経験値を獲得するメソッド
     * @param amount 獲得する経験値の量
     */
    public void gainExp(int amount) {
        exp += amount;
        System.out.printf(ANSIColors.GREEN + "%sは%d経験値を獲得しました!%n" + ANSIColors.RESET, name, amount);
        checkLevelUp();
    }

    /**
     * レベルアップの条件を確認し、必要に応じてレベルアップを行うメソッド
     */
    private void checkLevelUp() {
        int expToNextLevel = level * 100;
        while (exp >= expToNextLevel) {
            levelUp();
            expToNextLevel = level * 100;
        }
    }

    /**
     * レベルアップの処理を行うメソッド
     * ステータスの増加と経験値の調整を行います。
     */
    private void levelUp() {
        level++;
        exp -= (level - 1) * 100;
        
        increaseStat(Stat.MAX_HP, 10);
        increaseStat(Stat.MAX_MP, 5);
        increaseStat(Stat.ATTACK, 2);
        increaseStat(Stat.DEFENSE, 2);
        increaseStat(Stat.SPEED, 1);
        
        setStat(Stat.HP, getStat(Stat.MAX_HP));
        setStat(Stat.MP, getStat(Stat.MAX_MP));

        System.out.printf(ANSIColors.BRIGHT_PINK + "%sはレベル%dになりました!%n" + ANSIColors.RESET, name, level);
    }

    /**
     * 指定されたステータスを増加させるメソッド
     * @param stat 増加させるステータス
     * @param amount 増加量
     */
    private void increaseStat(Stat stat, int amount) {
        stats.put(stat, stats.get(stat) + amount);
    }

    /**
     * プレイヤーのステータスを表示するメソッド
     */
    public void displayStatus() {
        System.out.println(ANSIColors.CYAN + name + "のステータス:" + ANSIColors.RESET);
        System.out.println(ANSIColors.CYAN + "レベル: " + ANSIColors.YELLOW + level + ANSIColors.RESET);
        System.out.println(ANSIColors.CYAN + "経験値: " + ANSIColors.YELLOW + exp + "/" + (level * 100) + ANSIColors.RESET);
        for (Stat stat : Stat.values()) {
            System.out.printf(ANSIColors.CYAN + "%s:" + ANSIColors.YELLOW + " %d%n" + ANSIColors.RESET, stat.name(), stats.get(stat));
        }
    }

    /**
     * 指定されたステータスの値を取得するメソッド
     * @param stat 取得するステータス
     * @return ステータスの値
     */
    public int getStat(Stat stat) {
        return stats.getOrDefault(stat, 0);
    }

    /**
     * 指定されたステータスに値を設定するメソッド
     * @param stat 設定するステータス
     * @param value 設定する値
     */
    public void setStat(Stat stat, int value) {
        stats.put(stat, value);
    }

    /**
     * プレイヤーの名前を取得するメソッド
     * @return プレイヤーの名前
     */
    public String getName() {
        return name;
    }

    /**
     * プレイヤーのレベルを取得するメソッド
     * @return プレイヤーのレベル
     */
    public int getLevel() {
        return level;
    }
}

※ブログ表示の仕様上、設定した文字色とは異なります。実際に実行して文字色を確認してください。
設定した文字色は旧式のPC環境下のコンソールでは機能しない可能性があります。

テキストベースRPGを開始します...
テキストベースRPGへようこそ
ゲームの操作方法'help' と入力してください
> help
利用可能なコマンド:
help   - このヘルプメッセージを表示
status - キャラクターのステータスを表示
train  - トレーニングを行い経験値を獲得
exit   - ゲームを終了
> train
勇者は12経験値を獲得しました
勇者のステータス:
レベル: 1
経験値: 12/100
HP: 100
MAX_HP: 100
MP: 50
MAX_MP: 50
ATTACK: 10
DEFENSE: 5
SPEED: 5
> train
勇者は46経験値を獲得しました
勇者のステータス:
レベル: 1
経験値: 58/100
HP: 100
MAX_HP: 100
MP: 50
MAX_MP: 50
ATTACK: 10
DEFENSE: 5
SPEED: 5
> train
勇者は35経験値を獲得しました
勇者のステータス:
レベル: 1
経験値: 93/100
HP: 100
MAX_HP: 100
MP: 50
MAX_MP: 50
ATTACK: 10
DEFENSE: 5
SPEED: 5
> train
勇者は31経験値を獲得しました
勇者はレベル2になりました
勇者のステータス:
レベル: 2
経験値: 24/200
HP: 110
MAX_HP: 110
MP: 55
MAX_MP: 55
ATTACK: 12
DEFENSE: 7
SPEED: 6
>

ANSIColors.javaの解説

このコードは、ANSIカラーコードを定義するJavaクラスです。ANSIカラーコードは、コンソールやターミナルでテキストの色を変更するために使用されます。
ANSIカラーコードは旧式のPC環境下のコンソールでは機能しない可能性があります。

Java
public class ANSIColors {
    // クラスの内容
}

これは ANSIColors という名前のpublicクラスを定義しています。publicは、このクラスが他のクラスからアクセス可能であることを意味します。

クラス内部では、以下のような定数が定義されています:

Java
public static final String RESET = "\u001B[0m";
public static final String RED = "\u001B[31m";
public static final String GREEN = "\u001B[32m";
public static final String YELLOW = "\u001B[33m";
public static final String CYAN = "\u001B[36m";
public static final String BRIGHT_PINK = "\u001B[95m";

これらの行は、各色のANSIエスケープコードを定義しています。

  • public: この修飾子は、定数が他のクラスからアクセス可能であることを示します。
  • static: この修飾子は、定数がクラスに属し、インスタンス化せずに使用できることを意味します。
  • final: この修飾子は、定数の値が変更できないことを示します。
  • String: これは定数の型で、文字列であることを示します。

各定数の値は、ANSIエスケープシーケンスです:

  • \u001B: これはエスケープ文字を表します。
  • [XXm: これは色を指定するコードです。例えば、31mは赤色を意味します。

特に重要な点

  • RESET: この定数は、テキストの色をデフォルトに戻すために使用されます。
  • 他の定数(RED, GREENなど)は、それぞれ特定の色を表します。

このクラスを使用すると、次のようにコンソール出力の色を変更できます:

Java
System.out.println(ANSIColors.RED + "This text is red!" + ANSIColors.RESET);

この行は、”This text is red!”というテキストを赤色で出力し、その後テキストの色をリセットします。

よく使用される ANSI カラーコード:

色名通常明るい
\u001B[30m\u001B[90m
\u001B[31m\u001B[91m
\u001B[32m\u001B[92m
\u001B[33m\u001B[93m
\u001B[34m\u001B[94m
マゼンタ\u001B[35m\u001B[95m
シアン\u001B[36m\u001B[96m
\u001B[37m\u001B[97m

加えて、以下の特殊なコードも頻繁に使用されます:

  • リセット: \u001B[0m
  • 太字: \u001B[1m
  • 下線: \u001B[4m

これらのコードを組み合わせることで、テキストの色や書式を変更できます。例えば、赤色の太字テキストを作成するには、\u001B[1;31mのように組み合わせて使用します。

RPGGame.javaの解説

このコードは、テキストベースのRPGゲームを開始するためのJavaプログラムのメインクラスです。

Java
public class RPGGame {
    // クラスの内容
}

これは RPGGame という名前のpublicクラスを定義しています。このクラスがプログラムのエントリーポイントとなります。

Java
public static void main(String[] args) {
    // メインメソッドの内容
}

この部分はJavaプログラムのエントリーポイントです。プログラムが実行されると、まずこのmainメソッドが呼び出されます。

  • public static void: これらの修飾子は、メソッドが公開されており、クラスに属し、戻り値がないことを示します。
  • String[] args: コマンドライン引数を受け取るための配列です。

メインメソッド内の処理:

Java
System.out.println(ANSIColors.CYAN + "テキストベースRPGを開始します..." + ANSIColors.RESET);

この行は、シアン色のテキストでゲーム開始メッセージを表示します。

  • ANSIColors.CYAN: テキストをシアン色に設定します。
  • ANSIColors.RESET: テキストの色をデフォルトに戻します。
Java
GameEngine gameEngine = new GameEngine();

この行はGameEngineクラスの新しいインスタンスを作成し、gameEngine変数に代入します。

Java
gameEngine.start();

最後に、gameEngineオブジェクトのstart()メソッドを呼び出し、ゲームを開始します。

重要なポイント:

  1. メインクラス(RPGGame)の定義
  2. mainメソッドの実装
  3. ANSIカラーを使用したコンソール出力
  4. GameEngineオブジェクトの作成と使用

このプログラムは、ゲームエンジンを初期化し、ゲームを開始するための基本的な構造を提供しています。実際のゲームロジックはGameEngineクラス内で実装されています。

GameEngine.javaの解説

このコードは、テキストベースRPGのゲームエンジンを実装したJavaクラスです。

  1. クラス定義と変数:
Java
public class GameEngine {
    private static final String EXIT_COMMAND = "exit";
    private final Scanner scanner;
    private final CommandProcessor commandProcessor;
    private final Player player;
    private boolean isRunning;
    // ...
}
  • EXIT_COMMAND: ゲーム終了コマンドを定義する定数
  • scanner: ユーザー入力を読み取るためのScanner
  • commandProcessor: ユーザーコマンドを処理するオブジェクト
  • player: プレイヤーオブジェクト
  • isRunning: ゲームが実行中かどうかを示すフラグ
  1. コンストラクタ:
Java
public GameEngine() {
    this.scanner = new Scanner(System.in);
    this.player = new Player("勇者");
    this.commandProcessor = new CommandProcessor(player);
    this.isRunning = true;
}

ゲームエンジンの初期化を行います。Scannerの作成、プレイヤーの作成、コマンドプロセッサの初期化を行います。

  1. ゲーム開始メソッド:
Java
public void start() {
    init();
    gameLoop();
    cleanup();
}

ゲームの初期化メインループ終了処理を順番に実行します。

  1. 初期化メソッド:
Java
private void init() {
    System.out.println(ANSIColors.GREEN + "テキストベースRPGへようこそ!" + ANSIColors.RESET);
    System.out.println(ANSIColors.YELLOW + "ゲームの操作方法:'help' と入力してください。" + ANSIColors.RESET);
}

ゲーム開始時のメッセージを表示します。

  1. ゲームループ:
Java
private void gameLoop() {
    while (isRunning) {
        System.out.print("> ");
        String input = scanner.nextLine().trim().toLowerCase();
        processInput(input);
    }
}

ゲームのメインループです。ユーザー入力を受け取り、処理します。

  • scanner.nextLine():ユーザーからの入力を1行読み取ります。
  • .trim():取得した文字列の先頭と末尾にある空白文字(スペース、タブ、改行など)を削除します。これにより、ユーザーが誤って入力した余分な空白を除去できます。
  • .toLowerCase():文字列をすべて小文字に変換します。これにより、大文字小文字の違いを無視してコマンドを処理できるようになります。
  1. 入力処理:
Java
private void processInput(String input) {
    if (EXIT_COMMAND.equals(input)) {
        isRunning = false;
        System.out.println(ANSIColors.YELLOW + "ゲームを終了します..." + ANSIColors.RESET);
    } else {
        commandProcessor.processCommand(input);
    }
}

ユーザー入力が”exit”の場合はゲームを終了し、それ以外はコマンドプロセッサに処理を委譲します。

  1. 終了処理:
Java
private void cleanup() {
    scanner.close();
    System.out.println(ANSIColors.GREEN + "プレイしていただきありがとうございました!" + ANSIColors.RESET);
}

Scannerを閉じ、終了メッセージを表示します。

重要なポイント:

  • ゲームループの実装
  • ユーザー入力の処理
  • コマンドパターンの使用 (CommandProcessorクラスを通じて)
  • ANSIカラーを使用したテキスト装飾

このGameEngineクラスは、テキストベースRPGの基本的な構造を提供し、ユーザー入力の受け取りとコマンドの処理を管理しています。

CommandProcessor.javaの解説

このコードは、テキストベースRPGのコマンド処理を担当するCommandProcessorクラスを定義しています。

  1. クラス定義と変数:
Java
public class CommandProcessor {
    private final Player player;
    // ...
}
  • player: コマンドの対象となるプレイヤーオブジェクト
  1. コンストラクタ:
Java
public CommandProcessor(Player player) {
    this.player = player;
}

Playerオブジェクトを受け取り、フィールドに設定します。

  1. コマンド処理メソッド:
Java
public void processCommand(String command) {
    switch (command) {
        case "help" -> displayHelp();
        case "status" -> player.displayStatus();
        case "train" -> trainPlayer();
        default -> System.out.println(ANSIColors.RED + "不明なコマンドです。'help' と入力してコマンドのリストを表示してください。" + ANSIColors.RESET);
    }
}

このメソッドは入力されたコマンドに応じて適切な処理を実行します。

  • switchを使用して、各コマンドに対応する処理を呼び出しています。
  • ラムダ式 (->) を使用した新しいswitch式の構文を採用しています。
  • 不明なコマンドの場合は、エラーメッセージを表示します。
  1. ヘルプ表示メソッド:
Java
private void displayHelp() {
    System.out.println(ANSIColors.CYAN + "利用可能なコマンド:" + ANSIColors.RESET);
    System.out.println(ANSIColors.YELLOW + "help   - このヘルプメッセージを表示" + ANSIColors.RESET);
    System.out.println(ANSIColors.YELLOW + "status - キャラクターのステータスを表示" + ANSIColors.RESET);
    System.out.println(ANSIColors.YELLOW + "train  - トレーニングを行い経験値を獲得" + ANSIColors.RESET);
    System.out.println(ANSIColors.YELLOW + "exit   - ゲームを終了" + ANSIColors.RESET);
}

利用可能なコマンドとその説明を表示します。ANSIカラーを使用して、テキストを装飾しています。

  1. トレーニングメソッド:
Java
private void trainPlayer() {
    int expGained = (int) (Math.random() * 50) + 10;
    player.gainExp(expGained);
    player.displayStatus();
}
  • ランダムな経験値(10〜59)を生成します。
  • プレイヤーに経験値を付与し、ステータスを表示します。
Math.random()について
  1. Math.random(): 0.0以上1.0未満のランダムな小数を生成します。
  2. * 50: 生成された乱数を50倍します。結果は0.0以上50.0未満の値になります。
  3. (int): 小数を整数に変換します(小数点以下を切り捨て)。
  4. + 10: 最後に10を加算します。
  5. 結果として、expGainedには10以上60未満(10〜59)のランダムな整数が代入されます。

重要なポイント:

  • コマンドパターンの実装:各コマンドに対応する処理を一箇所にまとめています。
  • switch文を使用したコマンド分岐
  • カプセル化playerオブジェクトを通じてプレイヤーの操作を行っています。
  • ANSIカラーを使用したテキスト装飾

このクラスは、ユーザーからのコマンド入力を解釈し、適切な処理を実行する役割を果たしています。これにより、ゲームの主要な機能(ヘルプ表示、ステータス確認、トレーニング)が実現されています。

Player.javaの解説

このコードは、RPGゲームのプレイヤーを表現するPlayerクラスを定義しています。

Java
import java.util.EnumMap;
import java.util.Map;

Map と enum(列挙型) の組み合わせを使用して EnumMap を初期化し、その後は EnumMap の機能を活用してプレイヤーのステータス管理を実装しています。この方法により、型安全性が確保され、効率的なステータス管理が可能になっています。

  1. クラス定義と変数:
Java
public class Player {
    private final String name;
    private int level;
    private int exp;
    private final Map<Stat, Integer> stats;

    public enum Stat {
        HP, MAX_HP, MP, MAX_MP, ATTACK, DEFENSE, SPEED
    }
    // ...
}
  • name: プレイヤーの名前
  • level: プレイヤーのレベル
  • exp: 現在の経験値
  • stats: プレイヤーのステータスを保持するマップ
  • Stat: ステータスの種類を定義する列挙型

private final Map<Stat, Integer> stats;

  • Map: キーと値のペアを保存するデータ構造です。
  • <Stat, Integer>: このマップは Stat 型のキーと Integer 型の値を持ちます。
  • final: このマップの参照は変更できません(ただし、中身は変更可能です)。

この構造により、各ステータス(HP、MP、攻撃力など)とその数値を効率的に管理できます。

Map<Stat, Integer>enum Stat を組み合わせる利点:

  1. 各ステータスとその値を簡単に関連付けられます。
  2. 新しいステータスの追加が容易です(enum に追加するだけ)。
  3. ステータス名のタイプミスを防ぎ、コードの安全性が向上します。
  4. ステータスに関連する操作(取得、設定、更新など)を一貫した方法で行えます。

この設計により、プレイヤーのステータス管理が効率的かつ安全に行えるようになっています。

  1. コンストラクタ:
Java
public Player(String name) {
    this.name = name;
    this.level = 1;
    this.exp = 0;
    this.stats = new EnumMap<>(Stat.class);
    initializeStats();
}

プレイヤーを初期化し、初期ステータスを設定します。

this.stats = new EnumMap<>(Stat.class);

  • new EnumMap<>(Stat.class): 新しい EnumMap インスタンスを作成しています。
  • Stat.class を引数として渡すことで、この EnumMapStat 列挙型をキーとして使用することを指定しています。
  • EnumMapStat 型のキーと Integer 型の値を持つマップです。

EnumMap の特徴:

  1. キーが列挙型に限定されるため、型安全性が高くなります。
  2. 内部的に配列として実装されているため、通常の HashMap よりも効率的です。
  3. キーの自然順序(列挙定数の宣言順)で要素が管理されます。
  1. ステータス初期化:
Java
private void initializeStats() {
    stats.put(Stat.HP, 100);
    stats.put(Stat.MAX_HP, 100);
    // ...
}
  • このメソッドは、stats EnumMap に各ステータスの初期値を設定しています。
  • stats.put(Stat.キー, 値): EnumMap に新しいキーと値のペアを追加します。
  1. 経験値獲得とレベルアップチェック:
Java
public void gainExp(int amount) {
    exp += amount;
    System.out.printf(ANSIColors.GREEN + "%sは%d経験値を獲得しました!%n" + ANSIColors.RESET, name, amount);
    checkLevelUp();
}

private void checkLevelUp() {
    int expToNextLevel = level * 100;
    while (exp >= expToNextLevel) {
        levelUp();
        expToNextLevel = level * 100;
    }
}

gainExp メソッド:

このメソッドは、プレイヤーが経験値を獲得する際に呼び出されます。

  • exp += amount;: プレイヤーの現在の経験値(exp)に、獲得した経験値(amount)を加算します。
  • System.out.printf(...):
    • 経験値獲得のメッセージを表示します。
    • ANSIColors.GREEN: メッセージを緑色で表示します。
    • %s: プレイヤーの名前(name)が入ります。
    • %d: 獲得した経験値(amount)が入ります。
    • %n: 改行を表します。
    • ANSIColors.RESET: テキストの色をデフォルトに戻します。
  • checkLevelUp();: レベルアップの条件を確認するメソッドを呼び出します。

checkLevelUp メソッド:

このメソッドは、プレイヤーの経験値が次のレベルに必要な量に達しているかを確認し、レベルアップの処理を行います。

  • int expToNextLevel = level * 100;
    • 次のレベルに必要な経験値を計算します。
    • 現在のレベルに100を掛けた値が、次のレベルに必要な経験値となります。
  • while (exp >= expToNextLevel) { ... }
    • プレイヤーの現在の経験値が、次のレベルに必要な経験値以上である限り、ループが続きます。
    • これにより、一度に複数レベルアップする可能性にも対応しています。
  • ループ内の処理:
    • levelUp();: レベルアップの処理を行うメソッドを呼び出します。
    • expToNextLevel = level * 100;: レベルアップ後、次のレベルに必要な経験値を再計算します。
  1. レベルアップ処理:
Java
private void levelUp() {
    level++;
    exp -= (level - 1) * 100;

    increaseStat(Stat.MAX_HP, 10);
    increaseStat(Stat.MAX_MP, 5);
    increaseStat(Stat.ATTACK, 2);
    increaseStat(Stat.DEFENSE, 2);
    increaseStat(Stat.SPEED, 1);
        
    setStat(Stat.HP, getStat(Stat.MAX_HP));
    setStat(Stat.MP, getStat(Stat.MAX_MP));

    System.out.printf(ANSIColors.BRIGHT_PINK + "%sはレベル%dになりました!%n" + ANSIColors.RESET, name, level);
}


private void increaseStat(Stat stat, int amount) {
    stats.put(stat, stats.get(stat) + amount);
}

レベルアップ時にステータスを増加させ、メッセージを表示します。

レベルと経験値の調整:

  • level++: プレイヤーのレベルを1増やします。
  • exp -= (level - 1) * 100: 現在の経験値から、レベルアップに必要だった経験値を引きます。これにより、余剰の経験値が次のレベルアップに持ち越されます。

ステータスの増加:

increaseStatメソッドを呼び出し、ステータスの増加をします。

  • 最大HP: 10増加
  • 最大MP: 5増加
  • 攻撃力: 2増加
  • 防御力: 2増加
  • 速度: 1増加

HPとMPの回復:

  • setStatメソッドを使用して、HPとMPを最大値まで回復させます。
  • getStatメソッドで最大値ステータスの値を取得して、setStatメソッドで指定されたステータスに値をセットします。

レベルアップメッセージの表示:

  • レベルアップのメッセージを表示します。
  • ANSIColors.BRIGHT_PINKを使用して、メッセージを明るいピンク色で表示します。
  • %sにプレイヤーの名前、%dに新しいレベルが入ります。
  • ANSIColors.RESETでテキストの色をデフォルトに戻します。

increaseStat メソッド:

  • メソッドの定義
    • private: このメソッドはクラス内部でのみ使用可能です。
    • void: このメソッドは値を返しません。
    • Stat stat: 増加させるステータスを指定するパラメータです。
    • int amount: 増加させる量を指定するパラメータです。
  • メソッドの本体
    • stats.get(stat): 指定されたステータス(stat)の現在の値を取得します。
    • stats.get(stat) + amount: 現在の値に増加量(amount)を加算します。
    • stats.put(stat, ...): 計算結果を新しい値として、指定されたステータス(stat)に設定します。
  1. ステータス表示:
Java
public void displayStatus() {
    // プレイヤー名の表示
    System.out.println(ANSIColors.CYAN + name + "のステータス:" + ANSIColors.RESET);

    // レベルの表示
    System.out.println(ANSIColors.CYAN + "レベル: " + ANSIColors.YELLOW + level + ANSIColors.RESET);

    // 経験値の表示
    System.out.println(ANSIColors.CYAN + "経験値: " + ANSIColors.YELLOW + exp + "/" + (level * 100) + ANSIColors.RESET);

    // 各ステータスの表示
    for (Stat stat : Stat.values()) {
        System.out.printf(ANSIColors.CYAN + "%s:" + ANSIColors.YELLOW + " %d%n" + ANSIColors.RESET, stat.name(), stats.get(stat));
    }
}

プレイヤーの現在のステータスを表示します。

  • 各ステータスの表示:
    • for ループを使用して、すべてのステータスを順番に表示します。
    • Stat.values() で Stat 列挙型のすべての値を取得しています。
    • stat.name() でステータスの名前を、stats.get(stat) でその値を取得しています。
    • System.out.printf() を使用して、フォーマットされた文字列を出力しています。
      • %s: ステータス名
      • %d: ステータス値
      • %n: 改行
  • EnumMap の活用:
    • stats.get(stat) で EnumMap から各ステータスの値を取得しています。
  1. ユーティリティメソッド:
Java
public int getStat(Stat stat) {
    return stats.getOrDefault(stat, 0);
}

public void setStat(Stat stat, int value) {
    stats.put(stat, value);
}

public String getName() {
    return name;
}

public int getLevel() {
    return level;
}

ステータスの取得と設定を行うメソッドです。

getStat メソッド:

  • 目的: 指定されたステータスの値を取得します。
  • パラメータ: Stat stat – 取得したいステータス
  • 戻り値: 指定されたステータスの値(整数)
  • 特徴:
    • public: クラス外からアクセス可能
    • stats.getOrDefault(stat, 0): 指定されたステータスが存在しない場合、デフォルト値として0を返します。これにより、NullPointerExceptionを防ぎます。

setStat メソッド:

  • 目的: 指定されたステータスに新しい値を設定します。
  • パラメータ:
  • Stat stat – 設定したいステータス
  • int value – 設定する値
  • 戻り値: なし(void)
  • 特徴:
    • public: クラス外からアクセス可能
    • stats.put(stat, value): 指定されたステータスに新しい値を設定します。

getName メソッド:

  • 目的: プレイヤーの名前を取得します。
  • パラメータ: なし
  • 戻り値: プレイヤーの名前(String)
  • 特徴:
    • public: クラス外からアクセス可能
    • 単純にnameフィールドの値を返します。

getLevel メソッド:

  • 目的: プレイヤーの現在のレベルを取得します。
  • パラメータ: なし
  • 戻り値: プレイヤーのレベル(整数)
  • 特徴:
    • public: クラス外からアクセス可能
    • 単純にlevelフィールドの値を返します。

まとめ

  • キャラクター作成: Playerクラスを通じて、RPGの基本となるキャラクター管理システムを実装
  • ANSIColors: コンソール出力に色を付けることで、ユーザーエクスペリエンスを向上させる方法
  • RPGGame: メインクラスとしてゲームの起動と終了を管理する方法
  • GameEngine: ゲームのメインループと状態管理を担当するクラスの設計と実装
  • CommandProcessor: ユーザー入力を解釈し、適切なアクションを実行するシステムを構築
  • Player: 列挙型とEnumMapを使用して、効率的なステータス管理とレベルアップシステムを実装

このプロジェクトを通じて、オブジェクト指向プログラミングの重要な概念(カプセル化、継承、ポリモーフィズム)を実践的に適用する方法を学びました。

さらに、このプロジェクトはゲーム開発の基本的なアーキテクチャを示しており、より複雑なゲームシステムへの拡張の基礎となります。コマンドパターンの使用、状態管理、ユーザー入力の処理など、ゲーム開発特有の設計パターンも学ぶことができました。

未経験でもWEBスキルを取得したい方
  • Javaコース
    Javaプログラミングを基礎から応用まで、体系的に学べる実践的なカリキュラムが特徴です。「マインクラフト」を通じてJavaの基本文法とフレームワークの概念を学びます。また、実際のプロジェクト開発を通じて、データベース連携やWebアプリケーション開発のスキルを身につけることができます。

コメント

タイトルとURLをコピーしました