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 

 

 

inserted by FC2 system