課題 Java Appletプログラミング
Java Applet/AWTについて学び、Java Appletのオリジナルプログラムを作成し解説せよ。


<プログラム>
//FinalBlock
//ブロックくずし

import java.applet.Applet;
import java.awt.*;
import java.applet.AudioClip;
import java.util.*;

public class FinalBlock extends java.applet.Applet implements Runnable{

    MediaTracker mt;

    Image ball, racket;// 表示するボールの絵を入れる変数
    
    int speed = 80; // 表示時間(速度)
    int num = 3; // ボールの残数
    int bx, by; // ボールの位置(x座標、y座標)
    int rx = 96, ry = 249; // ラケットの位置(x座標、y座標)
    int ballWidth = 9, ballHeight = 9; // ボールの絵の幅、高さ
    int racketWidth = 25, racketHeight = 4; // ラケットの絵の幅、高さ
    int playWidth = 218 , playHeight = 270; // ボールが跳ねる範囲の幅、高さ
    int meterWidth = 90 , meterHeight = 270; //その他のパラメーターの幅、高さ
    int margin = 7; // 端まで行かないよう余裕を取る
    int score; // 点数
    int width = 323, height = 285; //ウィンドウ全体の幅、高さ
   
    int block[] = new int[150]; // ブロックがあるかどうかの配列
    int x[] = new int[150]; // ブロックのx座標
    int y[] = new int[150]; // ブロックのy座標
    int blockWidth = 12, blockHeight = 6; // ブロックの幅、高さ

    boolean loop = true;      // 繰り返すための変数
    Thread kicker = null; // アニメーションのためのスレッド変数
   
    Dimension d;  // 表示領域
    Image  offs;  // オフスクリーン
    Graphics grf;   
    AudioClip oto, cancel;   //効果音の宣言
    
    public void init() {
            int i ,j; // カウンター
            int k; // ブロック番号
            int yy; // 段毎のy座標
           
            /* 効果音を読み込む */
            oto = getAudioClip(getDocumentBase(), "oto7.au");       
            cancel = getAudioClip(getDocumentBase(), "cancel.au");
           
            mt = new MediaTracker(this);

             /* イメージファイルの読み込み */
             racket = getImage(getDocumentBase(), "border.gif");      //画像をインポートする
             ball = getImage(getDocumentBase(), "ball.gif");
             mt.addImage(racket,0);
             mt.addImage(ball,0);

            /* ブロックの位置(x、y座標)の設定、15列 × 7段のブロックを作る */
            k = 0;
            for( i = 0 ; i < 8 ; i++ ){      //段数の設定
                    yy = i * (blockHeight+1) +margin*3 ;    //隙間を空ける
                    for( j = 0 ; j < 15 ; j++ ){           //一つの段数のブロックの数を設定
                            x[k] = j * (blockWidth+1) + margin +2 ;     //隙間を空ける
                            y[k] = yy;
                            block[k] = 1; // 一つ一つのブロックの状態を表している配列block[]、 1はブロックがあるという意味
                            k = k + 1;
                    }
            }

            /* オフスクリーンの設定 */
           // 表示領域の取得
            offs = createImage( width, height);
            grf  = offs.getGraphics();

            /* ボールの初期位置の設定 */
            bx = margin + (int)(Math.random() * (float)(width - (margin*2+ballWidth+1)));
            by = 100;

    }

    public void paint(Graphics g) {
            update(g);
    }

