C言語ゲームプログラミング  ブロック崩し編 第2回




2014年10月より個人の方を対象に、Study C無料提供を開始しました。
C言語を勉強中の方は、学習・教育に最適なC言語インタープリタのStudy Cを使ってみてください(個人の方は無料です)。
大学・高専・高校などの教育機関での採用実績も多数あるロングセラー商品Study Cが、個人向けに無料提供を始めました。
インタープリタの手軽さに加え、ゲームや3Dタートルグラフィックで楽しく勉強したりと、C言語の学習を協力にサポートします。
ブロック崩しゲーム 3Dツリー クリスマスツリー
また、このようなボタンの用意されているページでは、掲載しているプログラムをStudy Cに直接ロードし実行したりすることができます。
Study Cにロードする Study Cにロードし編集する Study Cにロードし実行する
Study C無料利用についての詳細は、このページを参照してください。



1.壁で反射するボールとラケット


ボールが壁にぶつかって反射するプログラムの第6回講座ブロック崩し編 第1回のラケット移動プログラムを合成させます。 ただ第6回講座のボール描画/消去は手抜きをしているので、ラケットと同じような描画/消去に修正します。

#include <graph.h>

main()
{
	HBITMAP	hbmp_ball;
	//ボール用の変数
	int	b_xx = 0, bd_xx = 10,
		b_yy = 0, bd_yy = 10;
	int	bold_xx = -1, bold_yy = -1;

	//ラケット用の変数
	int	r_xx = 320, rold_xx = -1;
	unsigned long
		tick;

	hbmp_ball = gl_loadbitmap("ball.bmp");
	if(hbmp_ball == NULL){
		printf("ビットマップファイルが見つかりません.\n");
		exit(0);
	}
	gl_openwin(-1, -1, 640, 480, 0);

	tick = GetTickCount();
	for( ; ; ){
		if(GetTickCount() >= tick && GetTickCount() < tick + 50)
			continue;
		tick = GetTickCount();

		//ESCキーを押したらプログラムが終了する処理も追加
		if(gl_getkeystate(VK_ESCAPE) < 0)
			break;

		//カーソル左右キーでラケットの位置(r_xx)を変化させます
		//カーソル左キーが押されているときの処理
		if(gl_getkeystate(VK_LEFT) < 0){
			r_xx = r_xx - 20;
			if(r_xx < 0){
				r_xx = 0;
			}
		}
		//カーソル右キーが押されているときの処理
		if(gl_getkeystate(VK_RIGHT) < 0){
			r_xx = r_xx + 20;
			if(r_xx > 640 - 80){
				r_xx = 640 - 80;
			}
		}

		//横方向の処理
		b_xx += bd_xx;
		if(b_xx >= 640-16 || b_xx <= 0){
			bd_xx = -bd_xx;
		}
		if(b_xx < 0){
			b_xx = 0;
		}
		if(b_xx > 640-16){
			b_xx = 640-16;
		}

		//縦方向の処理
		b_yy += bd_yy;
		if(b_yy >= 480-16 || b_yy <= 0){
			bd_yy = -bd_yy;
		}
		if(b_yy < 0){
			b_yy = 0;
		}
		if(b_yy > 480-16){
			b_yy = 480-16;
		}

		//ボールの消去・描画処理
		if(bold_xx != b_xx || bold_yy != b_yy){
			//前に描画したボールを消去
			if(bold_xx != -1 && bold_yy != -1){
				gl_fillrect(bold_xx, bold_yy,
					bold_xx + 16, bold_yy + 16, RGB(0, 0, 0));
			}
			//ボールの旧位置(bold_xx、bold_yy)を更新
			bold_xx = b_xx;
			bold_yy = b_yy;
			//新しい位置にボールを描画
			gl_drawbitmap(hbmp_ball, b_xx, b_yy, 16, 16, 0, 0);
		}

		//ラケットの消去・描画処理
		if(rold_xx != r_xx){
			//前に描画したラケットを消去
			if(rold_xx != -1){
				gl_fillrect(rold_xx, 440, rold_xx + 80, 440 + 10, RGB(0, 0, 0));
			}
			//ラケットの旧位置(rold_xx)を更新
			rold_xx = r_xx;
			//新しい位置にラケットを描画
			gl_fillrect(r_xx, 440, r_xx + 80, 440 + 10, RGB(255, 255, 255));
		}

		gl_refresh();
	}
}
ボールでラケットが欠けている

