Since 1/15'97

Java applet超入門

Java本家へ To MENU

第9回 Bird SAMPLE

最新 Bird SAMPLE


初めに

 今までのJava実験は、その成果物だけを公開してきましたが、それだけで終わるつもりでないという訳で、順次、文字でも経過を公表することにしました。忘れないうちにという消極的理由もあるのですが。
 もちろん、内容は超入門。Javaはかなり多くのサイトで解説されているようですが、私自身は今のところあまり読んでいない。読んで理解するのが苦手というのが理由ですが。多分、参考になるサイトは数々あるでしょう。
 そんな自分がこんなものを書くというのは矛盾すると思われるでしょうが、初めに書いたように、忘れないため、自分のためなんです。
 もしかして、参考になるかもしれないと考えていただける人は読んでみて下さい。

後で付け加えた初めに

 読者の中には、JavaApplet と JavaScript を混同、あるいは JavaApplet を簡単にしたものが JavaScript だと思っている人もいるようです。しかし、同じ Java という言葉を使っていても全く別物と考えるのが正解です。
 Java はC言語やC++を元にサンマイクロシステム社が開発したウェブページとは無関係にも利用できる言語です。
 この言語から Applet として作った小さなプラグラムをウェブ上で利用します。
 対して、JavaScript はネットスケープ社がウェブページでの利用を前提に開発されたスクリプト言語です。では、なぜ Java と付くかというとよく分りませんが、文法要素をJava言語から引き継いでいるようです。
 書き方において JavaApplet は、命令文の1行の終わりにはC言語と同じく、";" を置くことが必須ですが、JavaScript では、どちらでもよいのです。
 C言語プログラマーは、習慣的に ";" を使いたがるということですが、私は明確に区別するために、";" を使いません。
 要は、JavaApplet と JavaScript は別物です。

※(97.4/5)JDK Ver.1.1.1で再コンパイルするとマウスのイベント処理が拡張されたのでより最適化するには、提供するDocumentを読むようにというWarningが出るが、コンパイルは正常に終わる。Document はまだ読んでいない。

 また、インターラクティブなオブジェクトは導入したいがプログラミングはどうもという人に最適なJava作成ソフトも出てきています。詳細は分かりませんが、自動的にプログラム化してくれるようです。

現在の開発環境

参考書(1)・・・Javaアプレット入門(佐渡秀治/足立隆弘/吉田智子著:ソフトバンク)
 この本は、Javaアプレットの概要説明と簡単なプログラムの例題による説明からなっていて、ページの大半は出来上がったフリーやシェアウエアのアップレット紹介にとどまっていて、これを持って開発するというにはちょっと無理がある。Javaアプレットとは、どんなもので、何が出来るかを知る読み物と思った方がいいかもしれない。
 付属CD-ROMには、JDK1.01と多くのアプレットが収録されている。
※JDK = Java Developer's Kit
参考書(2)・・・Javaプログラミング講座(Sun Microsystems,Inc.:アスキー出版)
 これも入門書であるがプログラムの作成を主眼に置いている。全体を通してプログラムの概要説明と用語のリファレンスとなっている。しかし、用語(や、コマンド)の詳しい説明が省かれているので、これだけで一から作っていくには無理があるかもしれない。
 付属CD-ROMには、JDK1.02と例題となるソースが含まれている。
コンパイラ・・・JDK1.02
ソースエディタ・・・秀丸エディタ
ファイルブラウザ・・・ノートン・ファイルマネージャー
※ノートン・ファイルマネージャーはファイル名の大文字小文字を正確に表示しないので必ずしもお勧めするものではありません。
 JDKのコンパイラはDOSプロンプト上で行う。秀丸エディタで作成し、DOSプロンプトに入り、ソースのあるフォルダにカレントを移動し、コンパイルを行う。
 通常ファイルブラウザにエクスプローラを使っているが、ノートンナビゲータのファイルマネージャを使うとDOSプロンプトに入る時に深いディレクトリにも簡単に移動ができるので、ファイルマネージャを使っている。
