================ 問題7.1

================ ● 問題7.1 ================
[ 問題 ]
適当なGUI API ( Java AWT, Perl/Tk, Qt, Aqua ) あるいはUnix APIを用いて、 kbhit() という以下のような関数を作成せよ。
kbhit()
ユーザからの入力があったら、その入力に対応する整数値>0を返す
ユーザからの入力がなかったら、0を直ちに返す
この方式で簡単なシューティングゲームを作り、 GUI APIの推奨する方法で実現する場合と、CPU使用率、応答速度を比較せよ。
file path --> naha:/net/home/student/e06/e065763/OS_rep/exercise/exercise7-1/ShootingDemo1.c
以下のサイトを参考に、シューティングゲームのようなプログラムを作成した。
[ Akamine Lab グラフィックプログラミング基礎 : http://assam.tea.ie.u-ryukyu.ac.jp/internal_2007lab2_graphics.html ]
▼ ShootingDemo1.c のソースコード
---------------------------------------------------------/* kbhit 関数を用いないプログラム */
#include <GLUT/glut.h>
#include <stdio.h>
typedef struct {
double r;
double g;
double b;
} COLOR;
typedef struct {
double posX[3];
double posY[3];
COLOR col;
} PLAYER;
PLAYER player;
// 描画イベントハンドラ
void display(void) {
☆★ 省略 ☆★
}
// player の位置を動かす関数
void movePlayer(double x, double y) {
☆★ 省略 ☆★
}
// 何もしていないときに呼び出される関数
void idle(void) {
glutPostRedisplay();
usleep(10000);
}
// キーボードイベントハンドラ
void keyboard(unsigned char key, int keyX, int keyY) {
int c;
double x, y;
x = y = 0.0;
switch(key) {
case 'a':
// 画面左に移動する
x = -0.02;
break;
case 'd':
// 画面右に移動する
x = 0.02;
break;
case 'w':
// 画面上に移動する
y = 0.02;
break;
case 's':
y = -0.02; // 画面下に移動する
break;
default:
break;
}
movePlayer(x, y);
glutPostRedisplay();
}
// player 構造体の初期化
void init(void) {
☆★ 省略 ☆★
}
int main(int argc, char *argv[]) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA);
glutCreateWindow(argv[0]);
glutIdleFunc(idle);
glutDisplayFunc(display);
glutKeyboardFunc(keyboard);
init();
glutMainLoop();
return 0;
}
---------------------------------------------------------このプログラムは kbhit 関数を使わずにイベント処理で自身の機体を操作するプログラムである。以下のようにコンパイルして実行した。
▼ ShootingDemo1.c のコンパイル・実行のようす
------------------------------------------------------------------------------------------------% gcc -framework OpenGL -framework GLUT -framework Foundation ShootingDemo1.c -o ShootingDemo1 \
-I/usr/X11R6/include -L/usr/X11R6/lib -lGLU -lGL -lXmu -lXext -lX11 -lm
% ./ShootingDemo1
------------------------------------------------------------------------------------------------この時、top コマンドでプログラムがどのくらい CPU を消費しているかを確認した。
----------------------------------------------------------------------------PID COMMAND
%CPU
TIME
#TH #PRTS #MREGS RPRVT RSHRD RSIZE VSIZE
12783 ShootingDe 36.1% 0:01.05
2
71
213 1.96M 17.0M+ 6.64M
143M+
12763 top
12.0% 0:12.96
1
19
22
672K
400K 1.07M 27.0M
----------------------------------------------------------------------------PID COMMAND
%CPU
TIME
#TH #PRTS #MREGS RPRVT RSHRD RSIZE VSIZE
12783 ShootingDe 42.3% 0:11.05
2
95
236 2.79M 18.2M 8.33M
146M
12763 top
12.7% 0:23.24
1
19
22
672K
400K 1.07M 27.0M
----------------------------------------------------------------------------上が ShootingDemo1 を実行直後の top コマンドのようすで、下はキーボードからの入力で自身の機体を操作しているときの top コマンドの
ようすです。CPU の使用率が少し上昇していることが確認できる。
▼ ShootingDemo2.c のソースコード
----------------------------------------------------------/* kbhit 関数を用いるプログラム */
#include <GLUT/glut.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/select.h>
☆★ 省略 ☆★
//描画イベントハンドラ
void display(void) {
☆★ 省略 ☆★
}
void movePlayer(double x, double y) {
☆★ 省略 ☆★
}
int kbhit(int fd) {
char c;
fd_set readers, readfds;
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = 0;
FD_ZERO(&readers);
FD_SET(fd, &readers);
readfds = readers;
if(select(1, &readfds, NULL, NULL, &timeout) <= 0) {
return 0;
}
if(! FD_ISSET(0, &readers)) {
return 0;
}
read(fd, &c, 1);
return (int)c;
}
void idle(void) {
int key;
double x, y;
x = y = 0.0;
for(;;) {
key = kbhit(STDIN_FILENO);
switch(key) {
case 'a':
x = -0.02;
break;
case 'd':
x = 0.02;
break;
case 'w':
y = 0.02;
break;
case 's':
y = -0.02;
break;
default:
break;
}
movePlayer(x, y);
}
}
void init(void) {
☆★ 省略 ☆★
}
int main(int argc, char *argv[]) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA);
glutCreateWindow(argv[0]);
glutIdleFunc(idle);
glutDisplayFunc(display);
init();
glutMainLoop();
return 0;
}
----------------------------------------------------------このプログラムの実行中の top コマンドは、以下のようになった。
----------------------------------------------------------------------------PID COMMAND
%CPU
TIME
#TH #PRTS #MREGS RPRVT RSHRD RSIZE VSIZE
12746 ShootingDe 77.7% 0:01.83
2
70
196 1.90M 8.27M 6.43M
134M
12742 top
9.8% 0:41.97
1
19
22
672K
400K 1.08M 27.0M
----------------------------------------------------------------------------PID COMMAND
%CPU
TIME
#TH #PRTS #MREGS RPRVT RSHRD RSIZE VSIZE
12746 ShootingDe 85.3% 0:34.17
2
70
196 1.90M 8.34M 6.42M
134M
12742 top
10.5% 3:48.80
1
19
22
672K
400K 1.08M 27.0M
----------------------------------------------------------------------------上は ShootingDemo2 実行直後で、下が ShootingDemo2 を実行して少し時間が経ったときの top コマンドの実行結果である。kbhit 関数が常
に呼び出されているので、CPU 使用率がかなり高い状態になっている。ShootingDemo1 はキーボードからの入力があるとイベントが発生し、
事前に登録された関数を呼び出して処理を行うので ShootingDemo2 に比べると CPU を使用する時間は少なくて済む。この二つのプログラム
は、キーボードからの入力で自身の機体を操作するだけだが、これに敵機体と弾丸を撃つ機能、弾丸の当たり判定を行う機能を実装したら簡
単なシューティングゲームのようなものができるだろう。