Advertisement
  1. Game Development
  2. Java
Gamedevelopment

ゲーム開発のための JavaFX 入門

by
Difficulty:IntermediateLength:LongLanguages:

Japanese (日本語) translation by Hiro (you can also view the original English article)

JavaFXはJavaでのクロスプラットフォームGUIツールキットです、またJava Swingライブラリー後継でもあります。 このチュートリアルでは、ゲームプログラミングを簡単に始めることができるJavaの特色を手引していこうと思います。

このチュートリアルはJavaの知識がすでにあることを前提に進めていきます。 もしそうでなければ、次のサイトを参照してくださいLearn Java for Android , Introduction to Computer Programming Width Java: 101201 , Head First Java, Greenfoot, また Learn Java the Hard Way

導入

もしもうすでにJavaを使ったアプリケーション開発の経験があるならば、おそらくなにもダウンロードする必要はないでしょう、JavaFXはJDK 7u6(2012年/8月)から標準バンドルされています。 もししばらくの間Javaをアップデートしていなければ、こちらで最新バージョンをインストールしてください。

基本的なフレームワーククラス

JavaFXプログラムの作成はApplicationクラスをもって行います。 メインクラスはlaunch()メソッドを呼ぶ必要があります、呼ぶとinit()メソッドが呼ばれ次にstart()メソッドが呼ばれる設計です、アプリケーションの終了まで待ち、終了時に呼ばれるメソッドがstop()メソッドです。 これらのメソッドの中でstart()メソッドだけが抽象でありオーバーライドされる必要があります。

StageクラスはトップレベルJavaFXコンテナです。 アプリケーション起動時、初期化ステージが作成されアプリケーションのstartメソッドに引数として渡されます。 Stageは基本的なタイトルやアイコン、可視やリサイズ可能、フルスクリーンモード、装飾といったウィンドウプロパティを操作します、装飾はStageStyleを使うことで設定できます。 追加ステージをつくることが必要な場合があるかも知れません。 ステージを作りコンテンツを追加したあとshow()メソッドが呼ばれます。

これらすべてを知ることで、JavaFXでウィンドウを表示するミニマムな例を作ることができるようになります。

コンテンツの構築

JavaFXのコンテンツ(テキスト, 画像, その他UIコントロールなど)はシーングラフというツリー状のデーター構造を使って構成されています。

JavaFX Scene Graph
JavaFX シーングラフの表現

JavaFXでのシーングラフの一般的な要素はNodeと呼ばれています。 ツリーの中のどのNodeも"親"ノードを持っています、例外として(親Nodeをもたない)特別なNodeはrootと呼ばれています。 Groupは多くの"子"ノードを持つことのできるNode要素です。 Groupに適用されたグラフィカルトランスフォーメーション(変形, 回転, 拡大縮小)とエフェクトは、その子Nodeにもまた適用されます。 NodeはJavaFX Cascading Style Sheets(CSS)を使ってデザインすることができます、それはHTMLドキュメントに使用されるCSSの構文にとても似ています。

Sceneクラスはシーングラフのためのすべてのコンテンツを含み、またルートNodeをセットする必要があります(このチュートリアルでは、そのルートNodeにGroupをよく使います)。 Sceneのサイズは任意に設定できますが、設定しない場合、SceneのサイズはそのSceneが含むコンテンツを元にして計算されたサイズが自動的に設定されます。 SceneオブジェクトはsetScene()メソッドによってStageに表示する順番に追加していく必要があります。

グラフィックのレンダリング

レンダリンググラフィックは特にゲームプログラマーにとって大切なものです。 JavaFXではCanvasオブジェクトにGraphicsContextオブジェクトを介して文字、図形、画像といったイメージを描画していくことができます。 (Java Swingツールキットに慣れた多くの開発者へ、これはJFrameでpaint()メソッドに渡されるGraphicsオブジェクトによく似ています。)

GraphicsContextオブジェクトは豊富でパワフルでカスタマイズ生に富んでいます。 文字や画像描画のための色を塗りつぶし色と境界色をPaintオブジェクトを使って選ぶことができます、Paintオブジェクトを継承クラスには単色の表現のColorオブジェクト、ユーザー定義のグラーデーション(LinearGradientRadialGradient)、ImagePatternがあります。 また複数のEffectスタイル(LightingShadowGaussianBlur)を適用でき、また既定のフォントからFontクラスを用いてフォントを変更することもできます。

Imageクラスは様々なファイルフォーマットからの画像のロードを簡単にします、そしてそれらはGraphicsContextクラスを介して描画されます。 WritableImageクラスとPixelReaderクラスとPixelWriterクラスを使って画像の作成を簡単にすることができます。

これらのクラスを使うことによって、より価値のある以下の例のような"Hello World"を描くことができるようになります。 簡潔にするために、ここからstart()メソッドのみ示します(import文とmain()メソッドを省略するということです)、こちらから完全に動作するコードを見つけることができます the GitHub repo that accompanies this turorial

