import java.awt.*;

import java.awt.event.*;

import javax.swing.*;

 

public class Rei52Sim extends JApplet implements Runnable, ActionListener{

       private volatile Thread th=null;

       Sim sm;                                    // シミュレーションのためのクラスSimのオブジェクトを参照する変数sm

      

       class Rei52Panel extends JPanel{

              public void paintComponent(Graphics g){

                     super.paintComponent(g);

                     Font f=new Font((g.getFont()).getName(), Font.BOLD,40);

                     g.setFont(f);

                    

                     int x = (int)sm.x;        // シミュレーションオブジェクトsmの変数xの値を使って★を描画する

                     g.drawString("",200+x,150);

              }

       }

      

       public void init(){

              setSize(300,250);

              Container c=getContentPane();

              c.add(new Rei52Panel(), "Center");

              JButton bt1 = new JButton("開始/停止");

              c.add(bt1,"North");

              bt1.addActionListener(this);

              sm = new Sim(100.0 , 0.0 , -20.0);         // シミュレーションのためのオブジェクトsmを作成する(初期値は位置x=100, 速度vx=0, バネ定数=-20)

       }

      

       public void actionPerformed(ActionEvent e){

              if(th==null){

                     th=new Thread(this);

                     th.start();

              }

              else

                     th=null;

       }

      

       public void run(){

              Thread thisThread = Thread.currentThread();

              while(th==thisThread){           // シミュレーションで繰り返しているのはこのwhile

                     repaint();                           // 毎回再描画する

                     try{

                            th.sleep(10);

                     }

                     catch(InterruptedException e){}

                     sm.one_step(0.01);            // シミュレーションオブジェクトsmone_stepメソッドによりxvxの値を0.01秒後の値にする(引数はΔt

              }

       }

}

 

 

 

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//

//  以下はシミュレーションのためのクラス(Simクラス)です

//

class Sim{

       public double x;          // 現在の位置xを保存する変数(外部から参照するためpublicとしている)

       private double vx, k;  // 現在の速度vxと、バネ定数k(外部から参照されないためprivateとしている)

      

       public Sim(double x0 , double vx0 , double k0){        // コンストラクタ(3個の引数で、位置x、速度vx、バネ定数kを初期化する)

              x=x0;

              vx=vx0;

              k=k0;

       }

      

       public void one_step(double dt){     // オイラー法の計算(引数で得たdt秒だけ時間を進める。つまりxvxの値を更新する)

              double x1, vx1;

              x1=dt*dx_per_dt();                   // x1dt秒間でのxの変化量

              vx1=dt*dvx_per_dt();               // vx1dt秒間でのvxの変化量

              x=x+x1;

              vx=vx+vx1;

       }

      

       private double dx_per_dt(){            // 運動方程式 dx/dt

              return vx;

       }

      

       private double dvx_per_dt(){          // 運動方程式 dvx/dt

              return k*x;

       }

}