ボールは壁で反射しながら動き、同時に左右のカーソルキー操作でラケットを移動させることができます。 ただ、ラケットの位置とボールの動きは連動していません。またボールとラケットが重なると表示が欠けてしまうこともあります。

2.ボールとラケットとの当り判定


ボールがラケットに当たっているかの判定を行い、ラケットに当たらなかった場合はプログラムを終了させるように修正します。
次のような修正を行います。
(1)下辺での反射位置が480ドットになっているので、ラケットの位置である440に変更します。
(2)下辺に達したときの処理(if文)をラケットの座標との当たり判定に変更します。
(3)ラケットに当たったとき音を鳴らします(課題1に入っているので)。
以上、3点の修正を行ったプログラムが下記になります。

#include <graph.h>

main()
{
	HBITMAP	hbmp_ball;
	//ボール用の変数
	int	b_xx = 0, bd_xx = 10,
		b_yy = 0, bd_yy = 10;
	int	bold_xx = -1, bold_yy = -1;

	//ラケット用の変数
	int	r_xx = 320, rold_xx = -1;
	unsigned long
		tick;

	hbmp_ball = gl_loadbitmap("ball.bmp");
	if(hbmp_ball == NULL){
		printf("ビットマップファイルが見つかりません.\n");
		exit(0);
	}
	gl_openwin(-1, -1, 640, 480, 0);

	tick = GetTickCount();
	for( ; ; ){
		if(GetTickCount() >= tick && GetTickCount() < tick + 50)
			continue;
		tick = GetTickCount();

		//ESCキーを押したらプログラムが終了する処理も追加
		if(gl_getkeystate(VK_ESCAPE) < 0)
			break;

		//カーソル左右キーでラケットの位置(r_xx)を変化させます
		//カーソル左キーが押されているときの処理
		if(gl_getkeystate(VK_LEFT) < 0){
			r_xx = r_xx - 20;
			if(r_xx < 0){
				r_xx = 0;
			}
		}
		//カーソル右キーが押されているときの処理
		if(gl_getkeystate(VK_RIGHT) < 0){
			r_xx = r_xx + 20;
			if(r_xx > 640 - 80){
				r_xx = 640 - 80;
			}
		}

		//横方向の処理
		b_xx += bd_xx;
		if(b_xx >= 640-16 || b_xx <= 0){
			bd_xx = -bd_xx;
		}
		if(b_xx < 0){
			b_xx = 0;
		}
		if(b_xx > 640-16){
			b_xx = 640-16;
		}

		//縦方向の処理
		b_yy += bd_yy;
		if(b_yy >= 440-16 || b_yy <= 0){
			bd_yy = -bd_yy;
		}
		if(b_yy < 0){
			b_yy = 0;
		}

		//ボールがウィンドウ下部に来たときの処理
		if(b_yy > 440-16){
			//if文にはボールのサイズを加味した方が良いですが
			//ここでは省略します。
			if(b_xx < r_xx - 16 || b_xx > r_xx + 80 + 16){
				break;
			}
			MessageBeep(0);
			b_yy = 440-16;
		}

		//ボールの消去・描画処理
		if(bold_xx != b_xx || bold_yy != b_yy){
			//前に描画したボールを消去
			if(bold_xx != -1 && bold_yy != -1){
				gl_fillrect(bold_xx, bold_yy,
					bold_xx + 16, bold_yy + 16, RGB(0, 0, 0));
			}
			//ボールの旧位置(bold_xx、bold_yy)を更新
			bold_xx = b_xx;
			bold_yy = b_yy;
			//新しい位置にボールを描画
			gl_drawbitmap(hbmp_ball, b_xx, b_yy, 16, 16, 0, 0);
		}

		//ラケットの消去・描画処理
		if(rold_xx != r_xx){
			//前に描画したラケットを消去
			if(rold_xx != -1){
				gl_fillrect(rold_xx, 440, rold_xx + 80, 440 + 10, RGB(0, 0, 0));
			}
			//ラケットの旧位置(rold_xx)を更新
			rold_xx = r_xx;
			//新しい位置にラケットを描画
			gl_fillrect(r_xx, 440, r_xx + 80, 440 + 10, RGB(255, 255, 255));
		}

		gl_refresh();
	}
}
課題1のプログラムが完成

これで課題1のプログラムが完成です。


[an error occurred while processing this directive]