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); // シミュレーションオブジェクトsmのone_stepメソッドによりxとvxの値を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秒だけ時間を進める。つまりxとvxの値を更新する)
double
x1, vx1;
x1=dt*dx_per_dt(); // x1はdt秒間でのxの変化量
vx1=dt*dvx_per_dt(); // vx1はdt秒間での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;
}
}