import java.applet.*;
import java.awt.*;
import java.awt.event.*;


public class BallApplet extends Applet
        implements Runnable,ActionListener,AdjustmentListener,ItemListener

//Appletクラスを継承して、時間的な処理、ボタンのイベント、スクロールバーのイベントを処理するインターフェイスを実装する。



{
    Thread th;                                                                    //Threadクラスの変数thを設定
    BallCanvas bc;                                                            //BallCanvasクラスの変数bcを設定
    

//コンポーネント
    Button button,button1;          
    Scrollbar scrbar,scrbar1;
    Label angleLabel,speedLabel;
    Checkbox ch;
    
    


//プロパティ、メンバ
    double t=0;   
    int dt=100;                                            //時間の刻み幅
    int count=0;           

    double theta=Math.PI/4;                                //初期角度
    double V=60.0;                                            //初期速度
    
    final int thetaMax_min=5;        //最小角度
    final int thetaMax_max=90;                 //最大角度
    final int deltaTheta=5;           //角度の刻み幅

    final int speedmax_min=30;           //最小角度
    final int speedmax_max=100;           //最大角度
    final int deltaspeed=1;                 //速度の刻み幅


    boolean threadFlg =true;                                                                     //スレッドのループに利用するフラグ変数  
    boolean suspendFlg = false;                                                                //スレッドの一時停止と再開に利用するフラグ変数


    


//---------------------------------------------------------初期設定用メソッド--------------------------------------------
//メソッド1
public void init(){        
    this.bc=new BallCanvas(0,0);                            //キャンバスをオブジェクト化 theta=thetaMax
    

//画面の設定を行っていく
    //画面上部のパネルの作成    //コンポーネントをオブジェクト化し、細部を決定していく
    int theta_i=30;
    int speed_i=60;
    this.button=new Button("reset");
    this.button1=new Button("start");
    this.ch=new Checkbox("stopped");
    this.scrbar=new Scrollbar(Scrollbar.HORIZONTAL,
                theta_i,
                this.deltaTheta,
                this.thetaMax_min,
                this.thetaMax_max+this.deltaTheta);    //
    this.angleLabel=new Label(theta_i+"deg",Label.CENTER);
    this.scrbar1=new Scrollbar(Scrollbar.HORIZONTAL,speed_i,this.deltaspeed,this.speedmax_min,this.speedmax_max+this.deltaspeed);
    this.speedLabel=new Label(speed_i+"m/s",Label.CENTER);

    Panel p=new Panel();                                                //1番目のパネルのオブジェクト化
    p.setLayout(new GridLayout(1,5));                        //パネルのレイアウトの設定

    p.add(ch);
    p.add(button1);
    p.add(button);                                                                            //パネルにコンポーネントを追加していく
    p.add(scrbar);
    p.add(angleLabel);

    //画面下部のラベルの作成
    Panel p2=new Panel();                  //2番目のパネルの設定
    p2.setLayout(new GridLayout(1,3));
    p2.add(new Label("Velocity",Label.CENTER));
    p2.add(scrbar1);
    p2.add(speedLabel);
    
    
    //アプレットのレイアウトを設定
    this.setLayout(new BorderLayout());

    this.add(p,BorderLayout.NORTH);                 //上部にオブジェクトp
    this.add(bc,BorderLayout.CENTER);                                            //中部にキャンバスのオブジェクト
    this.add(p2,BorderLayout.SOUTH);                                               //下部にp2

//リスナーに登録
    this.button.addActionListener(this);
    this.button1.addActionListener(this);
    this.scrbar.addAdjustmentListener(this);
    this.ch.addItemListener(this);
    this.scrbar1.addAdjustmentListener(this);
    
    th=new Thread(this);               //スレッドをオブジェクト化


    }

//-------------------------------------実行が始まると呼び出される処理----------------------//

//メソッド2
    

public  void actionPerformed(ActionEvent ev){            //Resetボタンを押したとき、初期条件の変更を含む
    if(ev.getSource()==this.button){
    this.t=0;                          
    this.theta=this.scrbar.getValue()*Math.PI/180.0;
    this.V=this.scrbar1.getValue();}

    if(ev.getSource()==this.button1){            //Startボタンを押したときスレッドをスタートさせる
        if(count==0){th.start();
            count++;}}
}
        


public void run(){
    
    while(threadFlg){
        double a=9.8;                
        double x = this.V*Math.cos(this.theta)*t;        //方程式
        
        double y= this.V*Math.sin(this.theta)*t-0.5*a*t*t;    //方程式
        
        this.bc.setx(x);        //x座標を設定
        this.bc.sety(y);        //y座標を設定
        this.bc.repaint();        //オブジェクトを更新


        t=t+dt/1000.0;            //時間を更新


        try{
            Thread.sleep(dt);                //dt秒間、スレッドを停止
             synchronized(this){
                    while(suspendFlg){wait();}                                //suspendFlg=Trueのときは、スレッドを一時停止
                    }
                        }
        catch(InterruptedException e){}

            }
        }


public void adjustmentValueChanged(AdjustmentEvent ev){        //スクロールバーを動かしたとき
    if(ev.getSource()==this.scrbar){
    this.angleLabel.setText(this.scrbar.getValue()+"deg");      //表示の更新
                    }
    if(ev.getSource()==this.scrbar1){
    this.speedLabel.setText("V="+this.scrbar1.getValue()+"m/s");
        }
    }


public synchronized void itemStateChanged(ItemEvent ev){        //チェックボックスを押したとき一時停止
    Checkbox ch = (Checkbox)ev.getItemSelectable();
      
    if(ch.getState()){
            this.suspendFlg=true;
        }    
 
    else{
        this.suspendFlg = false;      
        notify();}}
    
public void paint (Graphics g){

Dimension size = getSize();                                                    //ダブルバッファリングという技術を使い、画面のちらつきを抑える
  Image back = createImage(size.width, size.height);

  Graphics buffer = back.getGraphics();

 buffer.drawLine(10, 10, 100, 50);
 buffer.drawOval(10, 10, 100, 50);

 g.drawImage(back, 0, 0, this);


        }


public void stop(){

    }
}