Javaゲーム基本編1「画面表示」

ゲームプログラミング

以前「Javaでゲーム開発」ってタイトルで記事を書いたら中身があまりないにもかかわらず、そこそこアクセスがあるようになった。
そこそこ興味のある人がいるみたいなので続編として、実際に複数回にわたってゲームを実装していくことにする。

もともと記事は自分がゲームを作るという意思表示的に書いただけだったけど、どうせなら情報共有していこう。
ちなみにまだ完成していません。
一応、表示周りはできてきているので参考までに公開してます。
http://www.ligun.net/KanzumeProject/AppletTest.html
これの完成を目指しているので、シューティングゲームの実装をひとつずつ説明していこうかと思います。

上記のプログラムはちょっといろいろと寄せ集め的なところがあって、ソースが汚いので一時開発中断中です。
今回、この記事を書くにあたって一からプロジェクトを作り直して、汚いところを手直ししていこうかと思います。
なるべくわかりやすく書くので、質問等あれば気軽に聞いてください。

一応対象としては下記のような人たちです。

  • Java(もしくは類似言語)の基礎が一通りできる
  • GUIで画面表示やりたいけどわからない
  • わからないところは自分で調べられる
  • eclipseくらいまでの環境構築ができる

まぁ、その他あまりに基礎的なこと以外だったら答えます。

それでは第1回の内容は「画面表示」です。
JavaはGUI周りはそこそこ充実していてC++などに比べたら楽だけど、今まで”Hello,world”敵なCUIプログラムしか書いたことない人にはとっつきづらいだろうから、詳しく書いていく。
こんな基礎的な内容もうわかってるよって人は飛ばしてくれても結構

環境としては私は下記のようになっています。
Javaでの開発なのでSDK入っていれば基本的には問題ないでしょう。

  • OS:windows7 home premium
  • JDKバージョン:7
  • IDE:eclipse 4.2(All in one eclipse)

環境入っていないよって人は、windowsなら下記All in one eclipseをインストールすればいいでしょう。
MergeDocProject

新規プロジェクト作成

第一回なんで長丁寧にeclipseでのプロジェクト作成から書いていくか
まぁ、こんな記事見る人ならたいていわかってるだろうけど

ひとつのプロジェクトでアプリケーションとアプレット両方動くようにする

最初に乗せた僕のサンプルゲームだけど、ブラウザ上でアプレットとして動いてるよね?
でも実はあれ、アプリケーションとして単体で動かすことができる。
人によってどう配布するかはいろいろだけど、両方で出力できるようにする。

画面表示の基礎

JavaでGUIを扱うにはAWTとswingがある。
詳しい説明は省くけど、ウィンドウの機能とかをOSの機能を使って描画するのがAWT、そういうところまでJava内部でやってしまうのがswingってなかんじです。
なのでAWTは実行するOSごとに微妙にデザインが違ったりするけど、swingなら同じデザインになる。そしてAWTのほうが速度的には有利だと言われている(最も現在のJavaなら速度的なメリットはないに等しい)
反面AWTは各OSに共通の部分しか実装されていないけど、swingならひと通り機能が揃っている。
AWTはjava.awt以下のパッケージでswingはjavax.swing以下のパッケージである。AWTはクラス名はFrame、Panelみたいな感じで命名されていて、swingはJFrame、JPanelみたいにAWTの同等クラスの頭にJをつけた形になっている。

今回はメニューとか表示するわけではないのでどちらでもいいと思うけど、swingを使うことにする。

Javaでウィンドウ表示をする時、実装としては下記の図のイメージになる。
JFrame
まず、JFrameというウィンドウを表示する部分のインスタンスを作成する。
そして、その中に実際にキャラクタなどの描画を行うCanvasクラスのインスタンスを作成して、載せる。
アプレットの場合はJFrameの代わりにJAppletとなる。
それでは以下にそのソースを記述していく。

windowを表示する部分の記述

まず、プロジェクトのsrcフォルダの下に適当なパッケージを作成する。
僕の場合はサイトのドメインからパッケージ名をつけているので【net.ligun.gameTest】という風にしている。
特にドメインをもってなければ【example.gameTest】等でもしておきましょう。

次にメインメソッドのあるクラスを作成
作ったパッケージを右クリックして新規→クラスを選択
適当にクラス名をprogramとでもしておく。
下側にあるチェックボックスでmainメソッドの自動追加の部分のチェックを入れる。
継承するクラスのところで参照を押すと継承するクラスが選択できるのでJAppletを選択する。
これでクラスを作成する。

作成したクラスに次のように記述する。

package net.ligun.gameTest;

import javax.swing.JApplet;
import javax.swing.JFrame;

public class Program extends JApplet {

	public void init(){
		GameMain gameMain = new GameMain();
		this.add(gameMain);
		gameMain.start();
	}

