LoginSignup
6
9

More than 5 years have passed since last update.

JavaFXとSceneBuilderで簡単なじゃんけんゲーム

Posted at

夏にやるのかAdventCalendar第10回目です

はじめに

今回はタイトルの通シンプルなじゃんけんゲームを作りたいと思います。
私が以前投稿させていただいた、JavaFX導入の記事の続きくらいの認識で読んでいただけると幸いです。
-はじめてのJavaFX ~簡単な導入Hello world的なGUI作成まで~ 

環境

-macOS Sierra 10.12.6
-Eclipse Oxygen 4.7.3a(プラグインでe(fx)clipse導入済み)
-Scene Builder2.0

実際の作成過程

今回は、前回の記事と違う部分として、application以外のパッケージを作る、画像を使う要素が含まれます。

作りたいモノのイメージ

今回作成するゲームの中の流れは以下のようなものを想定しています。

  1. 待機画面
  2. ゲーム開始(「さいしょはグー、じゃんけん...」で入力待機)
  3. プレイヤーの入力を受けてじゃんけんのリザルト画面へ
  4. 1の待機画面へ

じゃんけんで用意する画像

今回はフリーの素材サイトから拝借しました。

-じゃんけん・グーのイラスト
-じゃんけん・チョキ・ピースのイラスト
-じゃんけん・パーのイラスト

プロジェクト内のパッケージ構成

  • application: FXのGUI関係のソースがここに入る
  • game: 今回のじゃんけんの処理がここに入る
  • pic: じゃんけんの手の画像を入れておく。グー:Rock.png, チョキ:Scissors.png, パー:Papaer.png

SceneBuilder内の操作

SceneBuilder内で操作をします。
前準備として, 前回と同じ手順でeclipseでJavaFXプロジェクトの作成をしてください。
プロジェクト名は「JankenFX」にします。(任意のものでも構いません)
プロジェクトが生成されたら、applicationパッケージのMain.javaを一部書き換えます。
Scene scene = new Scene(root,400,400);
となっている行を
Scene scene = new Scene(root, 500 ,400);
に書き換えます。前準備は以上です。


前準備が終わりましたら、Form.fxmlをSceneBuilderにて開いてください。
最初は中央には何もない状態ですので、画面左下のBorderPaneをクリック、画面右のLayoutでPref widthを500、Pref Heightを400に設定します。ここまでで、画面中央に白いパネルが出てくると思います。

今回のScene Builderでの作業が終わった段階の状態の画像を先に貼ります。
スクリーンショット 2018-08-22 20.42.53.png

BorderPaneの場所ごとに行っている操作は下記の通りです
1. Top
- Label: タイトルや進行状況に応じた文を表記する。fxidに"label_text"を書いています。

  1. Center
    -HBox: HBox内に入ってるパーツは水平に等しく並べられる。propaties内のAlignmentをCENTERにしています。
    HBox内

    • ImageView(左): 自分のじゃんけんの手を描写します。fxidに"image_player"を書いています。
    • ImageView(右): 相手のじゃんけんの手を描写します。fxidに"image_enemy"を書いています。
  2. Left

    • Label: 自分の手だとわかるように、"あなた"と propatiesのtextに書いています。
  3. Right

    • Label: 相手の手だとわかるように、"あいて"と propatiesのtextに書いています。
  4. Bottom

    • HBox:説明省略 HBox内
    • Button (OK): ゲーム画面を進めるためのボタンです。fxidは"button_OK"で、On Actionは"onOKClicked"を書いています。
    • Button (グー): じゃんけんで自分の手を出すためのボタンです。fxidは"button_Rock"で、On Actionは"onRockClicked"を書いています。
    • Button (チョキ): じゃんけんで自分の手を出すためのボタンです。fxidは"button_Scissors"で、On Actionは"onScissorsClicked"を書いています。
    • Button (パー): じゃんけんで自分の手を出すためのボタンです。fxidは"button_Paper"で、On Actionは"onPaperClicked"を書いています。

ここまでの操作、記入を終えたForm.fxmlは下記のとおりです。

Form.fxml

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.image.*?>
<?import javafx.scene.text.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.BorderPane?>

<BorderPane minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="500.0" 
xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8" fx:controller="application.FormController">
   <bottom>
      <HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0" BorderPane.alignment="CENTER">
         <children>
            <Button fx:id="button_OK" mnemonicParsing="false" onAction="#onOKClicked" text="OK" />
            <Button fx:id="button_Rock" mnemonicParsing="false" onAction="#onRockClicked" text="グー" />
            <Button fx:id="button_Scissors" mnemonicParsing="false" onAction="#onScissorsClicked" text="チョキ" />
            <Button fx:id="button_Paper" mnemonicParsing="false" onAction="#onPaperClicked" text="パー" />
         </children>
      </HBox>
   </bottom>
   <top>
      <Label fx:id="label_text" alignment="CENTER" prefHeight="80.0" prefWidth="400.0" text="じゃんけんゲーム" BorderPane.alignment="CENTER">
         <font>
            <Font size="20.0" />
         </font>
      </Label>
   </top>
   <center>
      <HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0" BorderPane.alignment="CENTER">
         <children>
            <ImageView fx:id="image_player" fitHeight="188.0" fitWidth="200.0">
               <image>
                  <Image url="@../pic/Rock.png" />
               </image>
            </ImageView>
            <ImageView fx:id="image_enemy" fitHeight="188.0" fitWidth="200.0">
               <image>
                  <Image url="@../pic/Rock.png" />
               </image>
            </ImageView>
         </children>
      </HBox>
   </center>
   <right>
      <Label text="あいて" BorderPane.alignment="CENTER">
         <font>
            <Font size="15.0" />
         </font>
      </Label>
   </right>
   <left>
      <Label text="あなた" BorderPane.alignment="CENTER">
         <font>
            <Font size="15.0" />
         </font>
      </Label>
   </left>
