C言語でグラフィックス | ||
【4】グラフィックスを動かす |
(2)ボールの跳ね返り
◆サンプルプログラム 〔mvball21.c〕
ボールをGWウィンドウの中央から右上方向に移動させる。ボールが壁(GWウィンドウの枠(フレーム))に当たったとき、跳ね返るようにする。
●ボールの移動方向と移動量
ボールの移動量をdx, dyとするとき、移動方向と移動量の関係は左図の通りである。GWウィンドウは原点(0,0)が左下である。
例えば、ボールが右上(B)の方向に移動していて、上の壁に当たったとき、右下(D)の方向に跳ね返る。このとき、移動量dyが正から負に変わる。
次に、移動方向と跳ね返りの関係をまとめておく。
移動方向 | 移動量 | 当たる壁 | 跳ね返り | 移動量 | 変化 |
Aの方向 | -dx, +dy | 上の壁 | Cの方向 | -dx, -dy | dy |
左の壁 | Bの方向 | +dx, +dy | dx | ||
Bの方向 | +dx, +dy | 上の壁 | Dの方向 | +dx, -dy | dy |
右の壁 | Aの方向 | -dx, +dy | dx | ||
Cの方向 | -dx, -dy | 下の壁 | Aの方向 | -dx, +dy | dy |
左の壁 | Dの方向 | +dx, -dy | dx | ||
Dの方向 | +dx, -dy | 下の壁 | Bの方向 | +dx, +dy | dy |
右の壁 | Cの方向 | -dx, -dy | dx |
上の壁または下の壁に当たったとき、移動量(dy)が正から負または負から正に変化する。また、左の壁または右の壁に当たったとき、移動量(dx)の正負が変化する。
移動量を正から負または負から正に変化させるには、移動量に-1を乗じる(かけ算する)。
●壁に当たる判定
ボールの座標と壁の座標を比較して、壁に当たったかどうかを判定する。壁に当たったときは移動量を変化させて跳ね返るようにする。
ボールは右図のように、座標(x, y)を基準に+x方向に20(=rr)、+y方向に20(=rr)の大きさで描画している。また、GWウィンドウの大きさは幅が640ピクセル(=width)、高さが400ピクセル(=height)に設定している。
次に、ボールと壁のあたり判定についてまとめておく。
左の壁(X座標=0) | if(x < 0) あたりの処理; |
下の壁(Y座標=0) | if(y < 0) あたりの処理; |
右の壁(X座標=width) | if(x+rr >= width) あたりの処理; |
上の壁(Y座標=height) | if(y+rr >= height) あたりの処理; |
#include <GrWin.h> int main(void) { int width = 640, height = 400; float xx, dx, yy, dy, rr = 20.0; 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); dx = 15.0; /* 移動量 */ dy = 15.0; xx = (float)width / 2.0; yy = (float)height / 2.0; while(GWevent(NULL, NULL) == 0){ /* ※1 */ 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){ /* 上の壁 */ dy = -dy; yy = (float)height - rr; }else if(yy < 0.0){ /* 下の壁 */ dy = -dy; yy = 0.0; } if(xx + rr >= width){ /* 右の壁 */ dx = -dx; xx = (float)width - rr; }else if(xx < 0.0){ /* 左の壁 */ dx = -dx; xx = 0.0; } } /* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */ GWquit(); return 0; }
※1 プログラムはGWevent関数によって、マウスのクリックまたはキーを押すと終了する。
while(GWevent(NULL, NULL) == 0)
今回、座標は必要ないのでGWevent関数の引数はNULLとしている。
Copyright © 2005 Hiroshi Masuda |