	public static void main(String[] args){
		//新しいフレーム(Window)を作成
		JFrame mainFrame = new JFrame();

		//Canvasクラスを継承したGameMainクラスのインスタンスを作成
		GameMain mainCanvas =new GameMain();

		//フレームのタイトルを設定
		mainFrame.setTitle("kanzume project");
		//Xボタン押下時の動作(終了)
		mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		//ウィンドウサイズの固定
		mainFrame.setResizable(false);
		//画面表示
		mainFrame.setVisible(true);

		//フレームにキャンバスを載せる
		mainFrame.getContentPane().add(mainCanvas);

		//フレームサイズをキャンバスに合わせる
		mainFrame.pack();
		//フレームの表示位置を画面中央に置く
		mainFrame.setLocationRelativeTo(null);
		//ゲームのメイン処理スタート
		mainCanvas.start();
	}

}

まず、アプレット側
これはJAppletを継承したクラスのinitメソッドから始まるのでオーバーライドする。
そこで次の項目で追加するGameMainクラスのインスタンスを作成してJAppletの上に載せる。
そしてスレッドを開始する。

次にアプリケーション側
こっちはstaticなmainメソッドから始まる。(クラス作成時に自動で追加されているはず)
こちらはJFrameのインスタンスを作って、そこにGameMainクラスを載せる。
こちらはウィンドウなので、タイトルやXボタンを押下した時の設定が必要である。
mainFrame.pack();という処理があるが、これはGameMainクラスで設定した画面の大きさに合わせてウィンドウを表示させる。この処理を入れないと画面の大きさが設定されず描画領域が表示されない。
その他処理の意味はコメントを見ればわかると思う。

window内に実際にキャラクターなどを配置する部分の記述

Canvasクラスを継承したGameMainクラスを作成する。
programクラスと同様にしてGameMainクラスを作成
下記のように記述する。

package net.ligun.gameTest;

import java.awt.Canvas;
import java.awt.Dimension;
import java.awt.image.BufferStrategy;

public class GameMain extends Canvas implements Runnable {

	//ゲームのメインループスレッド
	Thread gameLoop;
	//BufferStrategy用
	BufferStrategy bstrategy;
	//画面サイズ
	private static final int WIDTH = 800,HEIGHT = 600;

	public GameMain(){
		setPreferredSize(new Dimension(WIDTH, HEIGHT));
	}

	public void start(){
		//BufferedStrategy設定
		//バッファの数2つ(ダブルバッファリング)
		createBufferStrategy(2);
		//CanvasからBufferStrategy取得
		bstrategy = getBufferStrategy();
		//描画を自前でやる
		this.setIgnoreRepaint(true);

		//メインループ用のスレッドを作成して実行
		gameLoop = new Thread(this);
		gameLoop.start();
	}

	public void run(){
		//ここに描画処理
		while(true){
			//とりあえずは何もしない
			try{
				Thread.sleep(1/60*1000);	//1/60秒スリープ
			}catch(InterruptedException e){
				e.printStackTrace();
			}
		}
	}
}

GameMainクラスはRunnableインターフェースを実装しておく。
runメソッドで1フレームの処理、描画、時間計算を行う。
とりあえず今回は画面の表示だけなので1/60間隔でスリープさせておく。

これでビルドしてコンパイルするとウィンドウが表示される。
game_window
今回はここまで

*ちなみに余談だが、実装していて気づいた人もいるかもしれないが、今回swingを使うといったけど実はCanvasクラスはawtのクラスである。でも、Canvasだけはswingコンポーネントの中でも使えたりするんだよね。
Canvasを使う理由はBufferStrategyというクラスを使いたい場合、swingだとJFrameに直接描画するかCanvasクラスを使うしかないのでこのようにした。本来ならCanvasの代わりにJPanelクラスとかでもいいが、今後フルスクリーンモードを実装することを考えると(フルスクリーンモードはBufferStarategyの機能を用いる)Canvasクラスがいいかなと思う。

多分説明が足りないので、見なおしてから今後編集していく。
何か質問があればコメントの方でどうぞ

参考:
http://d.hatena.ne.jp/aidiary/20040918/1251374554

コメント

  1. […] Javaゲーム開発 基本編1「画面表示」 Check カテゴリー: ゲームプログラミング   タグ: Java, ゲーム, シューティング   作成者: りぐん   この投稿のパーマリンク […]

  2. 師子乃 より:

    初めまして、ゲーム開発に興味を持っている者です。

    特にRPGが好きですが、グラフィック表示など共通している部分も多く、勉強になります。

    どうぞよろしくお願いいたします。

    • りぐん より:

      はじめまして
      コメントありがとうございます
      この後全然更新できていないので申し訳ないです。
      もう数年前の記事で古いため、今だとあまり意味ないですね。
      今時だとcocos2dやUnityなどのフレームワークでゲーム作りしたほうが楽だと思います。

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