※ファイルマネージャを使わなくても、エクスプローラから好みのフォルダに簡単に移動して、DOSプロンプトに入ることができる DosPromptFromHere というプログラムがある。これは、マイクロソフトの PowerToy というフリーソフトのユーティリティ集の中にある。・・・後日入手した
 このファイルマネージャで気を付けないといけないのは、ファイル名の表示が全て小文字を使っていても、先頭大文字で表示され、サーバーのように大文字小文字を区別する環境でファイルが読めないといったトラブルが起こりうる。
 AUTOEXEC.BATにDOSKEYを常駐してあるので、DOSプロンプトでのキー操作も最低限になる。
 一度 C:\BIRD>javac Bird.java 等と打てば、後はカーソルキーと改行キーだけでコンパイルが何回でもできる。
 キー入力は出来れば最低限にしたいといつも思っている。
※DOSKEYに関しては、Windowsでは無用であるがメモリ上に常駐するので、AUTOEXEC.BATから現在は外している。必要な時にDosPrompt上で、doskey /insert とタイプすれば常駐する。 ※(6/26)もっと簡単な方法は、command.comまたはDosPromptのショートカットのプロパティで、プログラム・タブのバッチ ファイルに doskey を書き込んでおけば、DOSプロンプト起動時に常駐する。残念ながら、/insert は書き込めない。常駐後、insert KEY を押せばよい。(詳しくは、Windowsディレクトリにある Tips.txt を参照のこと)

今までに、分かったこれら参考書の問題点

 参考書(1)では、キーワードが網羅されていないので、これでプログラムを作るには情報不足。
 参考書(2)は、キーワードは必要最小限網羅されていると思うが、その意味が説明されていない。
 演算子の == , <= , < などは、なんとなく分かるかもしれないが、++ , -- , &&などは、説明がなければ、多分分からないだろう。これらの演算子については優先順位が列記されているだけである。
 多分、C言語くらいはかじったことのある人を対象にしているようだ。C言語をやっていれば、この辺のところはなんとなく分かる。
 さらに、C++ までやった人なら、オブジェクト指向とかマルチスレッドとかも簡単に分かるかもしれない。この辺のことについては、両参考書とも、分かり易い説明が載っている。ただし、概念までで、具体的にプログラムに応用できるかは別の問題になるけれど。

第1回Java実験

 当初、ホームページ(表紙)に wav形式の小鳥の声を入れていたが、これは IE ( Internet Explorer Ver.xx )でしか、聞くことが出来ない。
 これが NN ( Netscape Navigater ) でも聞けないかということから Javaの実験が始った。IEもVer3.0になってJavaに対応した。Javaであれば、最もポピュラーなブラウザの標準機能で動作する。
 Javaでサウンドを発生するには、wav形式では扱えない。まず、wavの音をau形式に変換しなくてはならない。
変換ソフトとして、取り敢えず、Coolを使う。Win95用にはCool95を使う。シェアウェアであるが、一定の試用期間がある。
 ただ、全て英語のため使い方がよく分からない。とにかく編集したいサウンドデータをCool95.exeか、そのショートカットにドラッグ&ドロップするとデータを読込んで起動する。
 起動すると波形が表示されるので、音の一部だけを切り取りたい時には、切り取りたい音の始点から終点までをドラッグすると色が反転するので、メニューのEditでCopy。FileのNew Instanceを選ぶともうひとつCool95が起動するので、これにPasteする。
 これをSave Asでau形式(Next/Sun(*.au,*.snd))を選択してSaveする。但し、ここで単にSaveしてau形式のファイルが出来てもJavaで使える音にはならない。
 読込んだwavデータのSample Rateは、11025であった。実際に音の出るau形式データのSample Rateを調べると皆、8000となっている。
 メニューのEditにAdust Sample Rateという項目があるので、ここで8000にする。これを保存すると見事音が出た。

 もちろん、ここで音を出すためには、音を出すためのJava Appletが出来ていなくてはならない。

 その時のソースは
//	Bird1.java

import	java.applet.*;

public	class	Bird1 extends Applet {
	AudioClip	cuck;

	public void init() {
		cuck = getAudioClip(getDocumentBase(), "sounds/bird.au");
	}

