// ====================================================================
//           Baku Puzzle Ver0.12    (c) BakuretuKen & Great-KUMA 1998  
// ====================================================================

import java.applet.Applet;
import java.awt.*;
import java.net.*;
import java.awt.image.*;
import java.applet.AudioClip;
import java.util.StringTokenizer;
import java.net.MalformedURLException;
import java.io.*;

// ===============================================================

public class BakuPuzzle extends Applet implements Runnable {
	
	// グローバル変数
	Image img, img2;
	// ダブルバッファリング用の宣言
	Graphics bg;
	Image backimage;
	// ＣＧ完成判別用配列
	int puzz[];
	// ＣＧが完成しているかどうか？
	boolean isWin;
	// 完成後ＵＲＬジャンプ
	String jumpURL;
	// 完成後ボーナスＣＧ
	String bonusCG;
	// スレッド
	Thread thread;
	MediaTracker mt;
	AudioClip au1;
	
	// -----------------------------------------------------------
	public void init() {  // 初期処理
		
		// 自己ＰＲ（爆）
		System.out.println("Baku Puzzle Ver 0.12 (c)BakuretuKen 1998\n" );
		
		// ダブルバッファリング初期宣言
		backimage = createImage( 480, 560 );
		bg = backimage.getGraphics();
		
		// ＣＧ完成判別用配列 初期宣言
		puzz = new int[36];
		
		// 初期状態でＣＧは完成していない
		isWin = false;
		
		jumpURL = null;
		img2 = null;
		
		// サウンドの読みこみ
		au1 = getAudioClip( getDocumentBase(), "sound1.au");
		
		// 画像(image.jpg)を変数(img)に読みこむ
		String s = getParameter("cg");
		if (s == null) s = "image.jpg";
		img = getImage(getDocumentBase(), s);
		
		// 画像完成後に飛ぶＵＲＬ設定
		s = getParameter("jump");
		if (s != null)  jumpURL = s;
		
		// 画像完成後に表示するボーナスＣＧ設定
		s = getParameter("bonus");
		if (s != null) img2 = getImage(getDocumentBase(), s);
		
		// puzz[] に順番に数字をいれる（初期状態）
		for (int i=0; i<36; i++) puzz[i]=i;
		
		// MediaTracker を使っての画像の読みこみ
		mt = new MediaTracker(this);
		mt.addImage( img, 0);
		if( img2!=null ) mt.addImage( img2, 0);
		
	} // init()
	
	// -----------------------------------------------------------
	public void paint(Graphics g) {  // 作画処理
		
		
		if (mt.isErrorID(0)) {
			g.setColor(Color.red);
			g.fillRect(0, 0, 480, 480);
			g.setColor(Color.yellow);
			g.setFont(new Font("TimesRoman", Font.BOLD, 25 ));
			g.drawString("Error", 190, 230);
			return;
		}
		
		if (mt.checkID(0)) {
			// 裏画像を表に転送
			g.drawImage( backimage, 0, 0, null );
			if( ! isWin ){
				g.setColor(Color.black); // 裏画像の作画ペンの色を黒に
				// すべてのパネルを四角で囲む
				for ( int x=0; x<6; x++ )
					for ( int y=0; y<6; y++ )
						g.drawRect( x*80, y*80, 80, 80 );
			}
			// もし完成後、ボーナスＣＧがあれば表示
			if(isWin && img2!=null) g.drawImage( img2, 0, 0, null );
		
		} else {
			g.setColor(Color.gray);
			g.fillRect( 0, 0, 480, 480 );
			g.setFont(new Font("TimesRoman", Font.ITALIC, 15 ));
			g.setColor(Color.black);
			g.drawString("Bakuretu Puzzle Ver0.12 (c)BakuretuKen 1998", 2, 15);
			g.setFont(new Font("TimesRoman", Font.BOLD, 20 ));
			g.setColor(Color.blue);
			g.drawString("CG Reading...", 180, 230);
		}
		
	} // paint()
	
	// -----------------------------------------------------------
	public void update(Graphics g) {  // 再作画処理
		paint( g );
	} // update()
	