ゲームループ

さて、そろそろプログラムを動的にしていく必要があります、時間毎にゲーム状態が変わっていくという意味です。 ゲームループを実装します、ゲームオブジェクトの更新、画面への描画のための無限ループは、1秒間に60回であることが望ましいです。

これをJavaFXで達成するために最も簡単な方法はAnimationTimerクラスを使う方法です、そのhandle()メソッドは1秒間に60回あるいはできる限りそれに近い割合で呼ばれます。 (このクラスは単にアニメーションの目的で使用される必要はなく、もっと別の用途にも使用されています。)

AnimationTimerクラスの使用は少々トリッキーです、なぜなら抽象クラスであるので、直接インスタンスを作成できないからですーこのクラスはインスタンス作成前に継承される必要があります。 しかしながらこのチュートリアルではこのクラスを匿名内部クラスに書くことで継承しています。 その内部クラスでは抽象メソッドであるhandle()メソッドを定義する必要があります、そのメソッドには現在のシステム時間がナノ単位で引数で渡されます。 内部クラスの定義後、すぐにゲームループを開始するためにstart()メソッドを呼びます。 (このループはstop()メソッドで止めることができます。)

これらのクラスを用いることで、さきほどのHello, Worldの例を拡張して星明りの背景画像を背にして太陽の周りを回る地球のアニメーションを作ることができます。

ゲームループをJavaFXで実装する別の方法がいくつか存在します。 すこし冗長になる(しかし柔軟性は高いです)方法にTimelineクラスがあります、それはKeyFrameオブジェクトとセットにしたアニメーションシーケンスです。 ゲームループを作るために、Timelineは無限リピートをするように設定する必要があり、また最低でも一つの、Durationを0.016秒に設定したKeyFrameを必要とします。 この実装はthe GitHub repoExample3T.javaで見つけることができます。

フレームベースのアニメーション

フレームベースのアニメーションもまたゲームプログラミングにとって必要な要素です、動きのあるアニメーションを作成するためにイメージを連続的に表示します。

すべてのアニメーションとすべてのフレームが同じ秒数ごとに同じ結果を表示するとすれば、基本的な実装は下記のようである。

このクラスを前の例にまとめることによって、アニメーションされたUFOを作成することができます、オブジェクトの初期化は次のコードを使います。

そして、AnimationTimer内にこのコードを、

適切な場所に挿入します。 完全なコードは the GitHub repo のファイル Example3AI.java で見ることができます。

ユーザー入力の検知

JavaFXはユーザー入力の検知と処理を簡単に行なえます。 システムに検知可能なキープレスやマウスクリックといったユーザーアクションはイベントと呼ばれます。 JavaFXでは、これらのアクションは(KeyEventMouseEventのような)それに関するデーター(キーやマウスポインタの位置など)を格納するオブジェクトを自動的に生成します。 EventTargetクラスを実装したSceneのようなJavaFXのクラスはイベントと入力の"監視"をすることができます、下記の例では、Sceneをいろいろなイベント処理をするように設定する方法を示します。

Sceneクラスのドキュメンテーションを見ると、様々な入力タイプからの処理を監視するための多くのメソッドがあることがわかります。 例えば、setOnKeyPressed()メソッドはキープレスされたときに呼ばれるEventHandlerを割り当てることができます、setOnMouseClicked()メソッドはマウスのボタンが押されたときに呼ばれるEventHandlerを割り当てることができます。 EventHandlerクラスの用途は、対応するイベントが発生したさいに呼ばれるメソッド(handle()メソッド)をまとめるこおです。

EventHandlerを作成する際、Eventの種類を明示的にする必要があります、例えばEventHandler<KeyEvent>EventHandler<MouseEvent>などといった宣言ができます。 また、EventHandlerはよく匿名内部クラスとして作られます、なぜならそれらは一般的に一度しか使用されないからです(それらが上記のようなメソッドに引数として渡されるときです)

キーボードイベントの処理

ユーザー入力はよくメインゲームループのなかで処理されます、またしたがって記録は現在アクティブなキーを保持し続けないければなりません。 これを達成する一つの方法はString型のArrayListを作成することです。 キーが初めて押されたとき、そのKeyEventのKeyCodeのString表現をそのリストに追加します、またそのキーが離されたとき、リストからそのキーを削除します。

下記の例では、そのキャンバスは矢印キーを表す2つの画像が表示されています、キーがプレスされたとき、対応する画像が緑色になります。


このソースコードはthe GitHub repoにてExample4K.javaファイルに含まれています。

マウスイベントの処理

さて、KeyEventクラスよりもMouseEventにフォーカスを当てた次の例を見てみましょう。 このミニゲームは、プレイヤーがターゲットがクリックしたときにポイントを得るというゲームです。