</BorderPane>

Eclipseでのソース作成

作成するプログラムは、FormController.javaの追記とgameパッケージにBattle.javaを作成する2つになります。
今回作成したソースは、筆者の経験量の浅さもあり、無駄のあるソースとなっていると思います。ご了承ください。

FormController.java

書き換えたものが下記になります。

FormController.java
package application;

import java.util.Random;
import game.Battle;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;

public class FormController {
    @FXML private Button button_OK;
    @FXML private Button button_Rock;
    @FXML private Button button_Scissors;
    @FXML private Button button_Paper;
    @FXML private Label label_text;
    @FXML private ImageView image_player;
    @FXML private ImageView image_enemy;

    private Battle battle= new Battle();
    private final Image ROCK= new Image("pic/Rock.png");
    private final Image SCISSORS= new Image("pic/Scissors.png");
    private final Image PAPER= new Image("pic/Paper.png");

    private int hand_player;
    private int hand_enemy;
    private int result; //じゃんけんの結果をintで保有

    private Random rand= new Random(); //相手の出す手をランダムに生成


//  進行状況1(じゃんけんの入力待機)以外のときに、進行状況を進める
    @FXML
    public void onOKClicked() {
        if(battle.getPhase() != 1){
        battle.nextPhase();
        draw();
        }
    }
    @FXML
    public void onRockClicked() {
        if(battle.getPhase() == 1) {
        hand_player= 1;
        hand_enemy= rand.nextInt(3)+ 1;
        result= battle.battle(hand_player, hand_enemy, battle.getPhase());
        battle.nextPhase();
        draw();
        }
    }
    @FXML
    public void onScissorsClicked() {
        if(battle.getPhase() == 1) {
        hand_player= 2;
        hand_enemy= rand.nextInt(3)+ 1;
        result= battle.battle(hand_player, hand_enemy, battle.getPhase());
        battle.nextPhase();
        draw();
        }
    }
    @FXML
    public void onPaperClicked() {
        if(battle.getPhase() == 1) {
        hand_player= 3;
        hand_enemy= rand.nextInt(3)+ 1;
        result= battle.battle(hand_player, hand_enemy, battle.getPhase());
        battle.nextPhase();
        draw();
        }
    }

//  進行状況に応じて描画の更新をする
    public void draw() {
        switch (battle.getPhase()) {
        case 0:
            label_text.setText("じゃけんゲーム");
            image_player.setImage(ROCK);
            image_enemy.setImage(ROCK);
            break;
        case 1:
            label_text.setText("さいしょはグー、じゃんけん...");
            break;
        case 2:
            image_player.setImage(changeImage(hand_player));
            image_enemy.setImage(changeImage(hand_enemy));
            switch (result) {
            case 1:
                label_text.setText("あなたの勝ちです!!");
                break;
            case 2:
                label_text.setText("あなたの負けです...");
                break;
            case 3:
                label_text.setText("あいこです!");
            default:
                break;
            }
            break;

        default:
            break;
        }
    }

//  じゃんけんの手の画像の更新をする
    private Image changeImage(int hand) {
        switch (hand) {
        case 1:
            return ROCK;
        case 2:
            return SCISSORS;
        case 3:
            return PAPER;
        default:
            return ROCK; //例外
        }
    }
}



続いて、じゃんけんの処理をするBattle.javaです。

Battle.java
package game;

// じゃんけんの処理を行うクラス
public class Battle {

    private int phase; //ゲームの進行状況を保有する

//  オブジェクトの生成時に進行状況0:最初の待機画面で初期化する
    public Battle() {
        this.phase= 0;
    }

//  じゃんけんの処理を行う。自分の勝ちなら1, 負けなら2, あいこなら3をかえす
    public int battle(int p, int e, int phase) { //p:自分の手, e,相手の手
        if(phase==1) {  //進行状況1: 入力待ちのときのみ作動
//          じゃんけんの手は、グー:1, チョキ:2, パー:3
            if(p==1) {
                if(e==1) return 3;
                else if(e==2) return 1;
                else if(e==3) return 2;
            }

            else if(p==2) {
                if(e==1) return 2;
                else if(e==2) return 3;
                else if(e==3) return 1;
            }

            else if(p==3) {
                if(e==1) return 1;
                else if(e==2) return 2;
                else if(e==3) return 3;
            }
        }
        return -1; //例外
    }

    //進行状況を次の段階へ進める。phaseが3になったら、0へ更新
    public void nextPhase() {
        phase++;
        if(phase>2)phase= 0;
    }

    //進行状況のゲッター
    public int getPhase() {
        return phase;
    }
}

以上ふたつのクラスの作成と、じゃんけんの手の画像をpicパッケージにコピーアンドペーストが完了すれば、完成になります。お疲れ様です。

実際に動かす

  1. 初期画面スクリーンショット 2018-08-22 21.26.09.png

  2. 入力待ち画面
    スクリーンショット 2018-08-22 21.26.13.png

  3. 結果 OKボタンを押すと1に戻る
    スクリーンショット 2018-08-22 21.26.21.png

おわりに

今回は、前回のハローワールドからの延長線というポジションで、別パッケージのクラスを利用したり、画像読み込みをしてじゃんけんのゲームを作成しました。
利用する画像を変えたり、SceneBuilderでレイアウトをいじったりして、練習材料にしていただけたら幸いです。

ここまで読んでいただきありがとうございました。

6
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
9