
| ★はじめに★ |
![]() |
第3話 Zaurus SL-C700でJ2ME CDCのゲームを作る [JAVA PRESS Vol.30] ゲーム:へにへにたたき 対応端末:Zaurus SL-C700
|
![]() |
へにへに、ただいま〜。Zaurus SL-C700を買ってきたよ〜! | |
| 「買ってきたよ〜!」じゃないでしょうに…、そらみちゃんたら、また高価なものを衝動買いして。 | ![]() |
|
![]() |
Linux搭載で640×480の高精細液晶に、臨機応変に活用できる2WAYスタイル。…だけど電池の持ちが悪くて、携帯端末だってのに携帯できやしないところがキュンってしちゃうよね。 | |
| …しょうがないなぁ、そらみちゃんは。そんなんだから高2にもなって彼氏の一人もできないんだよ。まあ、せっかくだし、Javaゲームでも作って動かしてみようか? | ![]() |
|
![]() |
………Zaurusで使えるJava実行環境は、確かPersonalJavaだよね。JDK1.1相当のJavaアプリケーションが動くんだっけ? | |
| 実はZaurus SL-C700用J2ME CDCの実行環境が公開されてたりするんだ。これを使えばJava2相当のゲームを作ることもできるんだよ。 | ![]() |
|
![]() |
あ、それは面白そうかも。PDAもついにJava2仕様に移る時がきたんだねぇ〜。…ってことは、いろいろとパワーアップしてるの? | |
| PDAの実行環境としてはあまり変わってないかもしれないけど、カーナビやセットトップ・ボックスとか、いろんな機器に柔軟に対応できるようになったんだ。 | ![]() |
|
![]() |
う、う〜ん、自由度は広がったみたいだけど、やっぱりあたしはゲームで遊んでみたいかな?まずは手始めに、ペン入力ができるZaurusの特徴を生かして、へにへにたたきでも作ってみよう〜♪ | |
| …へにへにたたき?(汗) | ![]() |
| ★Zaurus SL-C700★ |
「Zaurus SL-C700」は、シャープが2002年12月に発売した、PDA(携帯情報端末)です。世界初の高精細システム液晶を採用した端末で、640x480の高解像度でパソコン画面と同じようにホームページや表計算データの閲覧ができます。また、OSにLinuxが採用されており、Javaの実行環境「Jeode」も搭載されています。
JeodeはPersonalJavaの仕様を採用している組込み機器用Java仮想マシンです。PersonalJavaは、JDK1.1をベースとしている仕様で、執筆時現在(2003年3月)、多くのPDAで採用されています。今回は、最新のJ2ME CDCの実行環境を使うので、Jeodeは使いません。
| ★J2ME CDCとPersonalJava★ |
J2ME
Java言語は、パソコンはもちろん、サーバー、組み込み機器など、様々な用途で使われるようになり、APIの数も膨大になってきました。そこで、Java言語のAPIは3つのエディションに分けられました。J2MEはPDAや携帯電話など組み込み機器で使われるJava実行環境です。J2EEやJ2SEにはサン・マイクロシステムズからSDK(Software Development Kit)が提供されていますが、J2MEにはありません。これはJ2MEが対象とする組み込み機器は、メモリやCPUの処理能力はもちろん、インターフェースも多種多様なため、1つの開発キットとして提供することができないからです。J2MEでは機器に応じて「コンフィギュレーション」と「プロファイル」を組み合わせて使うことになります。
- Java2 Platform,Enterprise Edition(J2EE)‐サーバー向け
- Java2 Platform,Standard Edition(J2SE) ‐クライアント向け
- Java2 Platform,Micro Edition(J2ME) ‐組み込み機器向け
コンフィギュレーション
J2MEでは処理能力の低い機器でもプログラムが動くように、従来のJ2SEから機能を絞りこんだサブセットを定義します。この定義のことを「コンフィギュレーション」と呼びます。執筆時現在(2003年3月)、以下の2つのコンフィギュレーションがあります。「J2ME CDC」はハイエンドのPDAや、カーナビ、セットトップ・ボックスなど中程度の処理能力を持つ端末を対象としているコンフィギュレーションです。Java仮想マシンとしてCVMを利用します。CVMは携帯端末向けに最適化されたJava仮想マシンで、Java2の仮想マシン仕様を完全サポートしています。
- J2ME CDC(J2ME Connected Device Configuration)
- J2ME CLDC(J2ME Connected, Limited Device Configuration)
CDCで規定されているAPIは、基本的にJ2SEから組み込み機器で使用する必要最小限のものが抽出されています。ただし、J2SEの仕様でdeprecated(推奨しない)とマークされたAPIは排除されています。さらに、CDCにはJ2SEにはない、javax.microedition.ioパッケージが存在します。これはCLDCでjava.io、java.netパッケージの代替APIとして導入されたものです。CDCはCLDCのスーパーセットであるという要求仕様に沿って、CDCにも含まれています。具体的にどのようなAPIが使用できるかは、「CDC Specification, V1.0, Final」を参照してください。
- java.langパッケージ,java.ioパッケージ
全てのクラス- java.utilパッケージ
汎用性の高いクラスのみ- java.netパッケージ
UDPデータグラムとファイル入出力関連のクラスのみ- java.textパッケージ
エラーメッセージなどの最小限の国際化をサポートするためのクラスのみ- java.securityパッケージ
Java2セキュリティモデルの利用とオブジェクトシリアライゼーションの暗号化をサポートするクラスのみ- javax.microedition.ioパッケージ
J2ME CLDCで導入されたjava.ioやjava.netの代替API。
「J2ME CLDC」はPDAや携帯電話などの、処理能力やメモリに制限のあるデバイスを対象としているコンフィギュレーションです。iモード、J-PHONEやauの携帯電話、Palm等はこのプロファイルを採用しています。
プロファイル
組み込み機器は、PDAならペン入力、携帯電話ならバイブレーション機能というように、それぞれ特有の機能を持つため、それに対応できるように用途に応じた特殊なAPIが必要になります。このAPIのことを「プロファイル」と呼びます。J2ME CDCの主なプロファイルとしては、以下の4つが挙げられます。
「Foundation Profile」は、CDCに含まれなかったJ2SEの基本的なAPIを補うプロファイルです。CDCとFoundation Profileを組み合わせると、java.io、java.lang、java.math、java.net、java.security、java.text、java.utilパッケージについてはJ2SEと同じになります。「Personal Profile」は、グラフィックス関連の機能を利用するためのプロファイルです。「Personal Basis Profile」は、グラフィックス関連の機能を利用するためのプロファイルで、Personal Profileのサブセットです。組み込み機器によっては、グラフィックスAPIのほどんどが不要なものも存在するため、このようなものが用意されています。「RMI Profile」は、RMI(Remote Method Invocation)をCDCで利用するためのプロファイルです。
具体的にどのようなAPIが使用できるかは、各プロファイルのサイトで入手できるドキュメントを参照してください。
J2ME CDCとPersonalJava
執筆時現在(2003年3月)、多くのPDAではJavaの仕様としてPersonalJavaが採用されています。
PersonalJavaでは、「Write once Run any where(一度プログラムを書けばどこでも動く)」にこだわりすぎたため、パソコンより性能が劣る組み込み機器にまで、同等のアプリが動くことを要求しました。性能も低く、インタフェースも多種多用な組み込み機器では、そのようなことはできるはずもなく、結果として一部の高性能なPDAでのみ使われるようになりました。
そこでJ2ME CDCでは、J2SEのAPIを分類ごとにプロファイルとして分け、組み込み機器の処理能力と機能に応じてどのプロファイルを使うかを選択する形になりました。
J2ME CDCがPDAのJava実行環境としてまだ採用されていないのは、J2ME CDCの標準仕様の整備が大幅に遅れていたためです。今回紹介するJ2ME CDCの実行環境も、サン・マイクロシステムズが提供している参照実装となります。将来的にはPersonal Javaの役割はJ2ME CDCに移行することになるでしょう。
| ★開発環境を整える★ |
開発ツールのインストール
今回のゲームを作るのに必要な開発ツールは次の3つです。どれも無償で入手できます。
Java 2 SDK, Standard Edition Version 1.3(JDK1.3以降)
パソコン上で動くJavaアプリケーションを作るための開発キットです。サン・マイクロシステムズのサイトで入手できます。インストーラの指示に従ってパソコンにインストールしてください。
libfloat
浮動小数を扱うためのライブラリです。J2ME Personal Profile for Zaurusより先にZaurus本体にインストールしてください。ZIPファイルをダウンロードして解凍すると、「libfloat_1.0_arm.ipk」が出現します。拡張子がipkのファイルは、ザウルスへのインストール・パッケージです。ザウルスドライブ(パソコン-Zaurus間でファイルのやりとりを行うアプリケーション)の「本体メモリー/Install_Files」ディレクトリにlibfloat_1.0_arm.ipkを置き、Zaurus SL-C700の設定ホーム画面にある「ソフトウェアの追加/削除」で追加します。ソフトウェアの追加方法の詳細については、Zaurusのマニュアルを参照してください。
![]()
J2ME Personal Profile for Zaurus
J2ME CDCの仕様を採用しているZaurus SL-C700用のJava実行環境です。ダウンロードするには、Java Developer Connectionへのメンバー登録が必要です。ZIPファイルをダウンロードして解凍すると、「personal-profile-for-zaurus_arm.ipk」が出現します。ザウルスドライブの「本体メモリー/Install_Files」ディレクトリにpersonal-profile-for-zaurus_arm.ipkを置き、Zaurusの設定ホーム画面にある「ソフトウェアの追加/削除」で追加します。
開発環境を整える
JDKのbinディレクトリにパスを通す
パソコン上でjavacコマンド(コンパイル)やjavaコマンド(Javaアプリケーションの実行)を使うには、JDKのbinディレクトリにパスを通す必要があります。JDKのbinディレクトリが「C:\jdk1.3.1_04\bin\」の時、パスを通すコマンドは以下のようになります。
set path=C:\jdk1.3.1_04\bin\;%path%
cvmにパスを通す
Zaurus上でcvmコマンド(Javaアプリケーションの実行)を使うには、cvmの置いてあるディレクトリ(/home/QtPalmtop/j2me/bin)にパスを通す必要があります。
Zaurusのアプリケーションホーム画面にある「ターミナル」を起動してください。これは、LinuxのOSにアクセスするためのアプリケーションで、Windowsのコマンドプロンプトに相当します。現在設定されているパスを知るには、echoコマンドを使います。
echo $PATH
デフォルト状態では、以下の情報が出力されます。
/home/QtPalmtop/bin:/root/bin:/bin:/sbin:/usr/sbin:/usr/local/bin
cvmの置いてあるディレクトリは、このパスには含まれていないことがわかります。そこで、cvmのシンボリックリンクを作り、パスが通っている/home/QtPalmtop/binディレクトリ置くことにします。シンボリックリンクは、ファイルに別名をつけるようなもので、Windowsのショートカットに相当します。コマンドは以下の通りです。
su -
ln -s /home/QtPalmtop/j2me/bin/cvm /home/QtPalmtop/bin/cvm
exit
シンボリックリンクを作成する権限を得るために、suコマンドでスーパーユーザーになります。スーパーユーザーとは、何でもできる特権を持ったユーザーでのことです。その後、lnコマンドで/home/QtPalmtop/bin/cvmに/home/QtPalmtop/j2me/bin/cvmのシンボリックリンクを作り、exitコマンドでスーパーユーザーを終了しています。
シンボリックリンクの作成が完了したら、引数なしでcvmコマンドを入力してください。
cvm
パスが通っていれば、cvmの使い方(ヘルプ)が出力されます。
Linuxのコマンドの詳細については、Linuxのマニュアルを参照してください。
| ★文字列の表示★ |
それでは、「Hello World!」という文字列を表示するアプリケーションを作ります。J2ME CDCのアプリケーションの開発方法は、J2SEのアプリケーションの開発方法と基本的に同じです。エディタでJavaのプログラムファイルを作成し、JDKのjavacコマンドでクラスファイルを作成します。
今回のプログラムは、以下の1つのクラスで構成されています。
- HelloWorldクラス‐本体
HelloWorldクラス
HelloWorldクラスは、プログラムの本体となるクラスです。
HelloWorld.java import java.awt.*; import java.awt.event.*; //文字列の表示 public class HelloWorld extends Frame { //コンストラクタ public HelloWorld() { enableEvents(AWTEvent.WINDOW_EVENT_MASK); setSize(240,240); setVisible(true); } //描画 public void paint(Graphics g) { g.drawString("Hello World!",10,40); } //ウィンドウを閉じる protected void processWindowEvent(WindowEvent evt) { super.processWindowEvent(evt); if (evt.getID()==WindowEvent.WINDOW_CLOSING) { System.exit(0); } } //メイン public static void main(String[] args) { new HelloWorld(); } }
import
はじめのimportでは、java.awtパッケージとjava.awt.eventパッケージのクラスを使うことを宣言しています。次で説明するFrameクラスやAWTEventクラスがjava.awtパッケージに、WindowEventクラスがjava.awt.eventパッケージに含まれています。
HelloWorld.javaの一部 import java.awt.*;
import java.awt.event.*;
Frameクラス
Javaアプリケーションの本体となるクラスは、Frameクラスを継承します。Frameを継承したクラスでは、paint()メソッドをオーバーライドしています。paint()メソッドは、Javaアプリケーション起動時や、再描画が必要な時に呼ばれます。このpaint()メソッドに渡されるGraphicsクラスを操作することにより、画面に文字や絵を表示します。
void paint(Graphics g)
g:グラフィックス
Graphicsクラス
文字列を表示するにはGraphicsクラスのdrawString()メソッドを使います。
指定するXY座標は、文字列の左上でなくベースライン左隅の参照点の座標となります。
void drawString(String msg,int x,int y)
text:テキスト
x:X座標
y:Y座標
アプリケーションの終了処理
コンストラクタでは、enableEvents()メソッドによって、ウィンドウのイベントが発生した時、そのコンポーネントに通知するように指定しています。具体的には、processWindowEvent()メソッドが呼ばれます。
HelloWorld.javaの一部 enableEvents(AWTEvent.WINDOW_EVENT_MASK);
processWindowEvent()メソッドに渡されたWindowEventオブジェクトのgetID()メソッドによって、イベント種別を取得できます。
イベント種別定数 WindowEvent.WINDOW_ACTIVATED ウィンドウがアクティブになった WindowEvent.WINDOW_CLOSED ウィンドウがクローズされた WindowEvent.WINDOW_CLOSING ウィンドウをクローズしている WindowEvent.WINDOW_DEACTIVATED ウィンドウがアクティブではなくなった WindowEvent.WINDOW_DEICONIFIED ウィンドウが非アイコン化された WindowEvent.WINDOW_ICONIFIED ウィンドウがアイコン化された WindowEvent.WINDOW_OPENED ウィンドウがオープンされた
アプリケーションを終了させるには、Systemクラスのexit()メソッドを使います。引数には終了ステータスを指定します。通常0でOKです。
void exit(int status)
status:終了ステータス
今回はウィンドウをクローズしている時、アプリケーションを終了させるので、以下のようになります。
HelloWorld.javaの一部 protected void processWindowEvent(WindowEvent evt) { super.processWindowEvent(evt); if (evt.getID()==WindowEvent.WINDOW_CLOSING) { System.exit(0); } }
コンパイルとパソコンでの実行
javacコマンドでHelloWorld.javaをコンパイルします。
javac -g:none *.java
引数「-g:none」の指定して、デバッグオプション(デバッグのための情報)を付けないようにしています。これにより、ファイルサイズの小さくなり、端末への負荷も軽くできます。
成功すればクラスファイル「HelloWorld.class」が生成されます。試しにパソコン上で実行してみてください。
java HelloWorld
実機での実行
ザウルスドライブの「本体メモリー」ディレクトリにHelloWorld.classを置いてください。この場所は、Zaurusの/home/zaurus/Documentsディレクトリに相当します。ターミナルを開いて、/home/zaurus/Documentsディレクトリまで移動してください。ターミナルを起動し時のカレントディレクトリは/home/zaurusなので、以下のコマンドで移動できます。
cd Documents
pwdコマンドでカレントディレクトリを表示して、現在の位置を確かめることができます。
pwd
最後に、cvmコマンドでHelloWorldを実行します。
cvm HelloWorld
| ★イメージの表示★ |
次に、イメージを表示するアプリケーションを作ります。今回のプログラムは、以下の1つのクラスで構成されています。
- ImageExクラス‐本体
画像ファイルの用意
このプログラムで使う画像ファイルは1つです。クラスファイルと同じディレクトリに置いてください。
・そらみ
-sorami.gif
-240x240ドット
ImageExクラス
ImageExクラスは、プログラムの本体となるクラスです。
ImageEx.java import java.awt.*; import java.awt.event.*; import java.util.*; //イメージの表示 public class ImageEx extends Frame { private Image image=null;//イメージ //コンストラクタ public ImageEx(){ //画面 enableEvents(AWTEvent.WINDOW_EVENT_MASK); setSize(240,240); setVisible(true); //MediaTrackerオブジェクトの生成 MediaTracker med=new MediaTracker(this); //イメージの読み込み Toolkit tk=Toolkit.getDefaultToolkit(); image=tk.getImage( this.getClass().getResource("sorami.gif")); //MediaTrackerにイメージを登録 med.addImage(image,0); //イメージ読み込み待ち try { med.waitForAll(0); } catch (Exception e) { } repaint(); } //描画 public void paint(Graphics g) { if (image!=null) g.drawImage(image,0,0,this); } //ウィンドウを閉じる protected void processWindowEvent(WindowEvent evt) { super.processWindowEvent(evt); if (evt.getID()==WindowEvent.WINDOW_CLOSING) { System.exit(0); } } //メイン public static void main(String[] args) { new ImageEx(); } }
イメージの読み込み
Javaアプリケーションでは、ToolkitクラスのgetDefaultToolkit()メソッドでデフォルトのToolkitオブジェクトを取得し、getImage()メソッドで画像ファイル読み込みます。getImage()メソッドの引数として渡すURLは、getClass()メソッドで取得したClassオブジェクトのgetResource()メソッドによって取得します。今回は、sorami.gifを読み込むので、以下のようになります。
ImageEx.javaの一部 Toolkit tk=Toolkit.getDefaultToolkit();
image=tk.getImage(
this.getClass().getResource("0.gif"));
イメージの読み込み待ち
ToolkitオブジェクトのgetImage()メソッドによるイメージの取得の処理は、メソッドから処理が戻ってきても、イメージの読み込みが完了しているわけではありません。別スレッドで読み込み処理を行っています。イメージの読み込みが完了するまで待機したい時は、MediaTrackerクラスを使います。
MediaTrackerクラスのオブジェクトを生成し、addImage()メソッドで読み込み待ちを行うイメージを登録し、waitForAll()メソッドで読み込み完了するまで待ちます。addImage()メソッドやwaitForAll()メソッドで引数として指定するインデックスは、待機するまとまりをいくつかに分けたい時に使うグループIDです。
ImageEx.javaの一部 //MediaTrackerオブジェクトの生成
MediaTracker med=new MediaTracker(this);//MediaTrackerにイメージを登録
med.addImage(image,0);
//イメージ読み込み待ち
try {
med.waitForAll(0);
} catch (Exception e) {
}
| ★へにへにたたきを作る★ |
それでは、本題の「へにへにたたき」を作ります。画面をタップするとゲームがスタートします。へにへにが穴から顔を出すので、ペンでたたいてください。1回たたくと30点です。30秒間にどれだけたたけるかを競います。このゲームは、以下の2つのクラスで構成されています。
- HeniStrikeクラス‐本体
- HeniCanvasクラス‐キャンバス
画像ファイルの用意
このゲームでは以下の3枚の画像ファイルを使います。クラスファイルと同じディレクトリに置いてください。
・穴
-0.gif
-80x80
・へにへに(出現)
-1.gif
-80x80
・へにへに(ヒット)
-2.gif
-80x80
HeniStrikeクラス
HeniStrikeクラスは、プログラムの本体となるクラスです。
HeniStrike.java import java.awt.*; import java.awt.event.*; import java.util.*; //へにへにたたき(本体) public class HeniStrike extends Frame { public static HeniStrike current; //コンストラクタ public HeniStrike(){ //カレント current=this; //画面 setTitle("へにへにたたき"); setLayout(new BorderLayout()); HeniCanvas canvas=new HeniCanvas(); add(canvas,BorderLayout.CENTER); pack(); show(); enableEvents(AWTEvent.WINDOW_EVENT_MASK); //スレッド Thread thread=new Thread(canvas); thread.start(); } //ウィンドウイベント protected void processWindowEvent(WindowEvent evt) { super.processWindowEvent(evt); if (evt.getID()==WindowEvent.WINDOW_CLOSING) { System.exit(0); } } //メイン public static void main(String[] args) { new HeniStrike(); } }
タイトルバーの文字列
フレームのタイトルバーの文字列を指定するには、FrameクラスのsetTitle()メソッドを使います。
void setTitle(String title)
title:タイトル
今回は"へにへにたたき"と表示させるので、以下のようになります。
HeniStrike.javaの一部 setTitle("へにへにたたき");
キャンバスの追加
キャンバスなどのコンポーネントをフレームに追加する時は、その配置方法を指定します。今回は、BorderLayoutという上下左右および中央にコンポーネントを配置する方法を指定しました。
HeniStrike.javaの一部 setLayout(new BorderLayout());
HeniCanvas canvas=new HeniCanvas();
add(canvas,BorderLayout.CENTER);
pack();
レイアウトの指定には、setLayout()メソッドを使います。
void setLayout(LayoutManager mgr)
mgr:レイアウトマネージャ
BorderLayoutを指定した時は、add()メソッドの第2引数に配置位置を指定します。
void add(Component comp,int index)
comp:コンポーネント
index:配置位置
配置位置 BorderLayout.CENTER 中央 BorderLayout.WEST 左 BorderLayout.EAST 右 BorderLayout.NORTH 上 BorderLayout.SOUTH 下
最後に、pack()メソッドによって、キャンバにフィットするようにフレームサイズを変更しています。
HeniCanvasクラス
HeniCanvasクラスは、キャンバスとなるクラスです。
HeniCanvas.java import java.awt.*; import java.awt.event.*; import java.util.*; //へにへにたたき(キャンバス) public class HeniCanvas extends Canvas implements Runnable,MouseListener { //システム private int init=0;//初期化(0:タイトル,1:プレイ,2:終了) private int scene; //シーン private int time; //時間 private int score; //スコア private int[] state=new int[9];//状態(0:無,1:出,2:当) //ダブルバッファ private Image imgOff;//オフイメージ private Graphics graOff;//オフグラフィックス //コンストラクタ public HeniCanvas(){ setSize(240,240); addMouseListener(this); } //更新 public void update(Graphics g) { if (imgOff!=null) g.drawImage(imgOff,0,0,this); } //実行 public void run() { int i; //システム Image[] image=new Image[3];//イメージ Random rand =new Random();//乱数 //ダブルバッファ imgOff=HeniStrike.current.createImage(240,240); graOff=imgOff.getGraphics(); Font font=new Font("SansSerif",Font.PLAIN,16); FontMetrics fm=getFontMetrics(font); graOff.setFont(font); //イメージ読み込み MediaTracker med=new MediaTracker(this); Toolkit tk=Toolkit.getDefaultToolkit(); for (i=2;i>=0;i--) { image[i]=tk.getImage( this.getClass().getResource(i+".gif")); med.addImage(image[i],0); } try { med.waitForAll(0); } catch (Exception e) { } while (true) { //初期化 if (init>=0) { scene=init; init =-1; if (scene==1) { time =300; score=0; for (i=8;i>=0;i--) state[i]=0; } } //へにへに for (i=8;i>=0;i--) { //描画 graOff.drawImage(image[state[i]], (i%3)*80,(i/3)*80,this); //状態遷移 if (scene==1 && time%10==0) { if (state[i]==0 && (rand.nextInt()>>>1)%10==0) { state[i]=1; } else if (state[i]==1 || state[i]==2) { state[i]=0; } } } //ステータス graOff.setColor(Color.blue); graOff.drawString("時間:"+time,10,20); graOff.drawString("スコア:"+score, 230-fm.stringWidth("スコア:"+score),20); //メッセージ if (scene==0) { graOff.setColor(Color.red); graOff.drawString("へにへにたたき", (240-fm.stringWidth("へにへにたたき"))/2,120); } else if (scene==1) { if (--time==0) init=2; } else if (scene==2) { graOff.setColor(Color.red); graOff.drawString("タイムオーバー", (240-fm.stringWidth("タイムオーバー"))/2,120); } //再描画 repaint(); //スリープ try { Thread.sleep(100); } catch (Exception e) { } } } //マウスプレスイベント public void mousePressed(MouseEvent evt) { //タイトル if (scene==0) { init=1; } //プレイ else if (scene==1 && 0<evt.getX() && evt.getX()<240 && 0<evt.getY() && evt.getY()<240) { int index=evt.getX()/80+(evt.getY()/80)*3; if (state[index]==1) { state[index]=2; score+=30; } } //終了 else if (scene==2) { init=0; } } public void mouseClicked(MouseEvent evt) {} public void mouseEntered(MouseEvent evt) {} public void mouseExited(MouseEvent evt) {} public void mouseReleased(MouseEvent evt) {} }
シーンの遷移
今回のゲームには、以下の3つのシーンがあります。現在のシーンはint型変数sceneで保持しています。次に遷移するシーンはint型変数initで保持しています。遷移しない時はinitは-1を保持しています。
- 0.タイトル
"へにへにたたき"という文字列を表示するシーンです。画面をペンでタップすると、シーンは「プレイ」に遷移します。- 1.プレイ
実際にゲームをプレイするシーンです。30秒たったら、シーンは「終了」に遷移します。- 2.終了
"タイムオーバー"という文字列を表示するシーンです。画面をペンでタップすると、シーンは「タイトル」に遷移します。
へにへに状態の遷移
へにへにには、以下の3つの状態があります。現在の状態はint型配列stateで保持しています。穴は9つあるので、配列の長さも9となります。
- 0.穴
へにへにが穴に隠れている状態です。乱数によって状態は「へにへに(出現)」に遷移します。- 1.へにへに(出現)
へにへにが穴から出ている状態です。一定時間がたったら状態は「穴」に遷移し、ペンでタップしたら「へにへに(ヒット)」に遷移します。- 2.へにへに(ヒット)
へにへにがたたかれている状態です。一定時間がたったら状態は「穴」に遷移します。
マウスリスナー
マウスリスナーは、マウスの移動やクリックなどのイベント情報を受信するためのリスナーです。今回は、HeniCanvasクラス自身にMouseListenerインタフェースを実装します。Java言語では、インタフェースを実装していることを示すために、implementsキーワードの後にインタフェース名を記述します。
HeniCanvas.javaの一部 public class HeniCanvas extends Canvas
implements Runnable,MouseListener {
次に、CanvasクラスのaddMouseListener()メソッドで、イベントが発生した時、そのことをどこへ送信すればよいかを指定します。今回はHeniCanvasクラス自身がリスナーになるのでthisをセットします。
HeniCanvas.javaの一部 addMouseListener(this);
最後に、MouseListenerインタフェースが持つ5つのメソッドを実装します。今回は、mousePress()メソッドのみシーンの遷移やへにへにたたきの処理を行い、他のメソッドは空となります。
- mouseClicked()メソッド - コンポーネント上でマウスがクリックされると呼ばれる
- mousePressed()メソッド - コンポーネント上でマウスボタンが押されると呼ばれる
- mouseReleased()メソッド - コンポーネント上でマウスボタンが離されると呼ばれる
- mouseEntered()メソッド - コンポーネントにマウスが入ると呼ばれる
- mouseExited()メソッド - コンポーネントからマウスが出ると呼ばれる
ダブルバッファリング
ダブルバッファリングとは、画面と同じサイズのイメージを用意し、必要なものをこのイメージに描画してから、実画面に一変に反映させるという処理です。描画するところ1つ1つが見えて、画面がちらついてしまうことを防ぎます。イメージを生成するには、FrameクラスのcreateImage()メソッドを使います。また、イメージに描画するためのGraphicsオブジェクトを取得するには、getGraphics()メソッドを使います。
HeniCanvas.javaの一部 imgOff=HeniStrike.current.createImage(240,240);
graOff=imgOff.getGraphics();
Javaアプリケーション起動時や、再描画が必要な時、実機はまずupdate()メソッドを呼び、update()メソッドは画面クリア(デフォルト色での塗り潰し)を行ってからpaint()メソッドを呼びます。そのため、そのままではこの画面クリアもちらつきの原因となってしまいます。そこで、update()メソッドをオーバーライドし、画面クリアを行わず、ダブルバッファリング用のイメージを描画するようにしました。
HeniCanvas.javaの一部 public void update(Graphics g) {
if (imgOff!=null) g.drawImage(imgOff,0,0,this);
}
フォント
フォントの幅を取得するには、FontMetricsクラスを使います。Fontクラスを引数に、FontMetricsクラスを生成し、
stringWidth()メソッドで文字列の幅を取得します。
int stringWidth(String string)
string:文字列
戻り値:文字列の幅(ドット)
今回は、フォントに16ドットのSansSerifを指定して、文字列を画面中央に表示するので、以下のようになります。
HeniCanvas.javaの一部 Font font=new Font("SansSerif",Font.PLAIN,16);
FontMetrics fm=getFontMetrics(font);
graOff.setFont(font);graOff.drawString("へにへにたたき",
(240-fm.stringWidth("へにへにたたき"))/2,120);
| ★おわりに★ |
次回は、iモードの505iシリーズの新機能を使ったゲームを作る予定です。お楽しみに。
−戻る−
(C)Npaka/Sehira, 2003-2004