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 

 

 

inserted by FC2 system