JAVAプログラミング講座
宇宙のJAVAさん


< 某 空間 >

悪 宇宙(そら)を落とすには、まず地球から・・・

悪の手先 ぶー!

悪 行け! ぶーよ! われらの力を思い知らしめるのだぁあああああ!

悪の手先 ぶー!

 

・・・・・・・・・

・・・・・・

・・・・

・・

 

< JAVA対策本部@地球 >

 

うし君 JAVAが出たも〜!!

みゃあ またかにゃ! どうするみゃ!

うし君 ぼ、防衛システム、全開もー!

みゃあ レーダーシステム、コンパイルエラーの為、ダウン!!

みゃあ JAVAレベル感知センサー、オーバーフローの為、ダウン!!

うし君 ・・・

うし君 だから、あれほど「short で宣言するな!」と言ったのに・・・

うし君 メモリー節約も、どが過ぎると嫌味だも〜

みゃあ 敵、有視界に入ります!

 


悪の手先 ぶー

 

みゃあうし君 ・・・

みゃあ にゃ? こんなときに くま先生 がいないみゃ?

 

 

< JAVA対策本部付近@地球 >

 

エボ・クマ ふふふふふ・・・

エボ・クマ JAVAC !

 

説明しよう。
くま先生は「JAVAC」と唱えると、高速コンパイルを開始し、
地球を守る宇宙刑事に変身できるのだ。
ときどき変身時に コアダンプ することがあるが、気にしない。
速やかに「.core ファイル」を消して、無かったことにすれば良い。

 

JAVAN 宇宙刑事 JAVAN !!!

 

 

< JAVA対策本部@地球 >


うし君 くそー、どうすることもできないも〜

みゃあ みゃ? あれは、誰だみゃ?

 

JAVAN JAVAN参上!

悪の手先 ぶー!

JAVAN ふ、あまいな。

JAVAN Image、メソッド、flush() !

悪の手先 ぶ?

 

どがぁーーーーーーーーーーーん !

 

JAVAN さらば。

 

突如現れた謎のヒーロー。

その正体はいったい何者なのか?

謎が謎を呼び、爆裂健は酒に逃げる。

次回、宇宙刑事JAVAN 第2話 「コンパイルエラーの秘密」。

君も JAVAを語るプログラマーとなれ!

 

  − 続く −

 


くま先生の ノベルゲームをつくっちゃお(全4回)

第3回 画像を出そう


エボ・クマ さて、前回は画面に文章を表示させました。

エボ・クマ ノベルゲームと言えば、背景に画像が必要です。
そこで 今回は、タグで指定した画像を画面に出すプログラムに挑戦です。

みゃあ JAVANの正体はいったい誰なんだにゃ?

エボ・クマ これこれ、みゃあちゃん。 今はJAVAの講義中ですよ。

みゃあ ごめんみゃ。

うし君 画像はどうやってひょうじするも?

エボ・クマ タグで指定できるようにします。 「CG タグ」を追加しましょう。

CG kuma.gif

と文章内に書くと、 kuma.gif が表示されるようにします。
JAVAで使える画像は、gif と jpeg です。

エボ・クマ では、実際に始めましょう。
表示画像を入れておくための変数を、グローバルで宣言します。
変数名は img です。

// グローバル変数

String scene[];
String screen[];
int now_line;
Image img;

エボ・クマ で、当然 init() img を初期化します 初期値は null です。

