投げたボールの軌跡を計算しグラフィックスで表示をするのが目的です。空気抵抗がない場合、ボールの軌跡は放物線(時間に対する2次式)になります(これが「放物線」の名前の意味です)。ここでは、空気抵抗を考慮したボールに軌跡の表示を試みます。
dx=vx * dt ;速度の定義物体に力を加えると、速度が変化します。時間当たりの速度の変化率を加速度といいます。加速度と力の間には次の関係があります。
質量 * 加速度 = 力 :ニュートンの法則これが、力と質量、加速度の間の関係式になります。質量 m の物体に力Fを加えると、加速度aは次のようになります。
dy = vy * dt, dx = vx * dtとなります。
vx0 = v*cos(ang)、vy0 = v*sin(ang)となります。cos(ang)、sin(ang)は三角関数で、vのx成分とy成分を計算します。
vy(t)=vy0 - g * dtとなります。vy0/g 秒後にはy方向の速度は0になり、以後落下をはじめます。
t=vy0/g=v・sin(ang)/gとなります。
vx0=ve*(float)cos((3.14/180.0)*ang);
vy0=ve*(float)sin((3.14/180.0)*ang);
となります。ここで、(3.14/180.0)*ang で角度をラジアン単位に直しています(180度がπラジアンです)。x = x + vx * dt;//位置変化 y = y + vy * dt; vy = vy - g * dt;//速度変化ここで、dtは十分短くする必要があります。ここでの、計算は「dtの間はvx,vyは変化しない」、ことを前提としています。dtを大きくすると、この条件が成立しなくなるからです、
{
// 軌跡の計算
float ve,ang,vx0,vy0;
float g,dt,t1,t,x,y,vx,vy;
//速度設定、角度読み込み、初速度計算
ve=30.0;
vx0=ve*(float)cos((3.14/180.0)*ang);
vy0=ve*(float)sin((3.14/180.0)*ang);
//重力加速度、刻み時間、落下時刻
g=9.8f;
dt=0.01f;
//初期設定
x=0;y=0;
vx=vx0;vy=vy0;
for( t=0.0;y>=0;t=t+dt){
x = x + vx * dt;//位置変化
y = y + vy * dt;
vy = vy - g * dt;//速度変化
}
}
-k*v*v空気抵抗があると、vx,vyとも変化します。v は 速度成分 vx,vy から、三平方の定理で合成します。合成した加速度 v から 各加速度の成分を求めるには k*v*v*cos A を計算する必要がありますが、v*cos A = vx ですから、加速度の x 成分は k*v*vx で計算できます。
v=sqrt(vx*vx+vy*vy);
vx=vx - k*v*vx*dt
vy=vy - g *dt - k*v*vy*dt
となります。// 軌跡の計算
int ve,ang;
float vx0,vy0;
float g,dt,t1,t,x,y,vx,vy;
float k;
//速度設定、角度読み込み、初速度計算
void setup(){
ve=60;
ang=45;
init(ve,ang);
g=9.8f;
dt=0.1f;
k=0.0;
size(500,200);
}
void draw(){
float v;
v=sqrt(vx*vx+vy*vy);
x = x + vx * dt;//位置変化
y = y + vy * dt;
vy = vy - g * dt-k * v * vy * dt;//速度変化
vx=vx - k * v * vx * dt;
ellipse(x,height-y,5,5);
if(y<10) noLoop();
fill(150,150,150);
rect(0,height-10,width,height);
fill(250,250,250);
text("v="+ve+" a="+ang+" k="+k,10,height);
}
void init(int ve,int ang){
vx0=ve*(float)cos((3.14/180.0)*ang);
vy0=ve*(float)sin((3.14/180.0)*ang);
//初期設定
x=10;
y=10;
vx=vx0;
vy=vy0;
}
void keyPressed(){
if(key=='v') ve=ve+3;
if(key=='V') if(ve>40) ve=ve-3;
if(key=='a') ang=ang+3;
if(key=='A') if(ang>0) ang=ang-3;
if(key=='k') k=k+0.0001;
if(key=='K') if(k>0.0001) k=k-0.0001;
if(key=='c') background(200);
init(ve,ang);
loop();
}
実行画面(v=60,a=39,kを変化))