物体の投げ上げのシミュレーションを行うアプリケーションを作成する。
作成する際のフローチャートを図1に示す。
ウィンドウ上でクリックされたら
実行
初速度v0、投げ上げ角kakuの読み込み
ウィンドウの作成
v0、kakuをもとに投げ上げのシミュレーション
ウィンドウのクリア
右クリックした座標へ向け投げ上げのシミュレーション
左クリック
右クリック
中クリック
Exitのサブウィンドウが押されるまで条件分岐を繰り返し、押されたら終了
図1 フローチャート
作成したプログラムを下記に示し、その説明を行間に示す。
#include <stdio.h>
#include <math.h> /* 数学関数を使う */
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#define BORDER 2 /* 境界線の幅の宣言、2とする */
#define WIDTH 500 /* 横幅の宣言、500とする */
#define HIGHT 500 /* 縦幅の宣言、500とする */
main(int argc, char **argv)
{
int screen,j=0,k,x,y,flag=0,xx,yy; /* 各変数の宣言 */
float v0,kaku,g=-9.8,pi=3.14,h,i,highest=0,sub[256]; /* 各変数の宣言 */
char moji[256],hyouji[256],ji1[256],ji2[256],ji3[256],po[256]; /* 日本語メッセージが入る場所 */
printf("初速度と投げ上げ角をスペースで分けて入力してください:");
scanf("%f",&v0); /* 初速度の読み込み */
scanf("%f",&kaku); /* 投げ上げ角の読み込み */
printf("初速度=%4.1f[m/s] 投げ上げ角=%4.1f° \n",v0,kaku); /* 初速度、投げ上げ角の表示 */
Display *dpy;
Window w,quit;
Window root;
unsigned long black, white;
GC gc;
XEvent e; /* イベント構造体の定義 */
XFontSet fs; /* XFontsetで日本語フォントを選ぶ */
char **miss,*def;
int n_miss; /* 変数として宣言しておく */
Colormap cmap; /* カラーマップ構造体 */
XColor c0,c1; /* カラー構造体 */
dpy = XOpenDisplay(""); /* ディスプレイサーバと接続し、その情報をDisplay構造体にいれる */
fs=XCreateFontSet(dpy,"-*-*-medium-r-normal-*-16-*",&miss,&n_miss,&def);
/* fsにフォントセットの番号を入れる */
root = DefaultRootWindow (dpy);
screen = DefaultScreen (dpy);
white = WhitePixel (dpy, screen);
black = BlackPixel (dpy, screen);
cmap = DefaultColormap(dpy,0); /* カラーマップを得る */
XAllocNamedColor(dpy,cmap,"green",&c1,&c0); /* c1.pixel */
w = XCreateSimpleWindow(dpy,root,100,100,WIDTH,HIGHT,BORDER,black,white);
/* サブウインドウを作る */
quit = XCreateSimpleWindow(dpy, w, 10, 3, 30, 12, BORDER, black, white);
gc = XCreateGC(dpy, w, 0, NULL);
XSelectInput(dpy, w, ButtonPressMask); /* イベントマスクを指定する */
XSelectInput(dpy, quit, ButtonPressMask); /* サブウインドウ用 */
XMapWindow(dpy, w);
XMapSubwindows(dpy, w); /* サブウインドウも表示 */
XSetForeground(dpy,gc,black); /* blackにする */
while(1){ /* 無限に繰り返す */
if(XEventsQueued(dpy,QueuedAfterReading))
{
XNextEvent(dpy, &e); /* イベントがあったら */
switch(e.type){ /* イベントに応じた処理に分岐 */
case ButtonPress : /* マウスボタンが押された */
if(e.xbutton.button==3){ /* 右クリックが押されたら */
xx=e.xbutton.x; /* xxにx座標を代入 */
yy=e.xbutton.y; /* yyにy座標を代入 */
sprintf(po,"Point"); /* 画面に出す文字列を変数の中に入れる */
XDrawString(dpy,w,gc,xx,yy,po,strlen(po));
/* 上で入れた文字列を表示する */ /* 右クリックした座標に上で入れた文字列を表示する */
i=0;
while(i<8){
h=398.0-(((xx-50)*i*sin((tan(400-yy/xx-50)*pi)/180.0))+((1.0/2.0)*g*i*i))*25;
/* 物体の高さの位置計算 */
/* y=v0×t×sinθ- (1/2)×g×t×tを使用 */
/* y軸は上下が逆なので、投げ上げ台の位置(398)から上記の式を引いている */
/* 初速度は投げ上げ台から右クリックした際のx座標の距離としている */
/* 投げ上げ角度はtan(投げ上げ台から右クリックした際のy座標の距離 / 投げ上げ台から右クリックした際のx座標の距離としている */
/* 実際に実行すると、放物線が極端に低くなってしまったので、最後にhを25倍している */
XFillArc(dpy,w,gc,49+((xx-50)*cos((tan(400-yy/xx-50)*pi)/180)*i),h,6,6,0*64,360*64);
/* 物体を円を用いて描いている */
/* x=v0×cosθ×tを使用 */
/* x座標での変化は、上記の式を使用し投げ上げ台の位置(49)から足している */
/* y座標は上記で求めたhを使用 */
/* 円の大きさを指定、直径6の円 */
/* 円を描くので0*64,360*64として、0°から360°円を描いている */
i=i+0.1; /* iはtに相当 */
sub[j]=h; /* この配列に投げ上げした際の高さを格納していく */
j++;
if(j>1000)j=0;
if(h>500){ /* 高さが500以上になったら、つまりウィンドウの縦の幅を500としているの
でウィンドウ上から消えたら */
highest=sub[0]; /* 高さ配列の一番目を変数highestに格納 */
for(k=1;k<j;k++){
if(highest>sub[k])highest=sub[k];
/* 高さ配列を1つずつ調べていき、変数highestよりも大きければ値を格納しなおす */
/* つまり、投げ上げした物体の最高点を求めている */
}
if(flag==0){
sprintf(hyouji,"Highest Point = %4.1f ",398.0-highest);
/*画面に出す文字列を変数の中に入れる */
XDrawString(dpy,w,gc,180,highest-15,hyouji,strlen(hyouji));
/* 投げ上げした物体の軌道の上に最高点の高さを表示 */
flag=1;
}
}
usleep(50000); /* マイクロ数秒時間を待つ */
XFlush(dpy); /* 強制的に描画する命令 */
}
}
if(e.xany.window==quit)return; /* exitのサブウィンドウが押されたらウィンドウを閉じる */
if(e.xbutton.button==2)XClearWindow(dpy,w);
/* 中クリックが押されたら */ /* ウィンドウのクリア */
if(e.xbutton.button=...