public void init() { // 初期処理

scene = new String[1000];
screen = new String[15];
now_line = 0;
img = null;

エボ・クマ 当然 paint()img を表示するプログラムを書きます。
もし imgnull だった場合は、表示しないようにします。

public void paint(Graphics g) { // 作画処理

 g.setColor( Color.gray );
 g.fillRect( 0, 0, 480, 360 );

 if ( img != null ) {
  g.drawImage( img, 0, 0, this );
 }

エボ・クマ これで、画像を表する準備はできました。
つぎにタグの処理です。 これはかなり面倒になります。

タグ処理は SetText() 関数で行います。
前回作った SetText() 関数は、ただ scene[] から screen[] に15行コピーするだけの簡単なものでした。

今回はタグ処理プログラムを書きます。 前回の SetText() 関数の中身のほとんどを消してください。

public int SetText( int line ) {

 for ( int i=0; i<15; i++ ) {
  screen[i] = null;
 }

 for ( int i=0; i<15; i++ ) {
  if (scene[line+i].equals("END")) return 9999;
  screen[i] = scene[line+i];
 }

 if (scene[line+15].equals("END")) return 9999;

 return line+15;

} // SetText()

エボ・クマ さて、前回はただ15行コピーしただけだったので15回ループをすれば処理が終わりました。
しかし今回は、何回ループするかわかりません。

みゃあ にゃ? 15行表示だから、やはり15行ループじゃないのかみゃ?

エボ・クマ 違うんですよ。 文章は15行ですけど、文章の中にタグが入っている場合がありますね。
たとえば、

ある日 森の中 くまさんに出会った
花咲く森の道 くまさんに出会った
くまさんの言うことにゃ お嬢さんお逃げなさい
すたこらさっささのさ すたこらさっささのさ
ところが くまさんが あとから ついてくる
とことことっことっこと とことことっことっこと
お嬢さん お待ちなさい ちょっと 落とし物
仮想配列の JAVAのプログラム
CG kuma.gif
あら くまさん ありがとう お礼に歌いましょう
ラララ ラララララ ラララ ラララララ

この文章が scene[] に入っているとしましょう。
文章は11行ですけど、「CG kuma.gif」という行はタグですので、文章として表示しません。

極端な話、文章が15行で、間にタグが20行入っている場合は、35回ループをしないと画面に表示する15行分の文章が取得できないのです。

みゃあ にゃるほど。

エボ・クマ ですから、ループは無限に行い、条件でループを抜けるようにします。

public int SetText( int line ) {

 for ( int i=0; i<15; i++ ) {
  screen[i] = null;
 }
 
 for ( int i=0; i<1000; i++ ) {
  
 }


} // SetText()

うし君 無限じゃないも? 最大1000回だも?

エボ・クマ 便宜上無限といいましたが、 scene[] の最大行数が 1000 なので、1000回以上ループする必要はないのです。

うし君 なるほども。

エボ・クマ つぎに「画面表示配列 screen[] の何行目まで収納されているか?」を収納する変数を宣言します。
変数名は crt_line です。 これが15に達したら、ループ終了です。

public int SetText( int line ) {

 for ( int i=0; i<15; i++ ) {
  screen[i] = null;
 }

  int crt_line = 0;
 
 for ( int i=0; i<1000; i++ ) {
  
 }

} // SetText()

 

エボ・クマ さて、ここからが今回のメインです!

うし君 おお!

エボ・クマ 「文字列の切り出し」を行います。

みゃあ 切り出しってなんだにゃ??

エボ・クマ 半角スペースで区切られている文字列を、ばらばらにするのです。
つまり、次のような文章が1行あったとします。

ある日 森の中 くまさんに出会った

エボ・クマ この1行を「ある日」「森の中」「くまさんに出会った」に分ける処理です。
ちなみに「ある日」「森の中」「くまさんに出会った」は、半角スペースで区切られています。

エボ・クマ 文字列の切り出しには「 StringTokenizer 」を利用します。
StringTokenizer変数に文字列を入れて、nextToken() メソッドを実行するたびに、左側から文字列が切り出されます。

エボ・クマ ちょっと参考までに、プログラムを作りましょう。

String s = "ある日 森の中 くまさんに出会った";

StringTokenizer st = new StringTokenizer ( s );

String a1 = st.nextToken();
String a2 = st.nextToken();
String a3 = st.nextToken();

エボ・クマ これで文字列の切り出しができます。
さて、うし君、変数 a1、a2、a3 には何が入っているかな?

うし君 a1 には「ある日」 a2 には「森の中」a3 には「くまさんに出会った」 が入っているも〜

エボ・クマ そのとおり。 これでスペースで区切られた個々の文字列を取り出せます。
さっそく、文字列切り出しように変数宣言します。
切り出された文字列を入れるための st1〜st4 変数と、StringTokenizer を宣言します。

public int SetText( int line ) {

 for ( int i=0; i<15; i++ ) {
  screen[i] = null;
 }

 int crt_line = 0;
 String st1,st2,st3,st4;
 StringTokenizer st;

エボ・クマ さて、先ほどの無限(1000回)ループの中に、文字列切り出しのプログラムを書きます。
まず、st1〜st4 を null で初期化して、scene[] の指定行を、切り出しのため StringTokenizer 変数に入れます。

for ( int i=0; i<1000; i++ ) {

 st1=null; st2=null; st3=null; st4=null;
 st = new StringTokenizer(scene[line+i]);

}

エボ・クマ で、st に入っている文字列を、切り出します。

for ( int i=0; i<1000; i++ ) {

 st1=null; st2=null; st3=null; st4=null;
 st = new StringTokenizer(scene[line+i]);
 
 if ( st.hasMoreTokens() ) st1 = st.nextToken();
 if ( st.hasMoreTokens() ) st2 = st.nextToken();
 if ( st.hasMoreTokens() ) st3 = st.nextToken();
 if ( st.hasMoreTokens() ) st4 = st.nextToken();
 if( st1 == null ) st1=" ";


}

うし君 hasMoreToken() ってなんだも???

エボ・クマ それはですね。 まだ文字列が切り出せるかどうか調べる命令です。
すでに切り出し終わっている st st.nextToken() 命令を出すとエラーになりますので、
その前に切り出せるかどうかのチェックをしているんです。

うし君  if( st1 == null ) st1=" "; は、なんだも???
いらないと思うも??

エボ・クマ 必要です。 リターンだけの行があった場合、切り出しは行われずに st1〜st4 すべてに null が入ります。
これから st1 がタグかどうかのチェックをするプログラムを書きますが、null をチェックするとエラーを出すので、半角スペースを入れてやっているのです。

たとえば、

CG kuma.gif

という行が、scene[] にあったとします。
その場合は、

st1 に 「CG」
st2 に 「kuma.gif」
st3 に null
st4 に null

が、入ります。

エボ・クマ じゃ、タグ処理プログラムを書いていきます。
タグ処理プログラムとは「st1 がタグかどうかチェックして、もしタグだったらそのタグの動作をする」というものです。

まずは、「END」タグから・・・

for ( int i=0; i<1000; i++ ) {

 st1=null; st2=null; st3=null; st4=null;
 st = new StringTokenizer(scene[line+i]);

 if ( st.hasMoreTokens() ) st1 = st.nextToken();
 if ( st.hasMoreTokens() ) st2 = st.nextToken();
 if ( st.hasMoreTokens() ) st3 = st.nextToken();
 if ( st.hasMoreTokens() ) st4 = st.nextToken();
 if( st1 == null ) st1=" ";

 // <<タグの処理>>

 if ( st1.equals("END")) {
  return 9999;
 }

エボ・クマ END タグがあった場合は、返り値9999 でリターンします。
なぜ 9999 なのかは、前回の講義を読んでください。

エボ・クマ じゃ、次のタグは「#」タグです!
これは、コメントアウト用のタグにしましょう!
たとえば、

# シーン17(回想シーン)

という行があった場合、何も処理されませんし、この行が画面に表示もされません!

// <<タグの処理>>

if ( st1.equals("END")) {
 return 9999;
}

if ( st1.equals("#")) {
 continue;
}

エボ・クマ 「#」タグは簡単です。 何もしないで次の行を読み込むために continue するだけです。

みゃあ タグを考えるのは楽しいみゃ!
次はどんなタグを追加するみゃ???

エボ・クマ もちろん今回の講義のタイトルのCGを表示するためのタグです。
「CG」タグとしましょう。
たとえば、

CG kuma.gif

という行場あった場合は、画像ファイル「kuma.gif」が画面に表示されます。

// <<タグの処理>>

if ( st1.equals("END")) {
 return 9999;
}

if ( st1.equals("#")) {
 continue;
}

if ( st1.equals("CG")) {
 img = getImage(getDocumentBase(), st2 );
 continue;
}

エボ・クマ st1 が 「CG」だった場合、st2 の画像ファイルを img に読み込みます。
それだけです。

エボ・クマ 同様に、CGを消すタグを作りましょう。
「CGOFF」タグとします。 このタグがあった場合、今表示されている画像が消えます。

// <<タグの処理>>

if ( st1.equals("END")) {
 return 9999;
}

if ( st1.equals("#")) {
 continue;
}

if ( st1.equals("CG")) {
 img = getImage(getDocumentBase(), st2 );
 continue;
}

if ( st1.equals("CGOFF")) {
 img = null;
 continue;
}

エボ・クマ これも簡単です。 img 変数に null 入れるだけです。

さしあたり、今回のタグはこれで終了です。
この要領で「音を鳴らすタグ」などが増やせます。

エボ・クマ では、次にタグでなかった場合の処理です。

みゃあ タグでない場合?? なんだみゃ??

エボ・クマ 何言ってるんですか。 タグでない場合は「文章」ですよ!
画面に表示しなくてはなりません。

みゃあ そうだみゃ!!!!

うし君 これはノベルゲームだも〜 文章忘れちゃ、だめも〜

エボ・クマ では、さっきのタグ処理プログラムの下に追加します。

  if ( st1.equals("CGOFF")) {
   img = null;
   continue;
  }

 
  // <<タグがない場合の処理>>
  screen[crt_line] = scene[line+i];
  crt_line++;

 }

} // SetText()

エボ・クマ ここいらの処理は、前回やりましたね。
scene[] の文章を 画面表示関数 screen[] にコピーします。
で、screen[] crt_line 行まですでに文章が入っていることになってますので、新たに文章をコピーしたら crt_line を1つ増やします。

うし君 なるほども。

エボ・クマ あとは、15行文章を読み終わったかどうかのチェックです。
15行文章が読み終わったら、リターンで返ります。
返り値は line+i+1 になります。 次に scene[] をコピーするための行番号です。
これについても前回の講義を読んでください。

 // <<タグがない場合の処理>>
 screen[crt_line] = scene[line+i];
 crt_line++;
 if (crt_line == 15) return line+i+1;

エボ・クマ あと、前回同様、15行読んだときにすぐ下の行が「END」かどうか調べます。
15行読み終わった後、すぐ下の行が「END」タグだった場合、一見まだ文章が続くように見えますが、事実上文章がすべて終わりだからです。

  // <<タグがない場合の処理>>
  screen[crt_line] = scene[line+i];
  crt_line++;
  if (scene[line+i+1].equals("END")) return 9999;
  if (crt_line == 15) return line+i+1;
 }
 return 9999;

} // SetText()

