/* exercise08.c : 教科書 2-19 参照 */ /* compile: cc -o exercise08 exercise08.c -g -O2 -Wall -lglfw -lGLU -lGL -lX11 -lXrandr -lm */ #include #include #include #include typedef struct Ball{ long double x, y; /* ボールの中心位置 */ long double vx, vy; /* ボールの移動速度 */ long double r; /* ボールの半径 */ long double Rx, Ry, R2; /* ボールの半径 */ long double theta; /* ボールの半径 */ }ball; /* 円を描画する */ void circle(double x, double y, double r) { int const N = 24; /* 円周を 24分割して線分で描画することにする */ int i; glBegin(GL_LINE_LOOP); for (i = 0; i < N; i++) glVertex2d(x + cos(2 * M_PI * i / N) * r, y + sin(2 * M_PI * i / N) * r); glEnd(); } int main(void) { ball Ball[5]; int i; double restitution = 0.99; /* はねかえり係数 */ int width = 640, height = 400; /* ウィンドウのサイズ */ double gain = 10000.0; double dt = 1.0; Ball[0].x = 200; Ball[0].y = 200; Ball[0].vx = 5.0; Ball[0].vy = 10.0; Ball[0].r = 10.0; Ball[1].x = 200; Ball[1].y = 200; Ball[1].vx = 4.0; Ball[1].vy = 10.0; Ball[1].r = 11.0; Ball[2].x = 200; Ball[2].y = 200; Ball[2].vx = 3.0; Ball[2].vy = 10.0; Ball[2].r = 12.0; Ball[3].x = 200; Ball[3].y = 200; Ball[3].vx = 2.0; Ball[3].vy = 10.0; Ball[3].r = 13.0; Ball[4].x = 200; Ball[4].y = 200; Ball[4].vx = 1.0; Ball[4].vy = 10.0; Ball[4].r = 14.0; /* グラフィック環境を初期化して、ウィンドウを開く */ glfwInit(); glfwOpenWindow(width, height, 0, 0, 0, 0, 0, 0, GLFW_WINDOW); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); /* 投影以外の座標変換は行わない */ for (;;) { /* Esc が押されるかウィンドウが閉じられたらおしまい */ if (glfwGetKey(GLFW_KEY_ESC) || !glfwGetWindowParam(GLFW_OPENED)) break; glfwGetWindowSize(&width, &height); /* 現在のウィンドウサイズを取得する */ glViewport(0, 0, width, height); /* ウィンドウ全面をビューポートにする */ glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, width, 0, height, -1.0, 1.0); /* この範囲の空間をビューポートに投影する */ glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT); /* バックバッファを黒で塗り潰す */ for(i=0; i<5; i++){ /* ウィンドウのサイズが変更されても、ボールがウィンドウ外に出ていかないようにする */ Ball[i].x = fminl(Ball[i].x, width - Ball[i].r); Ball[i].y = fminl(Ball[i].y, height - Ball[i].r); /* ボール加速 */ Ball[i].Rx = Ball[i].x-(double)width/2; Ball[i].Ry = Ball[i].y-(double)height/2; Ball[i].R2 = pow (Ball[i].Rx,2) + pow(Ball[i].Ry,2); Ball[i].theta = atan2(Ball[i].Ry, Ball[i].Rx); Ball[i].vx -= gain*1 / Ball[i].R2 * cos (Ball[i].theta)*dt; Ball[i].vy -= gain*1 / Ball[i].R2 * sin (Ball[i].theta)*dt; /* ボールを移動 */ Ball[i].x += Ball[i].vx*dt; Ball[i].y += Ball[i].vy*dt; /* ウィンドウの上下左右の端にぶつかったらバウンド */ /* if (Ball[i].x <= Ball[i].r || Ball[i].x >= width - Ball[i].r) Ball[i].vx = -restitution*Ball[i].vx; if (Ball[i].y <= Ball[i].r || Ball[i].y >= height - Ball[i].r) Ball[i].vy = -restitution*Ball[i].vy; */ glColor3d(1.0, 1.0, 1.0); circle(Ball[i].x, Ball[i].y, Ball[i].r); /* ボールを描く */ } glfwSwapBuffers(); /* フロントバッファとバックバッファを入れ替える */ usleep(40 * 1000); /* 40ミリ秒くらい時間待ち */ } glfwTerminate(); /* ウィンドウを閉じる */ return 0; }