C言語でグラフィックス | ||
【4】グラフィックスを動かす |
◆サンプルプログラム 〔mvball22.c〕
ボールが壁で跳ね返った後、角度を変えて移動する。移動量は15ピクセルとし、角度は10, 20, 30, 40, 50, 60度の6種類とし、乱数で角度を決定する。
#include <GrWin.h> #include <stdlib.h> #include <time.h> #include <math.h> int xrand(int, int); /* 特定範囲の乱数発生関数 */ int main(void) { int width = 640, height = 400; float xx, dx, yy, dy, rr = 20.0; float mov = 15.0, kaku, dd; GWopen(0); GWsize(-5, &width, &height); GWsize(-3, NULL, NULL); GWvport(0.0, 0.0, (float)width / (float)height, 1.0); GWindow(0.0, 0.0, (float)width - 1.0, (float)height - 1.0); /* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */ GWclear(-1); srand(time(NULL)); dx = mov * cos(45.0 * M_PI / 180.0); /* 移動量初期値 */ dy = mov * sin(45.0 * M_PI / 180.0); xx = (float)width / 2.0; /* ボール位置初期値 */ yy = (float)height / 2.0; while(GWevent(NULL, NULL) == 0){ GWsetpen(0, 1, 1, -1); /* ペン黒色 */ GWellipse(xx, yy, xx + rr, yy + rr); GWsleep(100); /* 時間待ち(100ms) */ GWsetpen(19, 1, 1, -1); /* ペン白色 */ GWellipse(xx, yy, xx + rr, yy + rr); xx = xx + dx; /* 移動量計算 */ yy = yy + dy; if(yy + rr >= height){ /* 上の壁 */ kaku = (float)xrand(1, 6) * 10.0; /* 角度計算 */ dd = mov * sin(kaku * M_PI / 180.0); /* 移動量計算 */ if(dy > 0) dy = -dd; else dy = dd; yy = (float)height - rr; }else if(yy < 0.0){ /* 下の壁 */ kaku = (float)xrand(1, 6) * 10.0; dd = mov * sin(kaku * M_PI / 180.0); if(dy > 0) dy = -dd; else dy = dd; yy = 0.0; } if(xx + rr >= width){ /* 右の壁 */ kaku = (float)xrand(1, 6) * 10.0; dd = mov * cos(kaku * M_PI / 180.0); if(dx > 0) dx = -dd; else dx = dd; xx = (float)width - rr; }else if(xx < 0.0){ /* 左の壁 */ kaku = (float)xrand(1, 6) * 10.0; dd = mov * cos(kaku * M_PI / 180.0); if(dx > 0) dx = -dd; else dx = dd; xx = 0.0; } } /* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */ GWquit(); return 0; } int xrand(int lower, int upper) { return (upper - lower + 1) * (float)rand() / 32768.0 + lower; }
変数が多くなったので、次にまとめておく。
xx, yy | ボールの座標 |
dx, dy | x,y方向の移動量 |
rr | ボールの直径 |
mov | 移動量 |
kaku, dd | 角度格納用とその角度のときの移動量格納用 |
ボールが壁に当たったとき、跳ね返る角度kakuは10から60度まで10度単位で変化させるので次の乱数を使った式で計算している。
kaku = (float)xrand(1, 6) * 10.0;
この角度kakuのときのx方向(左右の壁に当たったとき)またはy方向(上下の壁に当たったとき)の移動量ddを次の式で計算している。
dd = mov * cos(kaku * M_PI / 180.0); … x方向
dd = mov * sin(kaku * M_PI / 180.0); … y方向
◆サンプルプログラム 〔mvball23.c〕
角度や移動量の計算で同じような式が多いのでまとめる。
/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */ GWclear(-1); srand(time(NULL)); dx = mov * cos(45.0 * M_PI / 180.0); /* 移動量初期値 */ dy = mov * sin(45.0 * M_PI / 180.0); xx = (float)width / 2.0; /* ボール位置初期値 */ yy = (float)height / 2.0; while(GWevent(NULL, NULL) == 0){ GWsetpen(0, 1, 1, -1); /* ペン黒色 */ GWellipse(xx, yy, xx + rr, yy + rr); GWsleep(100); /* 時間待ち(100ms) */ GWsetpen(19, 1, 1, -1); /* ペン白色 */ GWellipse(xx, yy, xx + rr, yy + rr); xx = xx + dx; /* 移動量計算 */ yy = yy + dy; kaku = (float)xrand(1, 6) * 10.0; /* 角度計算 */ dd = mov * sin(kaku * M_PI / 180.0); /* 移動量計算 */ if(yy + rr >= height){ /* 上の壁 */ if(dy > 0) dy = -dd; else dy = dd; yy = (float)height - rr; }else if(yy < 0.0){ /* 下の壁 */ if(dy > 0) dy = -dd; else dy = dd; yy = 0.0; } dd = mov * cos(kaku * M_PI / 180.0); /* 移動量計算 */ if(xx + rr >= width){ /* 右の壁 */ if(dx > 0) dx = -dd; else dx = dd; xx = (float)width - rr; }else if(xx < 0.0){ /* 左の壁 */ if(dx > 0) dx = -dd; else dx = dd; xx = 0.0; } } /* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
角度計算と移動量計算の文(式)をifブロックの外に出し、4カ所の角度計算を1つに、角度計算を2つにまとめた。壁に当たらないときも3つの文を処理するので無駄ではあるが、リストは見やすくなる。
Copyright © 2005 Hiroshi Masuda |