	public void start() {
		cuck.play();
	}
}
 となる。これは、ほとんど例題から、サウンドに関係ない部分を削除しただけのソースである。ファイル名は Bird1.java とする。
 Bird1.java のあるディレクトリをカレントにしてDOSプロンプトで javac Bird1.java と打てば、同じディレクトリに Bird1.class という実行ファイルができあがる。
 もちろん、このコンパイルの前に、JDKをインストールしておく必要がある。

 いよいよ、HTMLファイルにJavaを実行させるための1行を記入する。

<applet code="Bird1.class" width=100 height=50></applet>
 この1行で、実行できるはずである。但し、これでは、画面に幅100ドット、高さ50ドットのグレーの穴があいてしまう。
 音を出すだけなので、こんな枠は要らない。ということで、
<applet code="Bird1.class"></applet>
 とした。これをIEでローカルな環境で試すと、見事、小鳥の声がして成功だ。すぐさまアップしようと思った時に、ひとつ忘れていたことに気がついた。
 NNでまだ試していない。NNで試すと、なんと、ホームページの真ん中にぽっかりグレーの穴があいている。
 解説書をよくよく見るとwidth=100 height=50は省略できないとある。ここは、width=0 height=0としなければいけないのだ。
 ここでも、IEは間違いを見逃す方向に、NNは間違いをより顕著に表示するという原則が生きていた。果たして、どちらが親切なのか。

ここで、ソースの初歩的な説明

//	Bird1.java
 // に続く文はコメントとなり、行の最後まで、何を書いてもコンパイルには影響しない。通常、タイトルや作成日付などを書いておく。署名などでもよい。
import	java.applet.*;
 全てをはじめからプログラムしなくてもいいように、通常コンパイラには、ライブラリというコードを用意している。この import で、必要なライブラリを取込む宣言をする。java.applet.* は、java.applet.Applet を含むライブラリ(パッケージとも言うようだ)を取込むことになる。HTML文書で利用するには必ず必要となる。
 この他に、画像を扱うには java.awt.Graphics や java.awt.Image などがあるが、これも
import	java.awt.*;
などとしておけばいい。
public	class	Bird1 extends Applet {
 ここから、プログラムの本文に当たる部分を書くことになるが、この1行も決まり文句と思ってよさそうだ。Bird1 が、Appletの名前ということで、勝手に決めてよい。大文字小文字は区別されるので、気を付けたい。
	AudioClip	cuck;
 AudioClip は、オーディオを扱う時の変数を宣言する決まり文句で、cuck が変数ということで、kakou でも、chun でもよい。
 ただし、何を変数にしてもよいわけではない。予約語というものがあり、変数(識別子ともいう)に使ってはいけない言葉(キーワード)もある。例えば、if、do、default、const やベーシックで有名な goto その他があるが、このうち const と goto は、実際には使われないが、識別子として使ってはいけない。
	public void init() {
		cuck = getAudioClip(getDocumentBase(), "sounds/bird.au");
	}
 このルーチンはHTMLが読込まれる時に、一度だけ実行される。cuck という変数に実際の音のファイルを代入するということになる。
 HTMLを置いたディレクトリの下の sounds というディレクトリにある bird.au というサウンドファイルを代入する。
 データの初期化作業を行う。
 cuck と sounds/bird.au 以外は、決まり文句と思って間違いない。
	public void start() {
		cuck.play();
	}
 音を出すルーチンで、public void start() は、このHTMLが表示される度に、実行される。従って、別のページに行って、また戻ると実行され。小鳥が声を出すことになる。

ちょっと一言

 //によるコメントは、どこに置いてもよく、人が読んで分かるように書くというのが鉄則のようである。
 事実、趣味でC言語をやっていた時、結構大きなプログラムを書いていたことがあった。書いている時にはなにもかも頭にあり忘れることはないと思いがちである。が、しばらくして見ると、なぜそうしたかを、すっかり忘れていることがある。
 コメントは、いくらかいても Applet のサイズには影響しない。
 作成中に、人に分かるように書いておけば、後で読み返した時に、他の人が分かるように、自分も分かるということになる。
 明日の自分は今日の自分とは違う。人のためが、実は自分のためになる。

第2回Java実験

