今回は、ミニゲーム作成で作ったものをまとめます。
まとめたのちに、次の実装はどうしようか決めようと考えた次第です。
Gitリポジトリはこちらです。下の方に、接続方法などの記事へのリンクがあります。
オブジェクト指向について
オブジェクト指向について、Oracle認定の書籍を参考にまとめた記事です。参考にどうぞ
大まかな処理フロー
GameMainクラス
クラスの記述内容がコードより、ライセンスのJavaDoc部分が大半を占める状態です(笑)
public class GameMain {
public static void main(String[] args) {
// ゲームクラス
TextRpgGame main = new TextRpgGame();
// 初期処理
main.init();
while (true) {
// 入力受付
String in = main.input();
if ("bye".equals(in)) {
break;
}
// データの更新
if (main.update(in)) {
// 画面の描画
main.render();
}
}
}
}
メインメソッドを持っていて、ループ処理を行っています。
while(true) { ... }の部分が俗にいう「ゲームループ」の部分になります。
処理の説明としては、以下の通りです。
- TextRpgGameのインスタンスを取得
- 初期処理を行う
- ゲームループ開始
- 標準入力を受け取る
- "bye"と入力されたらアプリの終了
- 入力データにより、ゲームで使用するデータ(プレーヤーとモンスター)の情報を更新する
- 表示するステータスを再描画
こんな感じの処理を行っています。
TextRpgGameについて
メインメソッドから呼ばれるそれぞれのメソッドを実装しています。
具体的には下のものです。
- init(): 初期処理を行う。ステータスの表示など
- input(): 標準入力を受け取る。
- update (): データの更新を行う。使用しているプレーヤークラス、モンスタークラスのデータを更新します。主にHPの値を更新します。
- render(): ステータスの更新、モンスターを倒したなどの戦闘終了の文言を表示する。
public class TextRpgGame {
/** コマンド:たたかう */
private static final String ATTACK = "1";
/** コマンド:ぼうぎょ */
private static final String DEFFENCE = "2";
/** コマンド:にげる */
private static final String ESCAPE = "3";
/** 入力部品 */
private Scanner scan;
/** プレーヤー */
private Player player;
/** モンスター */
private Monster monster;
/** 初期表示を行う */
public void init() {
player = new Player(20, 10, 1, "プレーヤー");
monster = new Monster(10, 5, 1, "たくのじ");
System.out.println(monster.getName() + "が現れた!");
monster.say();
scan = new Scanner(System.in);
}
/** 入力処理 */
public String input() {
return scan.next();
}
/** 入力後に行う処理 */
public boolean update(String input) {
if (CheckerUtils.isNumber(input, CheckerUtils.REG_1_TO_3) == false) {
System.out.println("1-3を入力してください。: " + input);
return false;
}
// コマンド実行後の計算
if (ATTACK.equals(input)) {
// モンスターへダメージ
int monsterDamage = this.calcAttack(player.attack(), monster.deffence(), player.getName());
int monsterResult = monster.getHp() + monsterDamage;
monster.setHp(monsterResult);
}
// モンスターの攻撃
int monsterAttack = this.calcAttack(player.deffence(), monster.attack(), monster.getName());
int playerResult = player.getHp() + monsterAttack;
player.setHp(playerResult);
return true;
}
/**
* 画面を更新する。
* @return ture: 終了 false: 続く
*/
public boolean render() {
if (monster.getHp() > 0) {
monster.say();
} else if (player.getHp() <= 0 ) {
System.out.print(player.getName() + "はたおれてしまった。");
return true;
} else {
monster.lastMessage();
System.out.print(monster.getName() + "をやっつけた。");
return true;
}
return false;
}
public void viewStatus() {
viewStatus(player.getHp(), player.getMp(), monster.getHp(), monster.getMp());
}
private void viewStatus(int playerHp, int playerMp, int monsterHp, int monsterMp) {
String line1 = "たたかう: 1 プレーヤー たくのじ";
String line2 = "ぼうぎょ: 2 HP: A1 HP: B1";
String line3 = "にげる : 3 MP: A2 MP: B2";
// 値を入れ替える
line2 = line2.replace("A1", String.format("%02d", playerHp)).replace("B1", String.format("%02d", monsterHp));
line3 = line3.replace("A2", String.format("%02d", playerHp)).replace("B2", String.format("%02d", monsterHp));
System.out.println(line1);
System.out.println(line2);
System.out.println(line3);
}
private int calcAttack(int attack, int deffence, String attackerName) {
int result = 0;
System.out.println(attackerName + "のこうげき");
if (attack > deffence) {
result = deffence - attack;
System.out.println(Math.abs(result) + "のダメージ!");
} else {
System.out.println("こうげきを、はじいた!");
}
return attack > deffence ? deffence - attack : 0;
}
}
じゃんけんゲームから比べてみると、コード量が増えたように見えます。がビビることはありません。
ポイントはメソッド単位で処理を見ることです。
そうすれば、12〜16行くらいなもんです。物により長大なものもありますが。。。
そして、気をつけなければいけないのが、フィールド変数と以下のクラスです。
スーパークラス(親クラス)
今回の実装では、PlayerとMonsterクラスが似たような処理だったので、同じ処理はスーパークラスで管理することにしました。
TextRpgGame#init()
でインスタンスを取得している。2つのクラスが実装しています。
具体的には、スーパークラス(親クラス)のCharactor
クラスを継承して実装している。ということです。
そして、ネーミングが悪いのもあるのですが、CharactorクラスはJavaのライブラリの中にもありますのでちょっとだけ注意です。
PlayerクラスとMonsterクラスはデータを保持するクラスです。戦闘して互いのHPを削り合う形でゲームは進むので、ほぼデータクラスです。
「たたかう、ぼうぎょ」などのコマンドはそれぞれのクラスに実装します。PlayerとMonsterでは攻撃方法が違うからです。
PlayerクラスとMonsterクラス
フィールド変数とGetter, Stterを主軸に実装したクラスです。
しかし、HPなどのフィールドはスーパークラスのCharactorクラスへ移動しました。
public abstract class Charactor {
/** 名前 */
protected String name;
/** HP */
protected int hp;
/** MP */
protected int mp;
/** Level */
protected int level;
/** 攻撃力 */
protected int atack;
/** 防御力 */
protected int defence;
/** 武器 */
protected Wepons wepons;
/** 防具 */
protected Armors armor;
/** 抽象メソッド: 攻撃 */
public abstract int attack();
/** 抽象メソッド: 防御 */
public abstract int deffence();
・
・
・
}
このように、スーパークラスでHPなどは管理しています。
これを継承するPlayerは下のようにコンストラクタとスーパークラスの抽象メソッドをオーバーライドします。
public class Player extends Charactor {
/** コンストラクタ */
public Player(int hp, int mp) {
this.hp = hp;
this.mp = mp;
}
/** コンストラクタ */
public Player(int hp, int mp, int level, String name) {
this.hp = hp;
this.mp = mp;
this.level = level;
this.name = name;
// 装備を行う
setArms();
}
/**
* 装備を行う。
*/
private void setArms() {
this.wepons = new Wepons("ひのきのぼう", 5);
this.armor = new Armors("ぬののふく", 5);
}
/**
* 攻撃コマンドのメソッド。
* 武器の攻撃力を返却する。
* @return 武器の攻撃力
*/
@Override
public int attack() {
this.atack = wepons.getAttackPoint();
return this.atack;
}
@Override
public int deffence() {
this.defence = armor.getDeffencePoint();
return this.defence;
}
}
そして、setArms()
というメソッドでは、武器と防具クラスを生成して、Playerクラスのフィールドに設定しています。
名前の通りに、Weponsは武器、Armorsは防具を示しそれぞれ攻撃力と防御力を算出します。
現段階では、攻撃力と防御力がそのまま設定されていますが。。。
とりあえずは、こんな感じで作っています。
GitからPULLして遊んでみてください。
やり方は、こちらの動画にもあります。
記事もあります。
Eclipse GitからPULL
下の方に、関連ページの一覧がありますのでそちらもどうぞ
関連ページ
- Java はじめて 1 〜メインメソッド〜
- Java はじめて2 〜メソッドを呼び出す〜
- Java はじめて3 〜コメントの書き方〜
- Java はじめて4〜練習問題をやってみる〜
- Java はじめて5 〜変数について〜
- Java はじめて6 〜変数について2、byte, char, boolean型〜
- Java はじめて7 〜配列とは、配列の使い方〜
- Java はじめて8 〜booleanとif~
- Java はじめて 9 〜switch文〜
- Java はじめて 10 〜ループ処理A: for文1〜
- Java はじめて 11 〜ループ処理A: for文2 拡張for文〜
- Java はじめて12 〜ループ処理B: while文〜
- Java はじめて13 〜ループ処理C: do-while文〜
- Java はじめて14 〜クラスの作り方〜
- Java はじめて15 〜クラス型変数の使い方〜
- Java はじめて16 〜クラス設計から実装〜
- Java はじめて17 〜設計後の部品を実装する1〜
- Java はじめて18 〜設計後の部品を実装する2〜
- Java はじめて19 〜コンストラクタの役割を見る〜
- Java はじめて20 〜チェック処理クラスを作る〜
- Java はじめて21 〜オブジェクト指向的分析、アプリの拡張をする〜
- Java はじめて22 〜オブジェクト指向的分析、アプリ拡張の実装とテスト〜
- Java はじめて23 〜テスト駆動型開発を行う〜
- Java はじめて24 〜JUnitでのテスト駆動型開発1〜
- Java はじめて25 〜JUnitでのテスト駆動型開発2: テストケース作成〜
- Java はじめて26 〜JUnitでのテスト駆動型開発3: クラスの実装〜
- Java はじめて27 〜JUnitでのテスト駆動型開発4: 追加修正と実装〜
- Java はじめて28 〜JUnitでのテスト駆動型開発5: ファイル出力の実装〜
- Java はじめて29 〜JUnitでのテスト駆動型開発6: ファイル読み込みのテスト〜
- Java はじめて30 〜JUnitでのテスト駆動型開発7: テストクラスの実装方法〜
- Java はじめて31 〜JUnitでのテスト駆動型開発8: 処理をつなげたテスト〜
Git関連
- Java Git clone in Eclipse 〜サンプルの取得〜
- Eclipse Gitリポジトリの取得 〜GitからソースをPullしよう〜
- IntelliJ IDEA Git〜Gitリポジトリからクローン〜
<ins class="adsbygoogle"
style="display:block"
data-ad-format="fluid"
data-ad-layout-key="-6t+ed+2i-1n-4w"
data-ad-client="ca-pub-7367785927150581"
data-ad-slot="3284986237">
関連ページ一覧
Eclipse セットアップ
- Java Install Eclipse〜開発ツールのインストール〜
- TensorFlow C++環境〜EclipseにCDTをインストール〜
- Setup OpenGL with Java〜JOGLを使う準備 for Eclipse〜
- Eclipse Meven 開発手順〜プロジェクトの作成〜
- Java OpenCV 環境セットアップ(on Mac)
- Eclipse SceneBuilderを追加する
- JavaFX SceneBuilder 〜EclipseとSceneBuilder連携~
Java Basic一覧
- Java Basic Level 1 〜Hello Java〜
- Java Basic Level2 〜Arithmetic Calculate〜
- Java Basic Level3 〜About String class〜
- Java Basic Level 4〜Boolean〜
- Java Basic Level 5〜If Statement〜
- Java Basic Summary from Level1 to 5
- Java Basic Level 6 〜Traning of If statement〜
- Java Basic Level8 〜How to use for statement〜
- Java Basic Level 8.5 〜Array〜
- Java Basic Level 9〜Training of for statement〜
- Java Basic Level 10 〜While statement 〜
- Java Basic Swing〜オブジェクト指向〜
- Java Basic Swing Level 2〜オブジェクト指向2〜
- サンプル実装〜コンソールゲーム〜
- Java Basic インターフェース・抽象クラスの作り方
- Java Basic クラスとは〜Step2_1〜
- Java Basic JUnit 〜テストスイートの作り方〜