投げたボールの軌跡を計算しグラフィックスで表示をするのが目的です。空気抵抗がない場合、ボールの軌跡は放物線(時間に対する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を変化))