画像(logo)

HOME/[C言語DXライブラリ]ブロックパズルの作り方 目次/五日目 当たり判定「底辺」

広告

[C言語 DXライブラリ ブロックパズルの作り方]
五日目 当たり判定「底辺」

広告

↓2016年02月29日発売↓

12歳からはじめる ゼロからのC言語 ゲームプログラミング教室

目次へ戻る

当たり判定

当たり判定のお時間です!今回は底辺の当たり判定とともにブロックを固定するトコロまでをやっていきたいと思います。

底辺の当たり判定

前回作った左右の当たり判定用の関数を少し変えて底辺の当たり判定用関数を作っていきます。

void my_collision_bottom(){
	int x,y;

	collision_flag = 0;

	for(y=0;y<BLOCK_HEIGHT;y++){
		for(x=0;x<BLOCK_WIDTH;x++){
			if(block[y][x] != 0){
				if(stage[block_y + (y + 1)][block_x + x] != 0){
					collision_flag = 1;
				}
			}
		}
	}
}

底辺の当たり判定になるので「y座標+1」の部分を調べれば大丈夫ですね。

ブロック再生成

今回からブロックが固定された後にブロックが再生成されるのでその処理を加えたいと思います。

void my_make_block(){
	int x,y;

	if(make_block_flag == 1){
		for(y=0;y<BLOCK_HEIGHT;y++){
			for(x=0;x<BLOCK_WIDTH;x++){
				block[y][x] = blocks[y][x];
			}
		}
		make_block_flag = 0;
	}
}

ブロックを作る「my_make_block()」にブロックを生成するかどうかのフラグ「int make_block_flag」を加えました。

「make_block_flag == 1」の時にブロックを作ります。

今回はまだ四角いブロック一種類のみなので何の意味があるのかと思うトコロですがそのへんはもう少し後半にお話しします。

それではこれらを使ってブロックを固定していきます。

ブロック固定の手順

ブロック固定と言われると何か複雑な事をしそうな気がしますが、

1・底辺の当たり判定を調べる

2・当たり判定があれば現在の「block」の状態を「stage」に保存する

3・ブロックの座標を元に戻す

だけで意外と簡単にブロックは固定されます。

「block」を「stage」に保存する

現在の「block」を「stage」に保存する「my_save_block()」です。

void my_save_block(){
	int x,y;

	for(y=0;y<BLOCK_HEIGHT;y++){
		for(x=0;x<BLOCK_WIDTH;x++){
			stage[block_y + y][block_x + x] += block[y][x];
		}
	}
}

言葉通りそのまま保存しているだけなので特に説明はいらないですね。

ブロックの座標を元に戻す

続いてブロックの座標を元に戻す「my_init_var2()」になります。

void my_init_var2(){
	block_x = 7;
	block_y = 0;
	block_y_count = 0;
	make_block_flag = 1;
}

ブロックの座標を元の位置に戻してあげます。

さきほどのブロック生成用のフラグも初期化します。

あとはこれらを組み合わせるだけです。

ブロック固定

ブロック固定の「my_fix_block()」です。

void my_fix_block(){
	
	my_collision_bottom();

	if(collision_flag != 0){
		my_save_block();
		my_init_var2();
	}
}

1・底辺の当たり判定を調べる

2・当たり判定があれば現在の「block」の状態を「stage」に保存する

3・ブロックの座標を元に戻す

の手順通りにブロックを固めるだけですね!

画像(cdxb_5_1)

ブロック固定!

「my_fall_block」を変更

この時点で実行しても特に違和感がないので見落としがちですが、このままではブロックを固定した後にも「block_y++」の処理が一度行われるので一つ落ちた状態からブロックが現れてしまいます。

なので「my_fall_block」に少し手を加えます。

void my_fall_block(){
	if(make_block_flag == 0){
		block_y_count += block_speed;
		block_y = block_y_count / DRAW_BLOCK_WIDTH;
	}
}

ここでさきほどの「make_block_flag」が意味を成します。

ブロック生成中でなければ「block_y++」みたいな感じですね。

これでブロック固定後にブロックが下がってしまう事を防ぐ事ができます。

広告

降下

さきほどの底辺の当たり判定用関数を使ってブロック降下処理も作ります。