 今回は画像の表示。先ず表示したい画像を作成する。そのために画像の大きさの決定。大きすぎず、小さすぎずということで、背景を横400ドット縦30ドットとした。これを元に、HTMLファイルに加える1行は、
<applet code="Bird2.class" codebase="./java/" width=400 height=30></applet>
となる。
 大きさは、width=400 height=30 で指定する。今回は第2回ということで、Bird2.javaというファイル名でソースを作成するので、code="Bird2.class"とする。しかも、Bird2.classをHTMLファイルのあるディレクトリの下のjavaというディレクトリの下に置くので、codebase="./java/" と書く。
 これがなかなか分からなかった。
 通常、code="java/Bird2.class" とすれば、出来そうな気がするが、これではだめ。codebase="java/" も、試してみたが、これもだめ。
 参考書の説明は全て、THMLとAppletが同じディレクトリにあるという前提で書かれていて、codebase= を使った例題がない。
 ともかく、これで、HTML側の設定は出来た。
 この背景に置く小鳥のサイズは縦30ドット、横30ドットとする。PaintshopProを使ったが、Windows標準のPaintでも出来る。但し、背景を透明にしたいので、透過GIF用の変換ツールは必要だろう。PaintshopProであれば、変換ツールは必要ない。
 実は、作成過程でソースを残しておかなかったので、作成時のものとは違うが、次のようなソースとなる。
//	Bird2.java

import	java.applet.*;
import	java.awt.*;

public	class	Bird2 extends Applet {
	AudioClip	cuck;
	Image	im;
	int	MouseX = 50, MouseY = 0;

	public void init() {
		im = getImage(getDocumentBase(), "java/images/Bird.gif");
		cuck = getAudioClip(getDocumentBase(), "java/sounds/bird.au");
	}

	public void start() {
		cuck.play();
	}

	public void paint(Graphics g) {
		setBackground(Color.white);
		g.drawImage(im, MouseX, MouseY, this);
	}

	public boolean mouseDown(Event evt, int x, int y) {
		MouseX = x+20;
		MouseY = 0;
		repaint();
		cuck.play();
		return true;
	}
}

ここで、ソースの初歩的な説明

import	java.awt.*;
 これはグラフィック関係のライブラリを使用するということで、宣言する。必要に応じて awt.* でなく、
	import	java.awt.Graphics;
	import	java.awt.Event;
	import	java.awt.Image;
	import	java.awt.Color;
というように、選択的に並べてもよいが、awt.* で全てを含んでしまう。
	Image	im;
	int	MouseX = 50, MouseY = 0;
 im という変数をイメージデータ用に宣言する。
 int は0から始る整数を宣言する。MouseX は変数で、MX でも構わない。MouseX とした方が分かりやすい。
 イメージデータの座標は左上が(0.0)で、
 Javaのグレーの枠も左上が、(0.0)となる。
 ここでは、MouseXとMouseYの初期値が、左から50ドット、上から0ドットとしている。
		im = getImage(getDocumentBase(), "java/images/Bird.gif");
 これは変数 im に Bird.gif というイメージデータをセットする決まり文句。java/images/Bird.gif はHYMLからの相対パスで記入する。public void init()の中にあるので、最初の1回だけ実行される。
	public void paint(Graphics g) {
		setBackground(Color.white);
		g.drawImage(im, MouseX, MouseY, this);
	}
 ここで画像を表示する。setBackground(Color.white)は、背景すなわちグレーの部分をWhiteにする。g.drawImage(im, MouseX, MouseY, this)により、MouseX, MouseYの位置に、小鳥を表示する。
MouseX, MouseYは、次の
	public boolean mouseDown(Event evt, int x, int y) {
		MouseX = x+20;
		MouseY = 0;
		repaint();
		cuck.play();
		return true;
	}
 により、マウスが押された位置を取得する。
 int x, int yにクリックした時のマウスの座標値が入る。int x とあるのは x が整数であることを宣言している。MouseX = x+20とあるが、MouseX = x とするとマウスの位置の左に小鳥が表示されてしまうので、20ドットずらしている。
 ここでは、マウスを枠内でクリックする度に座標がセットされ、repaint()により、paint(Graphics g)とcuck.play()が実行される。

 ひとつ気がつくことがあるかもしれない。MouseY が 0 以外の値を持っていない。実は、MouseY は、ここでは不要であった。

	int	MouseX = 50;
 でよく、こうした場合、
		g.drawImage(im, MouseX, 0, this);
 とし、
		MouseY = 0;
 は削除しておくこと。
 削除の代わりに
//		MouseY = 0;
 でもよい。

第3、4回Java実験