	// -----------------------------------------------------------
	public boolean mouseDown(Event e, int x, int y) {  // マウスダウン
		
		// もし完成してジャンプ先が決まっていれば、ＵＲＬジャンプ
		if (isWin && jumpURL!=null) {
			try {
				this.getAppletContext().showDocument( new URL(getDocumentBase(), jumpURL ));
			} catch ( IOException err ) {
				System.err.println("URL JUMP Error !!! : "+jumpURL );
			}
		} // if
		
		// もしすでにＣＧが完成してるなら何もしない
		if (isWin) return true;
		
		// マウスがクリックされた場所のパネルを調べる
		int px, py;
		px= (int)( x/80 );
		py= (int)( y/80 );
		
		// 左上のパネルと入替える
		kcopy( 0, 0, 0, 6);
		kcopy( px, py, 0, 0);
		kcopy( 0, 6, px, py);
		
		// puzz[] の数字も入替え
		int tmp = puzz[ 0 ];
		puzz[ 0 ] = puzz[ py*6+px ];
		puzz[ py*6+px ] = tmp;
		
		au1.play(); // サウンド
		
		// ＣＧが完成したかどうかのチェック
		int c;
		for (c=0; c<36; c++){
			if (puzz[c] != c) break;
		}
		
		// テスト出力
		// for(int i=0; i<36; i++)
		//	System.out.print( puzz[i]+" ");
		// System.out.println( "\n ");
		
		
		// もし完成していたら、isWin を真に変更
		if( c==36 ) isWin = true;
		
		// 再作画
		repaint();
		
		return true;
	} // mouseDown()
	
	// -----------------------------------------------------------
	public boolean mouseUp(Event e, int x, int y) {  // マウスアップ
		
		return true;
	} // mouseUp()
	
	// -----------------------------------------------------------
	public boolean mouseDrag(Event e, int x, int y) { //  マウス移動
		
		return true;
	} // mouseDrag()
	
	// -----------------------------------------------------------
	public void start() { // 動作スタート時の処理
		if (thread == null) {
			thread = new Thread(this);
			thread.start();
		}
	} // start()
	
	// -----------------------------------------------------------
	public void stop() { // 動作一時停止時の処理
		if (thread != null) {
			thread.stop();
			thread = null;
		}
	} // stop()
	
	// -----------------------------------------------------------
	public void run() { // タイマー処理 本体
		try {
			mt.waitForID(0);
		} catch (InterruptedException e) {
			return;
		}
		RndPannel();
		repaint();
		if (thread != null) {
			thread.stop();
			thread = null;
		}
	} // run()
	// -----------------------------------------------------------
	// 簡単コピー関数 kcopy()
	void kcopy( int x, int y, int dx, int dy) {
		bg.copyArea( x*80, y*80, 80, 80,(dx-x)*80, (dy-y)*80 );
	}
	
	// -----------------------------------------------------------
	
	void RndPannel() {
		// 裏画面に img を作画
		bg.drawImage( img, 0, 0, this);
		
		int r, x1, y1, x2, y2, tmp;
		
		// 300回ランダムにパネルを入れ替える
		for ( r=0; r<300 ; r++) {
			// ランダムで動かすパネルを決める
			x1 = (int) (6 * Math.random());// ランダム発生
			y1 = (int) (6 * Math.random());// ランダム発生
			x2 = (int) (6 * Math.random());// ランダム発生
			y2 = (int) (6 * Math.random());// ランダム発生
			
			// ランダム１のパネルを、裏画面左下にコピー
			kcopy( x1, y1, 0, 6);
			// ランダム２のパネルをランダム１の場所にコピー
			kcopy( x2, y2, x1, y1);
			// 裏画面左下のパネルをランダム２の場所にコピー
			kcopy( 0, 6, x2, y2);
			
			// 画像を動かすと同時に puzz[] の数字も入替える
			tmp = puzz[ y1*6+x1 ];
			puzz[ y1*6+x1 ] = puzz[ y2*6+x2 ];
			puzz[ y2*6+x2 ] = tmp;
			
		} // for
	
	} // RndPannel()
	// -----------------------------------------------------------

// ===============================================================
}  // End of Class

// このプログラムの簡単なメイキングを爆裂健ＨＰUの「ＪＡＶＡ講座」で
// やっています。興味のある方は見に来てください m(__)m
// http://www.vector.co.jp/authors/VA006860/
// 爆裂健ホームページU（ＪＡＶＡ系）

