Javaにおける2Dゲーム描画設計 (キャラクタータスクにビットマップ情報を持たせる)
今回は1/22に説明した、「キャラクタータスクに描画属性を持たせた設計」の描画情報の一つであるビットマップの説明をメインに行いたいと思います。
◇ ◇ ◇
さて、キャラクタータスクに描画属性を持たせた設計では、
【2Dゲームの開発の場合の情報】
・ビットマップ(これは1枚~n枚)
・アニメーション情報(現在何枚目を示しているか等)
ということを説明しましたが、このビットマップをJavaで実現する場合には、「Imageクラス」を用いることができます。ImageクラスはJavaの標準ライブラリで実装されてる高機能なビットマップ情報を保持するクラスとなります。
次にキャラクタータスクより派生したタスクにてアニメーションが行われることを考える場合、このビットマップ情報が複数必要になるので、以下の二つのアプローチが考えられます。
【アニメーションにおけるビットマップの保持方法】
1.ビットマップファイルをアニメーションパターン分作成して、その分のImageクラスを配列で持つ。
長所:プログラミングとは離れたレベルでアニメーションの管理を行いやすい。
短所:「2.」に比べてパフォーマンスが良くない。
2.ビットマップファイルを一枚のみ作成し、この中にアニメーション分のパターンを描いておき、
Imageクラスを1つ持つ。
長所:「1.」に比べてパフォーマンスが良い。
短所:アニメーションが追加された場合など、ビットマップの修正が場合により大変になる。

インターネットにて検索すると「2.」の方式を取るケースをが多く見受けられますが、これには長所/短所や好みがあるので、ここでは話がシンプルにしやすい「1.」の方式で話を進めて行きたいと思います。
(ゲーム上の表現にて大量の計算やメモリを必要とする場合にて、パフォーマンス優先するという場合には、「2.」の方法は必須と思います)
これをプログラムソースで表すと以下のようになります。
【単純なコーディング例(Java) 】
public class CharacterTask extends Task { // 画像集合(アニメーション対応) public ArrayList<Image> m_images = new ArrayList<Image>(); // 現在の画像(この画像が描画対象となります) public Image m_image; // アニメーション画像インデックス(現在どのアニメーションを差しているか) public int m_animeIndex = 0; // アニメーション画像待ち時間(何フレーム後にアニメーションを切り替えるか) public int m_animeWait = 0; public int m_workAnimeWait = 0; } |
この中の"m_images"がアニメーション用のビットマップとなります。
実際に描画を行う対象のImageクラスはメンバ変数"m_image"が、対象となることに注意してください。
これはアニメーションを行わないタスクの場合を考慮してこのように設計しています。

まずはここで説明を一区切りとして、次回はこのImageクラスにビットマップファイルを設定する説明をしたいと思います。
実際に画面に描画されるまで道のりはまだまだですが、一つずつ説明していきたいと思います。
Javaにおける入力情報の保持
Java(JDK 1.5.0_xx)の標準ライブラリにはWindows上のジョイパッドのサポートが行われていません。このため入力はマウス、またはキーボードとなります。
私はマウスで操作するゲーム作りの経験がないので、ここではキーボードのみに話を限定して説明します。
(実際"イベント"としての考え方はキーボードもマウスもそれほど違いがありません。キーボードにはキーリピートの概念がありマウスにはない、マウスにはマウスポインタの座標があり、キーボードにはないという感じです)
Javaの場合はキーボード入力が行われると、ウィンドウやアプレットにprocessKeyEventというイベントが発生し、このイベントの引数に入力されたキーの情報が格納されています。
このイベントはゲームのメインループとは別のタイミングで発生し、タスク処理(キャラクター処理)中にどのようなキーが入力されているか判断できません。そこで、ゲーム処理としては、この情報はこの時点では保存しておくなどして、後のタスク処理などで参照できるようにしておきます。
また、アクションゲームのようなゲームは右左が同時に入力されるというケースは、あまり好ましくないことがあるので(レバーで考えると、左右同時入力はありえないため)、このような制御をここで行っておくと、タスクの方は意識しないで入力された状況を判断することができます。
例として記述するとこのような雰囲気です。
/** // キー押し下げ状態 /** : /** case KeyEvent.VK_DOWN: case KeyEvent.VK_LEFT: case KeyEvent.VK_RIGHT: // ボタン 1 // ボタン 2 // ボタン 3 // SELECT // START // キーアップイベント case KeyEvent.VK_DOWN: case KeyEvent.VK_LEFT: case KeyEvent.VK_RIGHT: // ボタン 1 // ボタン 2 // ボタン 3 // SELECT // START |
Javaにおける画面設計について
この画面には、キーボード入力イベントが発生するので非常に重要となります。
次に画面の中身(実際のゲーム画面)ですが、これは上述したウィンドウ、コンテンツペインの考え方を抽象化したいので、私が行った開発では、これらの中に更にコンポーネントを追加する形を取りました。こうすることにより、将来アプリケーションとしても、アプレットとしても、あまり意識しないで開発できると考えました。
まとめると、
・アプリケーション → ウィンドウとしてデスクトップで表示 → クラスとしては JFrame クラスから派生して作成。
・アプレット → コンテンツペインとしてブラウザ等で表示 → クラスとしては JApplet クラスから派生して作成。
・アプリケーションやアプレットにはキーボード入力イベントが発生する。
・アプリケーションやアプレッドの中にコンポーネントを追加して、ゲーム画面自体はこの中に描画を行う。
こんな感じでしょうか。