 実は、開発途中のソースは保存していなかったので、HISTORYに従ってソースを再現する。第3回Java applet実験では小鳥の数を増やす。Lineを引く。第4回Java applet実験では小鳥の向きを変える。背景のImageを置く。とある。
 Lineを引くというのは、小鳥が跳ねる緑のグランド部分をLine関係の関数で描いたということで、
	public void paint(Graphics g) {
		setBackground(Color.white);
		g.drawImage(im, MouseX, MouseY, this);
	}
 に、以下の2行を挿入して
		g.setColor(Color.green);	// 次に描くグラフィックを緑に
		g.fillRect(0,20,400,10);	// int x int y int width,int height

	public void paint(Graphics g) {
		setBackground(Color.white);	// 背景を白に
		g.setColor(Color.green);	// 次に描くグラフィックを緑に
		g.fillRect(0,20,400,10);	// int x int y int width,int height
		g.drawImage(im, MouseX, MouseY, this);	// 小鳥を描く
	}
 とする。fillRectを、次のようdrawRectに置き換えると、中抜きの四角形になり、drawLineに置き換えると、対角線になる。
( x1 y1 は始点、x2 y2 は終点 )
		g.drawRect(0,20,400,10);	// int x1 int y1 int width,int height
		g.drawLine(0,20,400,10);	// int x1 int y1 int x2 int y2
 第4回では、これを次のように、imageに置き換えた。背景のimageデータは予めサイズ400ドット*10ドットで java/images/bird_BG.gif として作成しておく必要がある。
 背景の上の部分(0,0,400,20)は、背景色の白をそのまま表示する。
	AudioClip	cuck;
	Image	im;
	Image	img_BG;	// 背景の変数の宣言
	int	MouseX = 50, MouseY = 0;

	public void init() {
		im = getImage(getDocumentBase(), "java/images/Bird.gif");
		img_BG = getImage(getDocumentBase(), "java/images/bird_BG.gif");	// 背景の変数にimageファイルを代入する
		cuck = getAudioClip(getDocumentBase(), "java/sounds/bird.au");
	}

	public void paint(Graphics g) {
		g.drawImage(img_BG, 0, 20, this);	// 背景を描く
		g.drawImage(im, MouseX, MouseY, this);
	}
 小鳥の数を増やすというのは、同じ小鳥のimageを左端にも配置するということで
	public void paint(Graphics g) {
		g.drawImage(img_BG, 0, 20, this);	// 背景を描く
		g.drawImage(im, 0, 0, this);		// 左端の小鳥( x=0 y=0 に固定)
		g.drawImage(im, MouseX, MouseY, this);	// 移動する小鳥
	}
 とするだけでよい。

第5回Java実験

 今回はアニメする小鳥に変身する。アニメするために3つの右向きの変化する小鳥の画像(カット)を用意する。左向きもあるので、ペインとソフトでそれぞれ反転させてさらに3つ、合わせて6つの画像(カット)を用意する。
 画像は多ければ多いほどスムーズにアニメするが、作成が面倒である。というより、通信時間も考慮する必要がある。あまり多くすると画像を表示するまで、我慢できない待ち時間となる。
 画像のファイル名は、右向きを bird_00.gif , bird_01.gif , bird_02.gif 左向きを bird_10.gif , bird_11.gif , bird_12.gif とする。

 ポイントは各ファイルを数字で識別できるようにすること。
 初めの 0 ,1 が右および左向き、次の 0 , 1 , 2 が各変化するカットを表す。