if(key[KEY_INPUT_DOWN] % 5 == 1){
	my_collision_bottom();
	if(collision_flag == 0){
		block_y++;
		block_y_count = block_y * DRAW_BLOCK_WIDTH;
	}
}

キー入力の「my_move_block()」内、「KEY_INPUT_DOWN」矢印キー下を押した場合の処理です。

さきほどの「my_collision_bottom();」を使って当たり判定がなければ「block_y++」、

そして「block_y_count」をそこに合わせてあげるように「block_y_count = block_y * DRAW_BLOCK_WIDTH;」と計算します。

ゲームオーバー

ついでにゲームオーバーも作ってしまいます。

ブロックパズルにおいてのゲームオーバーの条件はブロック再生成時にそこにすでにあるブロックと重なってしまった場合なのでまずは重なった場合の当たり判定用関数を作ります。

void my_collision_center(){
	int x,y;

	collision_flag = 0;

	for(y=0;y<BLOCK_HEIGHT;y++){
		for(x=0;x<BLOCK_WIDTH;x++){
			if(block[y][x] != 0){
				if(stage[block_y + y][block_x + x] != 0){
					collision_flag = 1;
				}
			}
		}
	}
}

ブロックと重なってしまった場合なのでその場の判定ですね。

それではゲームオーバー判定用の関数を見てみます。

void my_gameover(){
	my_collision_center();

	if(collision_flag != 0){
		gameover_flag = 1;
	}
}

さきほどの関数を使ってゲームオーバー用に用意したフラグ「int gameover_flag」の切り替えをします。

これでゲームオーバーの判定ができるようになりました。

あとは「int main()」にゲームオーバーの条件を加えるだけです。

メイン

今回から「switch」文を使って初期化→ゲームループ→ゲームオーバーそれぞれを場面分けしていきます。

int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){
	ChangeWindowMode(TRUE);
	DxLib_Init();
	SetDrawScreen(DX_SCREEN_BACK);

	my_init_var();

	while(ProcessMessage() == 0){
		ClearDrawScreen();

		switch(game_state){
		case 0:
			game_state = 5;
			break;
		case 5:
			my_make_block();
			my_gameover();
			my_get_key();
			my_move_block();
			my_draw_back();
			my_draw_variable();
			my_draw_block();
			my_draw_stage();
			my_fix_block();
			my_fall_block();

			if(gameover_flag == 1){
				game_state = 10;
			}
			break;
		case 10:
			my_draw_back();
			my_draw_block();
			my_draw_stage();
			my_ed();
			break;
		default:
			break;
		}

		ScreenFlip();
	}

	DxLib_End();
	return 0;
}

「int game_state」という場面を表す変数を用意してそれぞれの場面分けをしております。

今回はゲームが始まってゲームオーバーになるまで一方通行ですが、次のステージに行きたい、ゲームオーバーになった時に最初からやり直させたいなどの処理を入れたい時はこの「switch」で分けた場面をもとにもどして再初期化などして対応します。

画像(cdxb_5_2)

ゲームオーバー!

ここまでの中間ソースになります。

中間ソース4

それでは次回はブロックの種類を増やすのと横一列が揃ったらブロックを消去してみたいと思います。

次回

六日目 ブロック消去

□ページの先頭へ□

□目次へ戻る□

□HOME□

広告

↓2017年06月16日発売↓

やさしいC 第5版 (「やさしい」シリーズ)

新品価格
¥2,700から
(2017/5/1 13:05時点)

↓2014年08月09日発売↓

新・明解C言語 入門編 (明解シリーズ)

新品価格
¥2,484から
(2017/5/1 13:08時点)

↓2016年02月20日発売↓

新・解きながら学ぶC言語

新品価格
¥2,160から
(2017/5/1 13:10時点)

↓2017年02月11日発売↓

C言語プログラミング基本例題88 88

新品価格
¥3,024から
(2017/5/1 13:12時点)

↓2016年12月15日発売↓

Cの絵本 第2版 C言語が好きになる新しい9つの扉

新品価格
¥1,490から
(2017/5/1 13:13時点)

↓2017年02月08日発売↓

新・明解C言語で学ぶアルゴリズムとデータ構造 (明解シリーズ)

新品価格
¥2,700から
(2017/5/1 13:15時点)