第16回【テトリス制作.4】


まずは動画を見てくださいね!
前回で出来なかったブロック同士の当たり判定、壁との当たり判定をつけます。

キーボードの処理の修正

移動できるかどうか調べる関数checkMoveを作る事を想定して、if文を入れます。
	switch( e.keyCode )
	{
		case 37:// 左
			if( checkMove( -1, 0 ) )tetro_x--;
			break;
		case 38:// 上
			if( checkMove(  0,-1 ) )tetro_y--;
			break;
		case 39:// 右
			if( checkMove(  1, 0 ) )tetro_x++;
			break;
		case 40:// 下
			if( checkMove(  0, 1 ) )tetro_y++;
			break;
		case 32:// スペース
			break;
	}

checkMove本体を作ります。
プログラミングを始めたばっかりだと難しいかもしれないので良く考えて見てみてください!
// ブロックの衝突判定
function checkMove( mx,my )
{
	for(let y=0; y<TETRO_SIZE ; y++ )
	{
		for(let x=0; x<TETRO_SIZE ; x++ )
		{
			if(  tetro[y][x]  )
			{
				let nx = tetro_x + mx + x;
				let ny = tetro_y + my + y;
				
				if( ny < 0 ||
					nx < 0 ||
					ny >= FIELD_ROW ||
					nx >= FIELD_COL ||
					field[ny][nx] )
				{
					return false;
				}
			}
		}
	}
	
	return true;
}
※動画のコードにミスがあったので修正済み!field[ny][nx]の判定は最後にしましょう...
動画で解説していますが、フィールド範囲を超えてる場合と、テトロのブロックとフィールドのブロックが同じ位置にあったらfalseを返しています。

今回はこれでおしまいです!

これまでのソースコード

しっかり考えて理解してくださいね!
<!DOCTYPE html>
<html lang="ja">
<head><meta charset="utf-8">;</head>
<body>
<canvas id="can"></canvas>
<script>

//フィールドサイズ
const FIELD_COL = 10;
const FIELD_ROW = 20;

//ブロック一つのサイズ(ピクセル)
const BLOCK_SIZE = 30;

//スクリーンサイズ
const SCREEN_W = BLOCK_SIZE * FIELD_COL;
const SCREEN_H = BLOCK_SIZE * FIELD_ROW;

//テトロミノのサイズ
const TETRO_SIZE =4;

//テトロミノ本体
let tetro=[
	[ 0, 0, 0, 0 ],
	[ 1, 1, 0, 0 ],
	[ 0, 1, 1, 0 ],
	[ 0, 0, 0, 0 ]
];

//テトロミノの座標
let tetro_x = 0;
let tetro_y = 0;


//フィールド本体
let field = [];

let can = document.getElementById("can");
let con = can.getContext("2d");

can.width  = SCREEN_W;
can.height = SCREEN_H;
can.style.border = "4px solid #555";

init();
drawAll();

//初期化
function init()
{
	//フィールドのクリア
	for(let y=0; y<FIELD_ROW ; y++ )
	{
		field[y] = [];
		for(let x=0; x<FIELD_COL ; x++ )
		{
			field[y][x] =0;
		}
	}

	field[5][8]  = 1;
	field[19][9] = 1;
	field[19][0] = 1;
}

//ブロック一つを描画する
function drawBlock(x,y)
{
	let px = x * BLOCK_SIZE;
	let py = y * BLOCK_SIZE;
	con.fillStyle="red";
	con.fillRect(px,py,BLOCK_SIZE,BLOCK_SIZE);
	con.strokeStyle="black";
	con.strokeRect(px,py,BLOCK_SIZE,BLOCK_SIZE);
}

//全部描画する
function drawAll()
{
	con.clearRect(0,0,SCREEN_W,SCREEN_H);
	
	for(let y=0; y<FIELD_ROW ; y++ )
	{
		for(let x=0; x<FIELD_COL ; x++ )
		{
			if( field[y][x] )
			{
				drawBlock(x,y);
			}
		}
	}
	for(let y=0; y<TETRO_SIZE ; y++ )
	{
		for(let x=0; x<TETRO_SIZE ; x++ )
		{
			if( tetro[y][x] )
			{
				drawBlock(tetro_x+x, tetro_y+y);
			}
		}
	}
}

// ブロックの衝突判定
function checkMove( mx,my )
{
	for(let y=0; y<TETRO_SIZE ; y++ )
	{
		for(let x=0; x<TETRO_SIZE ; x++ )
		{
			if(  tetro[y][x]  )
			{
				let nx = tetro_x + mx + x;
				let ny = tetro_y + my + y;
				
				if( ny < 0 ||
					nx < 0 ||
					ny >= FIELD_ROW ||
					nx >= FIELD_COL ||
					field[ny][nx] )
				{
					return false;
				}
			}
		}
	}
	
	return true;
}

//キーボードが押された時の処理
document.onkeydown = function(e)
{
	switch( e.keyCode )
	{
		case 37:// 左
			if( checkMove( -1, 0 ) )tetro_x--;
			break;
		case 38:// 上
			if( checkMove(  0,-1 ) )tetro_y--;
			break;
		case 39:// 右
			if( checkMove(  1, 0 ) )tetro_x++;
			break;
		case 40:// 下
			if( checkMove(  0, 1 ) )tetro_y++;
			break;
		case 32:// スペース
			break;
	}
	
	drawAll();
}

</script>
</body>
</html>



akichon/あきちょん
Youtubeでプログラミング講座やってるゲーム好きの(元?)プログラマ...
>>open profile...
■Twitter始めました
https://twitter.com/ak1chon
■Youtubeチャンネルはこちら
akichon(Youtube)