    public void update(Graphics g) {
            int i; // カウンター
           
            /* 読み込み中メッセージの表示 */
            if (mt.checkID(0) == false) {
                    g.setColor(Color.black);   //色を決める
                    g.fillRect(0, 0, d.width, d.height);  //範囲を決めて塗りつぶす
                    g.setColor(Color.yellow);
                    g.setFont(new Font("TimesRoman", Font.PLAIN, 18));   //フォントの設定
                    g.drawString("Loading...", 40, 50);
                    return;
            }

            /* バックをオレンジで塗る */
            grf.setColor(Color.orange);     //色を決める
            grf.fillRect(0,0,width, height);    //範囲を決めて線を引く
            grf.setColor(Color.green);
            grf.fillRect(margin,margin, playWidth-margin*2, playHeight);
            grf.setColor(Color.darkGray);
            grf.fillRect(223,8, meterWidth , meterHeight);

            /* ブロックを描く */
            for( i = 0 ; i < 120 ; i++ ){      
                    if ( i < 14 ) {
                            /* 1段目は青 */
                            grf.setColor(Color.blue);       
                    }
                    if ( 15 <= i && i < 29 ) {
                            /* 2段目は赤 */
                            grf.setColor(Color.red);
                    }                    
                    if ( 30 <= i && i < 44 ) {
                        /* 3段目は黄色 */
                        grf.setColor(Color.yellow);
                    }
                    if ( 45 <= i && i < 59) {
                        /* 4段目はマゼンタ */
                        grf.setColor(Color.magenta);
                    }
                    if ( 60 <= i && i < 74) {
                        /* 5段目は白 */
                        grf.setColor(Color.white);
                    }
                    if ( 75 <= i && i < 89 ) {
                        /* 6段目はピンク */
                        grf.setColor(Color.pink);
                    }
                    if ( 90 <= i && i < 104 ) {
                        /* 7段目はオレンジ */
                        grf.setColor(Color.orange);
                    }
                    if ( 105 <= i ) {
                            /* 8段目はグレー */
                            grf.setColor(Color.lightGray);
                    }
                    if ( block[i] == 1 ) {
                            /* ブロックがあれば、ブロックを描く */
                            grf.fillRect(x[i], y[i], blockWidth, blockHeight);
                    }
            }

            /* ボールを描く */
            grf.drawImage(ball, bx, by, this);     //画像ファイルballを読み込みその幅、高さをbx,byにする
           
            /* ラケットを描く */
            /*画像ファイルracketを読み込み、その位置と幅、高さを指定する*/
            grf.drawImage(racket, rx, ry,racketWidth, racketHeight,this);  
            
            /* 点数、残りボール数、ボールスピードの表示 */
            grf.setColor(Color.white);
            grf.drawString("Score  ", 230, 21);  //Scoreの文字の表示
            grf.drawString(" "+score, 237, 38);  //スコアの表示
            grf.drawRect( 233, 25, 74, 15);
            grf.drawString("Boals  ", 230, 61);  //Boalsの文字の表示
            grf.drawString(" "+num, 281, 61);   //残りボール数の表示
            grf.drawString("Boal Speed  ", 230, 81);   //Boal Speedの文字の表示
            grf.drawRect( 233, 86, 41, 15);
            grf.drawString(" "+ speed , 235, 99);    //ボールスピードの表示
            /* ゲームがクリアできなかった時*/
            if ( num < 0 ) {     //ボールの数がなくなる
                    grf.setColor(Color.red);
                    grf.drawString("GAME OVER ", 230, 140);
                    grf.drawString("RESPECT ME!", 230, 165);
            }
            /*クリアできた時*/
            if ( score == 2250 ) {  //ブロックを全て崩したときの点数を得た時
                    grf.setColor(Color.yellow);
                    grf.drawString("PERFECT ", 230, 140);
                    grf.drawString("RESPECT YOU!", 220, 165);
            }
          
                    /* RESTARTボタンの描画 */
                    grf.setColor(Color.blue);
                    grf.fillRect( 242, 189, 62, 20 );  
                    grf.setColor(Color.white);
                    grf.drawString("RESTART", 244, 204);
                    grf.setColor(Color.white);
                    grf.drawRect( 240, 188, 2, 23);
                    grf.drawRect( 240, 188, 61, 2);
                    grf.setColor(Color.black);
                    grf.drawRect( 303, 188, 2, 23);
                    grf.drawRect( 242, 209, 61, 2);
       
            /* オフスクリーンのイメージを一挙に実際の表示領域に描く */
            g.drawImage(offs, 0, 0, this); 
       }    

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

            rx = x; // ラケットの位置の更新

            /* ラケットがコートを出ないための処理 */ 
            if ( rx < margin ) {    //ラケットがmarginから出ないようにする
                    rx = margin;
            }
            if ( rx + racketWidth > playWidth - margin ) {  //ラケットがplayWidthの範囲から出ないようにする
                    rx = playWidth - margin -racketWidth;
            }

