/* exercise08.c */ /* 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; int width = 640, height = 640; /* ウィンドウのサイズ */ double gain = 10000.0; double dt = 1.0; Ball.x = 0; Ball.y = 200; Ball.vx = 0.0; Ball.vy = 5.0; Ball.r = 10.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); /* バックバッファを黒で塗り潰す */ /* ウィンドウのサイズが変更されても、ボールがウィンドウ外に出ていかないようにする */ Ball.x = fminl(Ball.x, width - Ball.r); Ball.y = fminl(Ball.y, height - Ball.r); /* ボール加速 */ Ball.Rx = Ball.x-(double)width/2; Ball.Ry = Ball.y-(double)height/2; Ball.R2 = pow (Ball.Rx,2) + pow(Ball.Ry,2); Ball.theta = atan2(Ball.Ry, Ball.Rx); Ball.vx -= gain*1 / Ball.R2 * cos (Ball.theta)*dt; Ball.vy -= gain*1 / Ball.R2 * sin (Ball.theta)*dt; /* ボールを移動 */ Ball.x += Ball.vx*dt; Ball.y += Ball.vy*dt; glColor3d(1.0, 1.0, 1.0); circle(Ball.x, Ball.y, Ball.r); /* ボールを描く */ glfwSwapBuffers(); /* フロントバッファとバックバッファを入れ替える */ usleep(40 * 1000); /* 40ミリ秒くらい時間待ち */ } glfwTerminate(); /* ウィンドウを閉じる */ return 0; }