エボ・クマ それと、最後に return 9999 を書きます。
この行が処理されることはまずないのですが、これがないとコンパイル時にエラーを出します。

エボ・クマ これで、今回のプログラミングは終了です。
ついにこの述べるゲームも、「タグによる制御」ができるようになりました。

みゃあ うごかしてみるみゃ?

エボ・クマ では、文章ファイルにタグを書き込みます。

「#」タグ、「CG」タグ、「CGOFF」タグを書き込みましょう。

あと、「CG」タグで利用する画像も用意しましょう。
画像サイズはゲーム画面サイズと同様、 480x360 が良いでしょう。
GIF と JPEG 画像フォーマットが利用できます。

エボ・クマ これが、今回の文章ファイルです。

 

エボ・クマ では、動かしてみましょう!   

 

みゃあ ちゃんと、画像が出てきて、次に消えるみゃ!

うし君 無事動いてるも〜 コメント行は表示されていないから、「#」タグもOKだも〜

 

エボ・クマ では、次回は次のシーンへ移動するためのプログラムです。
これで、マルチエンディングも思いのまま!

うし君 やっと次回最終回だも〜

エボ・クマ あ、それなんですが、最初に(全4回)って書きましたが、あれ嘘になりました。

うし君 も?

エボ・クマ なんか、4回だと終わない予感が・・・
多分、「ノベルゲームをつくっちゃお」は、全5回 になると思います。

みゃあ さすがは くま先生! いいかげんだみゃ!

エボ・クマ しかも今回は、最初の導入の馬鹿話が長い上に、プログラム説明が多かったので、爆裂健が へろへろ になっています(今!)。

みゃあ 何気に作るのが大変なコーナーだったんだみゃ〜 知らなかったみゃ〜

エボ・クマ では、次回の講座でお会いしましょう!

 

 

テキストファイルのフォーマット(タグ一覧)


# (コメント)        ・・・  コメント用タグ
CG (画像ファイル名)  ・・・  画像表示タグ
CGOFF           ・・・  画像を消すためのタグ
END             ・・・  テキスト(文章)ファイルの最後に必ず書く

 

- 第4話につづく -


宇宙のJAVAさん (C) BakuretuKen 2000

戻る