//
/* ----------------------------------------------------------------------------------------------
tracking.java CD のトラッキング制御 ver. 2.00 (JDK 1.02)
ueyama@infonet.co.jp 2001.05.03
update: 2007.08.22
---------------------------------------------------------------------------------------------- */
import java.applet.Applet;
import java.awt.*;
import java.util.*;
public class tracking extends Applet implements Runnable
{
int Px=33, Lx=94; // ピットとレーザービームの X 座標値
int Py[][]=new int[3][4]; // ピットの Y 座標値
int Pl[][]=new int[3][4]; // ピットの長さ
int Ps[]={0,40,56,72,88,104}; // ピットの長さ(ピクセル)
int Gl[]={40,39,38,37,36,35,33,31,29,27,25,23}; // グラフの長さ
int Wait=32; // 表示変更待機時間 (msec)
int N=0,D=1;
int Mf=-1;
boolean F0=false, F1=false;
boolean Run=false;
Image Img;
Image Buf;
int Bgc;
Random Rnd=new Random();
Graphics bf;
Thread th;
public void init()
{
int i,j,k,l;
String bg=getParameter("bgcolor");
Bgc=Integer.valueOf(bg,16).intValue(); // html 背景色
setBackground(new Color(221,221,221)); // CD 鏡面色
Buf=createImage(250,380);
MediaTracker mt=new MediaTracker(this);
Img=getImage(getCodeBase(), getParameter("figure"));
mt.addImage(Img, 0);
try
{
mt.waitForID(0);
}
catch(InterruptedException e){};
for(i=0;i<3;i++) // ピットの位置と長さの設定
{
for(j=0;j<4;j++) Pl[i][j]=Math.abs(Rnd.nextInt())%4+1;
Py[i][0]=Rnd.nextInt()%40;
for(j=1;j<4;j++) Py[i][j]=Py[i][j-1]+Ps[Pl[i][j-1]]+Ps[Math.abs(Rnd.nextInt())%4+1];
}
}
public void start()
{
th=new Thread(this);
th.start();
}
public void stop()
{
if(th!=null)
{
th.stop();
th=null;
}
}
public void update(Graphics g)
{
paint(g);
}
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_p(int x, int y, int l) // ピットの表示
{
int i;
dsp_g(x,y,0,0,3); // ピットの上部を描く
for(i=0;i>, <<, |>, □)
case 3: w= 25; h= 12; ox= 0; oy= 0; break; // ピット上部
case 4: w= 25; h= 16; ox= 0; oy= 12; break; // ピット中央
case 5: w= 25; h= 12; ox= 0; oy= 28; break; // ピット下部
case 6: w= 13; h= 13; ox= 66; oy= 92; break; // 矢印
}
Graphics gx=bf.create();
gx.clipRect(x,y,w,h);
gx.drawImage(Img,x-(ox+w*m),y-(oy+h*n),this);
gx.dispose();
}
public int btn(int n) // ボタンの表示条件
{
int m=0; // 通常は白いボタン
if((n==0 && Mf==0) || (n==2 && Mf==2)) m=1; // クリックされているときは緑のボタン
if((n==0 && Wait==512) || (n==2 && Wait==8)) m=2; // 早すぎ、遅すぎは灰色に
return m;
}
public void paint(Graphics g)
{
int i,j,l;
bf=Buf.getGraphics();
bf.clearRect(0,0,250,350);
for(i=0;i<3;i++) for(j=0;j<4;j++) dsp_p(Px+i*80,Py[i][j],Pl[i][j]); // ピットの表示
dsp_g(Lx,119,0,0,0); // レーザビーム(主)の表示
dsp_g(Lx+45,18,0,0,1); dsp_g(Lx-23,241,0,0,1); // レーザビーム(副)の表示
bf.setColor(new Color(Bgc));
bf.fillRect(0,300,250,80);
dsp_g( 82,357, btn(0),1,2); // << ボタンの表示
dsp_g(112,357, (Mf==1)?1:0,(Run)?3:2,2); // |> & □ ボタンの表示
dsp_g(142,357, btn(2),0,2); // >> ボタンの表示
bf.setColor(new Color(255,156,156)); // グラフの表示色
l=(F0)? Gl[get_dup(-1)]:40; // 左のグラフの長さを求める
bf.fillRect(80,310+(40-l),20,l); // グラフの表示
if(l<40) dsp_g(107,307, (N%20)/10*2,0,6); // グラフが短いときは矢印をウインクさせる
l=(F1)? Gl[get_dup(1)]:40; // 右側のグラフも同様に
bf.fillRect(150,310+(40-l),20,l);
if(l<40) dsp_g(130,307, (N%20)/10*2+1,0,6);
g.drawImage(Buf,0,0,this); // バッファの表示
bf.dispose();
}
public void run()
{
int i,j,y0,y1,y2,x0,x1;
while(true)
{
repaint();
try
{
Thread.sleep((Run)?Wait:128);
}
catch (InterruptedException e){};
if(Run)
{
for(i=0;i<3;i++)
{
for(j=0;j<4;j++) Py[i][j]--; // ピットを上方に移動
if(Py[i][0]+Ps[Pl[i][0]]==0) // 画面から消えた
{
for(j=0;j<3;j++) Py[i][j]=Py[i][j+1]; // 新規ピットデータの作成
for(j=0;j<3;j++) Pl[i][j]=Pl[i][j+1];
Py[i][j]=Py[i][j-1]+Ps[Pl[i][j-1]]+Ps[Math.abs(Rnd.nextInt())%4+1];
Pl[i][j]=Math.abs(Rnd.nextInt())%4+1;
}
}
F0=false; F1=false;
for(i=0;i<4;i++) // レーザーとピットの接触検出
{
x1=Px+80+13; y1=Py[1][i]+13; y2=y1+Pl[1][i]*16; // ピットの中心座標
if(x1-Lx>32) {x0=Lx+45+21; y0= 18+21;} // レーザ副ビームの中心座標
else {x0=Lx-23+21; y0=241+21;}
if(inside(y0,y1,y2) && x0-x1<33) // ピット直線部の接触
{
if(i<2) F1=true;
if(i>0) F0=true;
}
else // ピットの両端での接触
{
if(y10) F0=true;
}
}
}
N++;
if(N%100==0)
{
if((Lx-Px)!=61) Lx+=D; // レーザーをピットの方向に移動
else if(Px!=33) // ピットとレーザーを中央に戻す
{
i=33-Px; i/=Math.abs(i);
Lx+=i; Px+=i;
}
}
}
}
}
public int get_dup(int m) // レーザーとピットの重なり幅
{
int d=0;
d=(m>0)? (Px+80+25)-(Lx+45): (Lx-23+41)-(Px+80);
if(d>11) d=11; // 11 は配列 Gl[] の要素数
return (d<0)?0:d;
}
public boolean mouseDown(Event e, int x, int y) // マウスがクリックされたときの処理
{
int m=(x-125)/63, g=get_dup(m);
if(y<300)
{
if(g<11) Px+=m; // CD 部両端をクリック
if(m==0) {Px=33; Lx=94;} // CD 部中央をクリック
else D=m;
}
if(inside(x, 82,168) && y>357) // ボタンをクリック
{
Mf=(x-82)/30; // Mf: 0=<<, 1=|>, 2=>>
if(inside(x, 82,108) && Wait<512) Wait*=2; // << ボタンをクリック
if(inside(x,142,168) && Wait> 8) Wait/=2; // >> ボタンをクリック
}
return true;
}
public boolean mouseUp(Event e, int x, int y) // クリックを止めたときの処理
{
if(Mf==1) Run=!Run;
if(inside(x, 82,168) && y>357) Mf=-1;
return true;
}
}
// 戻る