            repaint();
            return true;
    }

   public void start() {
            if(kicker == null) {    
                    /* スレッドを実行させる */
                    kicker = new Thread(this);        
                    kicker.start();                 
           }
    }

    public void stop() {
            /* スレッドを止める */
            if ( kicker != null ) {
                    kicker.stop();  
                    kicker = null;
            }
    }

   /* dx,dyでボールの進む量を設定する、ラケットで打ち返すときはdx,dyの値を変えて、進む方向を変更する */
             
    public void run() {
            int dx = 7, dy = 7; // ボールの進む量(x増分、y増分)
            int oldx=0; 
            int i; // カウンター
           
            /* 全てのイメージの読み込みを待つ */
            try{
                    mt.waitForID(0);
            } catch (InterruptedException e) {
                    return;
            }

            /* ずっと繰り返し */
            while(loop) {

                    /* ラケットに当たったときの処理 */
					/* ボールが左端、右端、上端に来たら、逆の方向に進むようにdx.dyの値を設定する */
					/* ラケットに当たらず下まで到達したときは、ボールを元の位置に戻す */
					/* ボールの個数をnumとおいてボールを元の位置に戻すだびにnumから1を引きます */
				if ( by + ballHeight >= ry && by + ballHeight <= ry+racketHeight && bx + ballWidth >= rx && bx <= rx+racketWidth ) {
                    	
                    /*otoファイルを再生する*/
                    	       oto.play();
                    	       oto.stop();
                         
                     	/* ラケットに当たったら上へ返す */
                            dy = -7;
                             
                            if ( bx < rx || bx + ballWidth > rx + racketWidth ) {
                                    /* ラケットの端に当たった時 */
                                    oldx = dx;
                                    if ( oldx == 0 ) {
                                            /* 垂直に来たボール */
                                            if ( bx < rx ) {
                                                    /* 左端に当たったら左斜め上に返す*/
                                                    dx = -7; // 左斜め上に返す 
                                            }
                                            if ( bx + ballWidth > rx + racketWidth ) {
                                                    /* 右端に当たったら右斜め上に返す*/
                                                    dx = +7;
                                            }
                                    } else {
                                            /* 斜めに来たボールは少し斜めにして返す */
                                            dx = 1;                                           
                                    }
                            }                            
                    }

                    /* 左端、右端、上端に来たときの処理 */
                    if (bx < 0 + margin ) {
                            /* 左端に来たら反転 */
                            dx = 7;
                    }
                    if (bx + ballWidth > playWidth - margin) {
                            /* 右端に来たら反転 */
                            dx = -7;
                    }

                    if (by < 0 + margin) {
                            /* 上端に来たら反転 */
                            dy = 7;
                    }
                  
                    /* ラケットの下へ行ったときの処理 */
                    if ( by + ballHeight > playHeight - margin ) {
                            /* 下端に来たらボールを初期位置へ */
                            bx = margin + (int)(Math.random() * (float)(playWidth - (margin*2+ballWidth+1)));
                            by = 100;                                
                            num = num - 1; // ボールの残数を減らす
                             
                    }

                    /* ブロックに当たったときの処理 */
                    for( i = 0 ; i < 120 ; i++ ){           
                    	
                      	     if ( block[i] == 1 ) {
                                    if ( by + ballHeight >= y[i] && by <= y[i]+blockHeight
                                            && bx + ballWidth >= x[i] && bx <= x[i]+blockWidth ){
                                           /*cancelファイルを再生*/
                                    	      cancel.play();
                                            cancel.stop();  
                                    	     /* ブロックに当たったら反転 */
                                            dy = - dy;
                                           /* 得点の加算 */
                                            if ( 10 <= i && i <= 29 ) { // 1、2段目
                                                score = score + 30;                                                    
                                            }
                                             if( 30 <= i && i <= 74 ){  // 3,4,5段目
                                             	 score = score + 20;  
                                            }
                                            else {                     // 6段目以降
                                              	score = score + 10;  
                                            }
                                            
                                            block[i] = 0; // ブロックを消す
                                           /*1~4段目が消された時スピードを?速くする*/                                       
                                            if ( 0 <= i && i <= 59 ) {
                                                speed -= 1;                                                                                                                                                                                   	                                            
                                        }
                                   }                                	
                      	     }
                   	   }

                    /* ゲーム終了の判定 */
                    if ( num < 0 || score == 2250) {     //ボールがなくなるか、全部崩した場合
                            loop = false; 
                    }

                    bx = bx + dx;
                    by = by + dy;   

                    repaint();

                    try{
                            Thread.sleep(speed);
                    } catch (InterruptedException e){}
          }
} 

    public boolean mouseDown(java.awt.Event evt, int ix, int iy){

            if ( ix > 240 && ix < 305 && iy > 188 && iy < 210 ) {
                    /* マウスの座標(ix,iy)がRESTARTボタン内 */
                    /* だったらゲーム再スタート       */
                    stop();
                    gameStart();
                    repaint();
            }
            return true;
    }

    public void gameStart(){
            int i;
            /* 変数の初期化 */            
            num = 3; // ボールの残数をリセット
            score = 0; // 点数のリセット
            speed = 80; // 速度のリセット
            for( i = 0 ; i < 120 ; i++ ){
                    block[i] = 1; // ブロックがある状態に戻す
            }
            bx = margin + (int)(Math.random() * (float)(width - (margin*2+ballWidth+1)));
            by = 100;
            loop = true;
            start();
    }
}