 変数は2次元配列を使う。2次元配列は「Javaプログラミング講座」には、例題も解説もない。C言語の入門書でも通常は配列までで2次元配列の解説は実習書からということになるので、ちょっと難しいかもしれないが、ここではこのように使うという点にとどめ詳しい解説はここでも省略します。
(以前利用したC言語の解説書は、入門C言語、実習C言語、応用C言語:三田典玄著、アスキー出版局

 とにかく、変数の宣言は
	Image	img[][] = new Image[2][3];
 となり、決まり文句とする。ただし、img は適当に付けた変数の名前で、[2]には 0 ,1 が、[3]には 0 , 1 , 2 がはいる。
 img[0][0] , img[0][1] , img[0][2] , img[1][0] , img[1][1] , img[1][2]という6つの変数となる。
 imageの代入は
	public void paint(Graphics g) {
		for(i = 0; i < 2; i++){	// 右向き(0)と左向き(1)
			for(j = 0; j < 3; j++){	// 右左それぞれ3つのカット
				img[i][j] = getImage(getDocumentBase(), "java/images/bird_"+i+j+".gif");
			}
		}
 となるが、ここには変数 i , j があるので、予め int i,j で宣言しておく。int で整数を宣言。
 for というのは、ベーシックでも有名。i++ は、i に 1を加えるという意味。
	"java/images/bird_"+i+j+".gif"
 は、Javaでは i や j が数字であっても、文字列に変数を + で結ぶと文字列になるという規則があり、java/images/bird_00.gif などに置き換えられる。
 従って
	img[0][0] = getImage(getDocumentBase(), "java/images/bird_00.gif");
	img[0][1] = getImage(getDocumentBase(), "java/images/bird_01.gif");
	img[0][2] = getImage(getDocumentBase(), "java/images/bird_02.gif");
	img[1][0] = getImage(getDocumentBase(), "java/images/bird_10.gif");
	img[1][1] = getImage(getDocumentBase(), "java/images/bird_11.gif");
	img[1][2] = getImage(getDocumentBase(), "java/images/bird_12.gif");
 と i , j という変数を使わず直接数字を書込んでもimageの代入結果は同じになる。
 描画ルーチンはどうなるかというと
	public void paint(Graphics g) {
		setBackground(Color.white);
		g.drawImage(img_BG, 0, 20, this);
		g.drawImage(img[0][sr], 0, 0, this);		//左端に右向きの小鳥
		g.drawImage(img[rl][ss], MouseX, 0, this);	// 移動する小鳥
		g.drawImage(img[1][sl], 370, 0, this);		//右端に左向きの小鳥
	}
 rl,sr,ss,sl は整数で、次の mouseDown で指定する。
	public boolean mouseDown(Event evt, int x, int y) {

		if( MouseX > x-15 ){
// マウス位置が小鳥よりも右か左かを判定している。
// -15は幅30ドットの画像の中央から左端に補正するため
// 次はマウスが小鳥より左なら左を向くように rl に 1 を代入、
// そうでなければ右を向くように 0 を代入
			rl = 1;
		}else {
			rl = 0;
		}
// 次は小鳥のカットを順次変更するための仕組み、
// SS++ によって順次 1 づつ増えていく。
		sl = sr;
		sr = ss;
		ss++;
		if( ss > 3 ){
			ss = 0;
		}
// 小鳥がスクリーンをはみ出さないための仕組み
		if( x<15 ) {
			MouseX = 0;
		} else if( x > 385 ){
			MouseX = 370;
		} else {
			MouseX = MouseX+(x-15-MouseX)/4;
		}
		repaint();
		snd.play();
		return true;
	}

第6、7回Java実験

 これで一応アニメするようになったが、ハードディスク内のローカルな環境では問題ないものの通信環境では画像の読込が遅いので、初めのマウスクリックで一旦小鳥が消えるという現象が起こってしまう。

 その説明の前に、左右の小鳥もその場でアニメするだけでなく、移動を試みる。
	public void paint(Graphics g) {
		setBackground(Color.white);
		g.drawImage(img_BG, 0, 20, this);
		g.drawImage(img[0][sr], 0, 0, this);		//左端に右向きの小鳥
		g.drawImage(img[rl][ss], MouseX, 0, this);	// 移動する小鳥
		g.drawImage(img[1][sl], 370, 0, this);		//右端に左向きの小鳥
	}
 であったが、

	public void paint(Graphics g) {
		setBackground(Color.white);
		g.drawImage(img_BG, 0, 20, this);
		g.drawImage(img[0][sr], 0+MouseX/20, 0, this);	//置換個所1
		g.drawImage(img[rl][ss], MouseX, 0, this);
		g.drawImage(img[1][sl], 370-MouseX/20, 0, this);//置換個所2
	}
 まあどうということはなく、中央の小鳥よりも20分の1だけ移動するようになっている。

 いよいよ、通信環境での遅い画像の読込に対処するために、MediaTracker というのを使う。これは、画像を全て読込むまで、画面表示を待つというもの。
 MediaTracker を使わないと、最初の小鳥の画像は表示されるが、次の画像は、次のクリックがあった後にサーバーから画像を読込もうとするので、クリックしても、一瞬小鳥が消えたようになってしまう。一瞬か長い時間かは、通信速度にもよる。

 この部分のソースは
public	class	Bird extends Applet {
	AudioClip	snd;
	Image	img_BG;
	Image	img[][] = new Image[2][3];
	int	i, j, k, MouseX = 100,rl = 0, ss = 0, sr = 1, sl = 2;
	MediaTracker mt;	// mt という変数の宣言

	public void init() {
		mt = new MediaTracker(this); // MediaTrackerオブジェクト mt の作成
		img_BG    = getImage(getDocumentBase(), "java/images/bird_BG.gif");
		mt.addImage(img_BG, 0);
		for(i = 0; i < 2; i++){
			for(j = 0; j < 3; j++){
				img[i][j] = getImage(getDocumentBase(), "java/images/bird_"+i+j+".gif");
				mt.addImage(img[i][j], 0);
			}
		}
		snd = getAudioClip(getDocumentBase(), "java/sounds/bird.au");
	}

	...................(途中省略)..........................

	public void paint(Graphics g) {
		if( ! mt.checkID(0)){
			g.drawString("Wait ...", 10,20);
			try{
				mt.waitForID(0);
			}catch(InterruptedException e){}
			g.setColor(Color.white);
			g.fillRect(0,0,200,20);
		}
		setBackground(Color.white);
		g.drawImage(img_BG, 0, 20, this);
		g.drawImage(img[0][sr], 0+MouseX/20, 0, this);
		g.drawImage(img[rl][ss], MouseX, 0, this);
		g.drawImage(img[1][sl], 370-MouseX/20, 0, this);
	}

ここで説明

	public void init() {
		mt = new MediaTracker(this); // MediaTrackerオブジェクト mt の作成
 までは、決まり文句と思って下さい。
mt.addImage(img_BG, 0); と mt.addImage(img[i][j], 0); で、読込みを監視するイメージデータを指定する。最後の 0 は、整数で指定される ID で、ここでは ID に 0 を指定して画像をグループ化する。1 を指定すれば別のグループとして監視できる。
		if( ! mt.checkID(0)){			//	(1)
			g.drawString("Wait ...", 10,20);//	(2)
			try{				//	(3)
				mt.waitForID(0);	//	(4)
			}catch(InterruptedException e){}//	(5)
			g.setColor(Color.white);	//	(6)
			g.fillRect(0,0,200,20);		//	(7)
		}
 (1)の ! は次に続く条件式を否定する。mt.checkID(0)は ID が 0 のグループが読込まれていれば、false を返す。! が付くことで falseでない=true(真)となる。すなわち、画像が読込まれていない時に、次の行を実行する。
 (2)は読込みおわるまで、Wait ...を表示する。
 (3)〜(5)が、読込終了まで待機状態になるための指定で、決まり文句と思って下さい。ただし、mt.waitForID(0)で ID を 0 にする。
 (6),(7)は、Wait ...を消すためにあるだけ。

 これで、画像アニメはスムーズになった。しかし、初めに画面が表示されるまでしばらく待たされることになった。
 IE3.0では、なぜか、ページが再表示される度に、しばらく Wait ... が表示されるようになった。NN2.02 でも事情は同じだが、NN3.01ではページの再表示でも即座に画像表示に移る。
 このあたりの理由はよく分からないのだが。

第8、9回Java実験

《 取り敢えず、最終回 》
ここで、一気に最終ソースを掲載する。

 注意点は、小鳥の画像は3個であるが、画像を表示する順序を変化させるために、image[][]の変数は6個用意する。

 この6個をセットしているのは、(注2)の部分で
				switch( j ){ //(注2)j の値により k を 0〜2 の範囲にする。
				case 1:
					k = 1;
					break;
				case 4:
					k = 2;
					break;
				default:
					k = 0;
				}
 小鳥のファイル名の後半の数字になる。bird_ik の k の部分。
 switch( j ){
 case 1: k = 1;  ・・・というのは、j の値が 1 の時、k を 1 にする。ということで、if文に置き換えることができるが、この場合は、switch文の方が表現がすっきりする。
 default: k = 0;  ・・・は、それ以外は k は 0 にする。となる。
 ただし、switch文が使えるのは、j が個々の値を持つ時だけで、j > 0 といった範囲を指定することは出来ない。
//	Bird.java

import	java.applet.*;
import	java.awt.*;

public	class	Bird extends Applet {
	AudioClip	snd;
	Image	img_BG;
	Image	img[][] = new Image[2][6];
	int	i, j, k, MouseX = 100,rl = 0, ss = 0, sr = 1, sl = 2;
	MediaTracker mt;

// ここで、イメージとサウンドの変数をセットする。
	public void init() {
		mt = new MediaTracker(this);
		setBackground(Color.white);
		img_BG = getImage(getDocumentBase(), "java/images/bird_BG.gif");
		mt.addImage(img_BG, 0);
		for(i = 0; i < 2; i++){
			for(j = 0; j < 6; j++){
				switch( j ){ //(注2)j の値により k を 0〜2 の範囲にする。
				case 1:
					k = 1;
					break;
				case 4:
					k = 2;
					break;
				default:
					k = 0;
				}
				img[i][j] = getImage(getDocumentBase(), "java/images/bird_"+i+k+".gif");
				mt.addImage(img[i][j], 0);
			}
		}
		snd = getAudioClip(getDocumentBase(), "java/sounds/bird.au");
	}

	public void start() {
		snd.play();
	}

	public void paint(Graphics g) {
		if( ! mt.checkID(0)){
			g.drawString("Wait ...", 10,20);
			try{
				mt.waitForID(0);
			}catch(InterruptedException e){}
			g.setColor(Color.white);
			g.fillRect(0,0,200,20);
		}
		setBackground(Color.white);
		g.drawImage(img_BG, 0, 20, this);
		g.drawImage(img[0][sr], 0+MouseX/20, 0, this);
		g.drawImage(img[rl][ss], MouseX, 0, this);
		g.drawImage(img[1][sl], 370-MouseX/20, 0, this);
	}

	public boolean mouseMove(Event evt, int x, int y) {

		if( MouseX > x-15 ){
			rl = 1;
		}else {
			rl = 0;
		}
		sl = sr;
		sr = ss;
		ss++;
		if( ss > 5 ){ // ss は 0〜5 までなので、5 を超えたら 0 にする。
			ss = 0;
		}
		if( x < 15 ) {
			MouseX = 0;
		} else if( x > 385 ){
			MouseX = 370;
		} else {
			MouseX = MouseX+(x-15-MouseX)/4;
		}
		repaint();
		snd.play();
		return true;
	}
}
 このソースをそのまま javac でコンパイルすれば、実行できる applet が生成されるはずである。
 これを実行させるための htmlファイルには、

<applet code="Bird.class" codebase="./java/" width=400 height=30></applet>

 を置けばよいが、codebase="./java/" により、Java Applet の置くディレクトリを指定する。これは、htmlファイルのあるディレクトリの下の java というディレクトリに Java Applet を置くということを示す。
 一般の解説書には、この例題がないので、これが分かるのに苦労した部分である。
 小鳥の画像データは java/images に、小鳥のサウンドデータは java/sounds に置くようになっているが、これは、ソースファイルの方で指定する。

最後に

 これで、一応 Java Applet超入門は終わりとしますが、意見、質問等がありましたら、私宛にメールを下さい。私の分かる範囲でお答えしたいと思います。
 なお、ここに掲載された全てについて著作権を放棄するものではありません。ただし、個人の利用の範囲では、ソースの利用および改変について制限は設けませんが、私宛にご一報ください。
 さらに、ここから得られた情報から、あらゆる不都合が生じたとしても一切の責任は負いかねますのでご承知ください。
 なお、ここで利用されている画像および音声データについては提供していませんので、各自の力量で作成下さい。ただ、どうしてもこれらデータを入手したいという方は、一度、私に相談下さい。提供する場を考えたいと思います。

 ここまで読んでいただいた方には、改めて感謝いたします。

To MENU

メインメニューへ