戻る プログラム ソースリスト (2)

ゲーム Green Ring のプログラムのソースリストです。

前のプログラムに手を加えて、コンピュータが適当にタイミングを計って乱数で決めた位置に図形を表示し、 表示されてから 0.5秒以内にマウスでクリックされれば点数を加え、時間を計算して表示するようにしました。

"/*" と "*/" で囲まれた部分や "//" より右はコメントで、 プログラムの動きには関係がありません。 このページでは緑で表示しています。


/* --------------------------------------------------------------------------------------------
	green_ring.java		ゲーム Green Ring		ver. 1.00 (JDK 1.02)
												ueyama@infonet.co.jp  2000.05.07
-------------------------------------------------------------------------------------------- */

import java.applet.*;
import java.awt.*;
import java.util.*;
public class green_ring extends Applet implements Runnable
{
  int      X0=0,Y0=0;// 図形の表示位置
  int      No=0;// 図形 No.
  int      Time=0;// 経過時間 (1/100秒単位)
  int      Tlimit=50;// 制限時間(0.5秒)
  int      Total=0;// 合計時間
  int      Wait=200;// 図形表示時間
  int      Qty=10;// 正解数
  int      Err=0;// 誤答数
  int      Br=240, Bg=240, Bb=250;// 背景色
  boolean    Run=false;// ゲームの開始・終了
  AudioClip  Pi, Pinpon, Boouu;// 効果音
  
  Graphics  gr;
  Random    Rnd=new Random();
  Thread    th=null;
  
  public void start()
  {
    if(th==null)
    {
      th=new Thread(this);
      th.start();
    }
  }
  
  public void init()
  {
    setBackground(new Color(Br,Bg,Bb));
    gr=getGraphics();
    gr.setFont(new Font("Helvetica",Font.BOLD,20));// 書体と文字サイズの設定
    Pi    =getAudioClip(getCodeBase(), "pi.au");// 効果音データの読み込み
    Pinpon  =getAudioClip(getCodeBase(), "pinpon.au");
    Boouu  =getAudioClip(getCodeBase(), "boouu.au");
  }
  
  public boolean inside(int x, int a, int b)
  {
    return (x<=Math.max(a,b) && x>=Math.min(a,b)) ? true:false;
  }
  
  public void dsp_fig(int x, int y, int n)// 図形の表示
  {
    if(n%2==0)  gr.setColor(Color.red);// n=0:赤正方形 n=1:緑正方形
    else    gr.setColor(Color.green);// n=2:赤円 n=3:緑円 n=4:消去
    if(n/2==0)  gr.fillRect(x+10,y+10,130,130);// n=0 or 1 なら正方形を描く
    if(n/2==1)  gr.fillOval(x,y,150,150);// n=2 or 3 なら円を描く
          gr.setColor(new Color(Br,Bg,Bb));
    if(n/2==0)  gr.fillRect(x+40,y+40,70,70);
    if(n/2==1)  gr.fillOval(x+30,y+30,90,90);
    if(n==4)  gr.clearRect(x,y,150,150);// n=4 なら消去する
  }
 
  
  public void new_fig()// 図形と表示位置を乱数で決める
  {
    dsp_fig(X0,Y0,4);// 前の図形の消去
    Wait=Math.abs(Rnd.nextInt())%101+50;// 表示時間:50〜150 (≒0.5〜1.5秒)
    X0  =Math.abs(Rnd.nextInt())%430+10;// X 座標: 10〜439
    Y0  =Math.abs(Rnd.nextInt())%230+10;// Y 座標: 10〜239
    No  =Math.abs(Rnd.nextInt())%4;// 図形No.: 0〜3
    dsp_fig(X0,Y0,No);// 図形の表示
    Pi.play();// 効果音「ピッ」
    Time=0;// 経過時間をクリア
  }
  
  public void dsp_time()// 時間の表示
  {
    gr.setColor(Color.white);
    gr.fillRect(0,400,600,20);
    gr.setColor(Color.blue);
    gr.drawString("("+Qty+") time; "+Total/100+"."+((Total%100<10)?"0":"")+Total%100+" sec. Error; "+Err,10,416);
  }
  
  public void paint(Graphics g)// 画面の表示
  {
    g.clearRect(0,0,size().width,size().height);
    g.setColor(Color.white);
    g.fillRect(0,400,600,20);
    gr.setColor(Color.blue);
    if(Qty==10) gr.drawString("Click here !",460,416);
  }
 
  
  public void run()// ゲームの処理
  {
    while(true)
    {
      try
      {
        Thread.sleep(10);// 1/100秒待つ
      }
      catch (InterruptedException e){}
      if(Run)
      {
        Time++;// 経過時間カウントアップ
        Wait--;// 表示時間のカウントダウン
        if(Wait==0) new_fig();// 表示時間が 0 になったら次の図形を表示する
        if(Qty==10)// 10 回正解すれば終了
        {
          dsp_fig(X0,Y0,4);// 図形を消去
          dsp_time();
          gr.drawString("Click here !",460,416);
          Run=false;
        }
      }
    }
  }
 
  
  public boolean mouseDown(Event e, int x, int y)// マウスがクリックされたときの処理
  {
    if(y>400 && Qty==10)// 画面下部をクリック。ゲーム開始
    {
      if(X0*Y0>0) dsp_fig(X0,Y0,4);
      Qty=0; No=0; Err=0; Total=0; X0=0; Y0=0; Run=true;// 諸条件の設定
    }
    else if(No==3 && inside(x,X0-10,X0+160) && inside(y,Y0-10,Y0+160))// 緑の円をクリック
    {
      Total+=Time;// 経過時間の更新
      if(Time<=Tlimit)// 規定時間以内
      {
        Pinpon.play();// 効果音「ピンポ〜ン」
        Qty++;// 正解数のカウントアップ
        new_fig();// 次の図形の表示
        dsp_time();// 経過時間の表示
      }
    }
    else// 緑の円以外をクリック
    {
      Boouu.play(); Err++; dsp_time();// 効果音、エラー回数カウントアップ、表示
    }
    return true;
  }
  