EventHandlerは内部クラスですから、変数はfinal、あるいは"事実上のfinal"でなくてはなりません、これは変数は変更さることができないという意味です。 先ほどの例では、データはArrayListを用いてEventHandlerに渡されました、ArrayListのデータは再初期化なしに値を変更することができます(add()メソッドとremove()メソッドを通じて)。

しかしながら、基本的なデータタイプの場合、その値は変更できません。 もしEventHandlerにプログラムのどこでも変更される基本的なデータタイプにアクセスさせたい場合、publicな変数ないしゲッター/セッターメソッドを持つラッパークラスを作成する必要があります。 (下記の例を見てください、IntValuevalueと呼ばれるpublic intの変数を持つクラスです)

完全なソースコードはthe GitHub repoExample4M.javaに保存されています。

JavaFXを使った基本的なスプライトクラスの作成

ビデオゲームでは、スプライトはチームのための単一の可視の実体です。 下記は画像と位置、もちろん速度情報(可動性の実体のための)と衝突判定のための領域を計算するときに必要な縦/横のサイズ情報を持ったスプライトクラスの例です。 また標準的な多くのデータのためのゲッター/セッターメソッド(簡潔にするために省略しています)、といくつかのゲーム開発に必要な標準的なメソッドも持ちます。

  • update() : そのスプライトの速度情報に基づき位置情報を計算します。
  • render() : そのスプライトのイメージをキャンバスに描画します(GraphicsContext クラスを介して)座標として位置情報を使用します。
  • getBoundary() : JavaFXのRectamgle2Dオブジェクトを返します、そのオブジェクトには衝突判定をするintersectsメソッドがあるので便利です。
  • intersects() : そのスプライトの領域が他のスプライトに衝突するか判定します。

完全なソースはthe GitHub repoSprite.javaに含まれています。

スプライトクラスの使用

スプライトクラスのおかげで、簡単にJavaFXで簡素なコレクティングゲームを作ることができます。 このゲームでは、あなたは前の持ち主の注意不足によってそこらじゅうにおいていかれた大金のバッグを集めることが目標の意識のあるブリーフケースになります。 矢印キーで画面の中のプレイヤーを動かします。

このコードは今までの例から多くのもの借りてできています、それはスコアを表示するフォントの設定、ArrayListでのキーボード入力の取得、AnimationTimerでのゲームループの実装、ゲームループ中に変更される必要がある値をラップするクラスの作成です。

特にこのコードの興味深い部分はプレイヤーのためのSpriteオブジェクト(briefcase)とコレクションのためのスプライトオブジェクトのArrayList (money bags)を含んでいます。

他の興味深いコードの部分は下記のタスクのAnimationTimerの作成です。

  • 最終更新から経過した時間の計算
  • 現在のキープレスによるプレイヤーの速度設定
  • コレクションとプレイヤーの間の衝突判定の実行と、スコアと存在しているコレクションリストの更新(イテレーターはリストからオブジェクトを削除するときのConcurrent Modification Exceptionを避けるためにArrayListで直接やるよりも良いです)
  • スプライトとテキストのキャンバスへの描画

いつもどおり、完全なコードはthe GitHub repoExample5.javaファイルより見つけることができます。

次のステップへ

  • 次のリンクはあなたをJavaFXの学びに助けるであろうOracleの入門的なチュートリアルのコレクションです : Getting Started with JavaFX Sample Applications
  • もしかしたらSceneBuilderの学習に興味がでるかもしれません、それはユーザーインターフェイスのデザインレイアウトを直感的に構築できるものです。 このプログラムはXMLベースの言語のJavaFXでユーザーインターフェイスの定義に使われるFXMLを生成します。 詳しくは、こちらです JavaFX Scene Builder: Getting Started
  • FX Experienceは素晴らしいブログです、定期的に更新され、それにはJavaFX開発者に興味深い情報とサンプルプログラムが含まれています。 多くの掲載されているデモはとても刺激的です!
  • José Peredaは素晴らしいJavaFXで作られた様々な工夫のあるゲームサンプルです、彼のGit Hub repositoryはこちらです。
  • JFxtras projectはJavaFXに今不十分な部分を拡張したJavaFXコンポーネントの開発者グループで構成されるものです。
  • JavaFXPorts project はあなたのJavaFXアプリケーションをiOSやAndroidで展開することを可能にします。
  • JavaFXのための公式リファレンスをブックマークする必要があります、特にOracle's JavaFX guiteAPI documentationです。
  • JavaFXで評価のある本は、Pro JavaFX 8JavaFX 8 - Introduction by Example、また特にゲーム開発者に注目のある Beginning Java 8 Games Developmentです。

終わりに

このチュートリアルでは、ゲーム開発に役立つJavaFXクラスを紹介していきました。 どんどん複雑さをます例題の数々をこなし、スプライトベースのコレクション制のゲームをマスターしました。 さて今、上記の資料を研究や挑戦、またオリジナルゲームの作成の準備はできています。 あなたの努力に最高の幸あれ!

Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.