☆考察

<ルール>
マウスでラケットを操作してブロックを全部崩してください。
上4段を崩すとボールのスピードが上がります、そこからスピードが下がる事はありません。
ボールの数は3つまで、横のBoalSpeedは20mphからどんどん速くなります。
*メソッドの説明
Runnableメソッド: このメソッドがメインになるわけですが、ここでこれから使用する変数の宣言をしています。

initメソッド: イメージファイルのラケットやボールを読み込みます、そして8行15列、120個のブロックの位置(x、y座標)を設定します。この時、ブロックの状態(1=ある、0=なし)の配列block[]はすべて、1にしておきます。ボールの初期設定はbx,byにそれぞれ代入して設定します。
 
updateメソッド: ここではblock[]が1のブロックだけ描画するようにします、背景やフォント、ボタン、画面表示に必要な物の設定も行います。

mouseMoveメソッド: ラケットの移動を設定します、このメソッドは、mouseDownメソッドと同じように、イベントを取り扱うメソッドです。mouseMoveは、マウスがアプレット範囲内で動かされると呼ばれるメソッドで、x , yにはそのときの x 座標、y座標の値が入ります。ここで、マウスの x 座標をラケットの x 座標としています。スクリーンをはみ出さないようにラケットの x 座標を調整してます。

startメソッド: スレッドを実行させます。  

stopメソッド: スレッドを停止させます。

runメソッド: ボールの動きを設定します、block[]が1のブロックに当たったら、ボールを反転させ、得点を加算します、得点の加算の方法は1、2段目のブロックは30点、3,4,5段目は20点、それ以降は10点と設定しました、このときblock[]を0にし、ブロックを消します。
ボールが垂直にラケットに当たると少しだけ角度が変わるようにしました。ゲームを面白くするために、上4段のブロックを崩すとボールスピードが少しずつ早くなるようにしました、元の早さには戻らないので、ブロックを崩すほど難易度が高くなります。ゲーム終了の判定もします、num=0すなわち残りボール数がなくなるか、score = 2250 ブロックを全部崩すかした時にそうなるように設定します、try,catchを使ってエラーに対処できるようにもなってます。

mouseDownメソッド: mouseMoveメソッドと同じようにイベントを取り扱うメソッドです。RESTARTボタンを押すとゲームが再スタートされるように設定しています。

gameStartメソッド: ゲームを再スタートさせるメソッドです、残りボールの数、点数、ボールスピード、ブロックを元の状態に戻します。ボールも元の位置に戻します。

<反省、感想>
自分のホームページにアップ出来なくて、提出すつのがおくれたが、出せたのでよかった。

春休みにでも復習をしなきゃなと思いつつ、だらけてしまいそうな

自分が想像できたりもするのでした

<参考文献> 
やさしいC  高橋麻奈 著 Soft Bank Publicing社
独習JAVA ジョセフ・オニール 著 翔泳社 


浅煎り珈琲Java アプリケーション入門 
http://msugai.fc2web.com/java/index.html