  public void stop()
  {
    if(th!=null)
    {
      th.stop();
      th=null;
    }
  }
}

情報処理概論 に戻る  講義資料 に戻る  ゲームを作る に戻る  戻る

 
int      Time=0;
変数(メモリ)の定義をしています。int は integer の略で、整数の変数という意味です。
Time という変数は、このプログラムで、図形が表示されると 0 になり、 以後 1/100 秒毎にカウントアップされます。
 
int      Wait=200;
Wait という変数は、図形の表示時間を表しています。 new_fig() という関数の中で、乱数によって 50〜150 の値が決められます。 約0.5〜1.5秒間図形が表示されることになります。
 
boolean    Run=false;
boolean という型の変数は、true (真) と false (偽) の2つの値だけを取ります。
ここでは、Run という変数が、ゲーム中は true、ゲームが終了すると false になる、 という使い方をしています。
 
public void start()
このプログラムのように、一定時間毎に何かをしたい場合は、スレッド (Thread) というものを使います。
start() というメソッドは、プログラムの開始時に実行されて、 run() メソッドが実行されるようにします。
 
pi.au
"pi.au" も "pinpon.au" も "boouu.au" も、すべて音声データファイルです。 ここでデータを読み込んでおいて、Pi は図形が表示されたときに、Pinpon は正解の時に、 Boouu は間違いの時にならす効果音として使用します。
 
public boolean inside(int x, int a, int b)
inside(int x, int a, int b) は、変数 x の値が a と b の中間であるときに true を返すようにしている関数です。 図形をマウスでクリックしたときのマウスカーソルの位置を調べるために、 mouseDown(Event e, int x, int y) というスレッドで使用しています。
 
Wait=Math.abs(Rnd.nextInt())%101+50;
Wait は、図形の表示時間を表す変数ですが、このプログラムはいくつかの関数や計算をまとめて書いているので、 分かりにくいものになっています。
Rnd.nextInt() は整数の乱数を求める関数で、-2147483648〜2147483647 という、 とてつもなく広い範囲から、ランダムな数値を得ることができます。
このうち、負の数値は必要がないので、絶対値を求める関数 abs() で、正の数値に変換しています。
しかし、ここでほしいのは、ゲームとして面白そうな図形を表示する時間、0.5〜1.5秒 程度の範囲の値です。
このプログラムでは、時間の単位は 1/100秒ですから、 50〜150 の範囲でランダムな値が得られればいいことになります。
 
X0  =Math.abs(Rnd.nextInt())%430+10;
上の Wait=Math.abs(Rnd.nextInt())%101+50; と同様に、乱数を使って図形を表示する x 座標を決めます。
ゲームを作る のページで説明していますが、 図形は画面の周囲 10ピクセル以内に表示したいので、 x 座標は 10〜440、y 座標は 10〜240 の値であればいいことになります。
Wait とまったく同じ方法で 10〜439 の範囲のランダムな値を取得しています。
 
drawString();
drawString(); は文字列を表示するメソッドです。( ) の中には表示したい文字列と、 表示位置の X,Y 座標を指定します。
ここで注意しないといけないのは、Y 座標値は、欧文文字列のベースラインであるということです。
欧文英数字のレタリングの基礎的な知識が必要になります。
 
Thread.sleep(10);
Thread.sleep(); は、Java のプログラムの実行を指定された時間だけ停止します。
停止時間の単位は 1/1000秒ですから、Thread.sleep(10) だと、1/100秒だけ待つことになります。
このプログラムでは、1/100秒待って時間のカウントをしていますから、 ほぼ 1/100秒の精度で応答時間の計算をしていることになります。
 
No==3
No は表示図形の番号で、0 は赤色正方形、1 は緑色正方形、2 は赤の円、3 は緑の円を表しています。
C 言語や Java では、変数の値が 〜 に等しければ、というのを == という記号で表します。
if(No==3) というのは、表示された図形が緑の円であれば、という意味になります。
 
inside(x,X0-10,X0+160) && inside(y,Y0-10,Y0+160)
inside( ) はすでに説明したとおり、変数 x の値が a と b の中間であるときに true を返す関数です。
このプログラムにある && は、"AND" の意味で、 マウスでクリックされた X 座標値と Y 座標値が、いずれも指定された範囲内であれば、 マウスの操作は正しいということになります。
ただし、このような反射神経に依存するゲームでは、マウスのクリック位置も乱れがちになりますから、 表示された図形の 10ピクセル外側をクリックした場合も正解ということにしてあります。

2000.05.09 ueyama@infonet.co.jp