テトリスの7種類のブロックが落ちてくる部分

テトリスの7種類のブロックが落ちてくる部分 プログラム

JavaScriptでテトリスの7種類のブロックがランダムに落ちてくる部分のみを作った。

サンプルを見る

ブロック部分は3次元配列になっており、配列の一番目がブロック番号としている。
4×4のブロックが7種類で、

block[7][4][[4]

というようなイメージ。
0が何も無い部分で、1がブロック部分という見た目で分かる配列データになっている。(というか、こうしないとわたしがよくイメージできないから)

// ブロックを作成
	block =	 [[	[0, 0, 0, 0],
			[0, 1, 1, 0],
			[0, 1, 1, 0],
			[0, 0, 0, 0]],
			
		[	[0, 1, 0, 0],
			[0, 1, 0, 0],
			[0, 1, 0, 0],
			[0, 1, 0, 0]],

		[	[0, 0, 1, 0],
			[0, 1, 1, 0],
			[0, 1, 0, 0],
			[0, 0, 0, 0]],

		[	[0, 1, 0, 0],
			[0, 1, 1, 0],
			[0, 0, 1, 0],
			[0, 0, 0, 0]],

		[	[0, 0, 0, 0],
			[0, 1, 1, 0],
			[0, 1, 0, 0],
			[0, 1, 0, 0]],

		[	[0, 0, 0, 0],
			[0, 1, 1, 0],
			[0, 0, 1, 0],
			[0, 0, 1, 0]],

		[	[0, 0, 0, 0],
			[0, 1, 0, 0],
			[1, 1, 1, 0],
			[0, 0, 0, 0]]
		];

昔からわたしはオリジナルのブロックでテトリスが出来ないか考えていた。
ついでに9種類のオリジナルブロックのイメージも作ってみた。

かなりやるせない内容になった。
そういう意味では、テトリスのオリジナルで設定されたブロックの種類は良くできているのだと思った。

ソースコード

HTML部分

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Tetris v0.5</title>
<link rel="stylesheet" type="text/css" media="screen,print" href="style.css" />
</head>
<body>
<canvas id="canvas"></canvas>
<script type="text/javascript" src="game.js"></script>
</body>
</html>

CSS部分

/* css for Tetris */
* {
  margin: 0;
  padding: 0;
  border: 0;
}

body {
  background-color: #ddd;
  font: 30px sans-serif;
}

JavaScript部分

/*
 * Tetris v0.5
 *	Created by Shuichi Takeda at 2014-04-07
 */

/* ------- 開発履歴
	v0.5 テトリスのブロックがランダムに落ちてきて、積み重なる
*/
var cwidth = 320;
var cheight = 480;
var stage = new Array(12);
var field = new Array(12);
var bs = 24;                    // ブロックサイズ
var speed = 200;                // 落下速度
var block = new Array();	// 元のブロック(7種類)
var tblock = new Array();	// 回転用のブロック
var blockno;
var x, y;						// ブロックの位置
var sx, sy;					// ブロックの元の位置
var gameover;
var timer1;
// 初期化
window.onload = function(){
	var i;
	gameover = false;
	// キャンバスの設定
	var canvas = document.getElementById("canvas");
	canvas.width = cwidth;
	canvas.height = cheight;
	cnt = canvas.getContext("2d");
	cnt.fillStyle = "rgb(200, 200, 200)";
	cnt.fillRect(0, 0, cwidth, cheight);

	// ブロックを作成
	block =	 [[	[0, 0, 0, 0],
				[0, 1, 1, 0],
				[0, 1, 1, 0],
				[0, 0, 0, 0]],
				
			[	[0, 1, 0, 0],
				[0, 1, 0, 0],
				[0, 1, 0, 0],
				[0, 1, 0, 0]],

			[	[0, 0, 1, 0],
				[0, 1, 1, 0],
				[0, 1, 0, 0],
				[0, 0, 0, 0]],

			[	[0, 1, 0, 0],
				[0, 1, 1, 0],
				[0, 0, 1, 0],
				[0, 0, 0, 0]],

			[	[0, 0, 0, 0],
				[0, 1, 1, 0],
				[0, 1, 0, 0],
				[0, 1, 0, 0]],

			[	[0, 0, 0, 0],
				[0, 1, 1, 0],
				[0, 0, 1, 0],
				[0, 0, 1, 0]],

			[	[0, 0, 0, 0],
				[0, 1, 0, 0],
				[1, 1, 1, 0],
				[0, 0, 0, 0]]
			];

	// ステージとなる2次元配列を作成
	for(i=0; i<stage.length; i++){
		stage[i] = new Array(20);
	}
	for(i=0; i<field.length; i++){
		field[i] = new Array(20);
	}
	init();
	// イベント処理を設定
	canvas.addEventListener("mousedown", mousedownfunc, false);
	
	createblock();
	tick();
}
// 配列初期化
var init = function(){
	stage = [ [9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9],
			[9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9],
			[9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9],
			[9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9],
			[9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9],
			[9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9],
			[9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9],
			[9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9],
			[9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9],
			[9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9],
			[9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9],
			[9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9],
			[9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9],
			[9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9],
			[9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9],
			[9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9],
			[9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9],
			[9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9],
			[9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9],
			[9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9]];

	field = [	[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
			[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
			[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
			[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
			[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
			[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
			[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
			[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
			[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
			[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
			[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
			[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
			[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
			[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
			[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
			[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
			[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
			[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
			[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
			[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]];

	tblock = [	[0,0,0,0],
				[0,0,0,0],
				[0,0,0,0],
				[0,0,0,0]
			];

	// フィールドにステージをセット
	for(i=0; i<20; i++){
		for(j=0; j<12; j++){
			field[i][j] = stage[i][j];
		}
	}
}
// 描画
var drawfield = function(){
	var i, j;
	
	cnt.clearRect(0, 0, cwidth, cheight);		// キャンバスをクリア
	for(i=0; i<20; i++){
		for(j=0; j<12; j++){
			switch(field[i][j]){
				case 0:		// なにもない
					cnt.fillStyle = "#ddd";
					cnt.fillRect(j*bs, i*bs, bs-1, bs-1);    // 1引いているのはブロック同士の隙間を入れるため
					break;
				case 1:		// ブロック
					cnt.fillStyle = "rgb(0, 200, 0)";
					cnt.fillRect(j*bs, i*bs, bs-1, bs-1);    // 1引いているのはブロック同士の隙間を入れるため
					break;
				case 9:		// 壁
					cnt.fillStyle = "rgb(0, 150, 0)";
					cnt.fillRect(j*bs, i*bs, bs-1, bs-1);
					break;
				default:		// 重なったときの色
					cnt.fillStyle = "#f00";
					cnt.fillRect(j*bs, i*bs, bs-1, bs-1);
			}
		}
	}       
}

// 新しいブロックを作成
var createblock = function(){
	x = sx = Math.floor(Math.random()*7)+1;
	y = sy = 0;
	blockno = Math.floor(Math.random()*7);
//	blockno = 1;
	// ブロックをコピー
	for(i=0; i<4; i++){
		for(j=0; j<4; j++){
			tblock[i][j] = block[blockno][i][j];
		}
	}
	
	if(hitcheck()){
		gameover = true;
		putblock();
	}
}

// 元のブロックをクリア
var clearblock = function(){
	var i, j;


	for(i=0; i<4; i++){
		for(j=0; j<4; j++){
//			if(block[blockno][i][j]) field[i+sy][j+sx] = 0;
			if(tblock[i][j]){
				stage[i+y][j+x] = 0;
			}
		}
	}
	for(i=0; i<20; i++){
		for(j=0; j<12; j++){
			field[i][j] = stage[i][j];
		}
	}
}

// ブロックの位置をセット
var putblock = function(){
	var i, j;
	for(i=0; i<4; i++){
		for(j=0; j<4; j++){
//			field[i+y][j+x] = stage[i+y][j+x] + tblock[i][j];
			field[i+y][j+x] = stage[i+y][j+x];
			field[i+y][j+x] += tblock[i][j];
		}
	}
}

// ブロックの位置をチェック
var hitcheck = function(){
	var i, j;
	for(i=0; i<4; i++){
		for(j=0; j<4; j++){
/*
			if(stage[i+y][j+x] == 9 && block[blockno][i][j] == 1) return 1;
			else if(stage[i+y][j+x] == 1 && block[blockno][i][j] == 1) return 1;
*/
			if(stage[i+y][j+x] == 9 && tblock[i][j] == 1) return 1;
			else if(stage[i+y][j+x] == 1 && tblock[i][j] == 1) return 1;
		}
	}
	return 0;
}

var lockblock = function(){
	var i, j;
	for(i=0; i<20; i++){
		for(j=0; j<12; j++){
			stage[i][j] = field[i][j];
		}
	}
}
var linecheck = function(){
	var ly = 18;		// 一番下のライン
	var lx;
	
	while(ly >= 0){
		count = 0;
		for(lx=1; lx<=10; lx++){
			if(stage[ly][lx]) count++;
		}
		if(count >= 10){
			for(var i=ly; i>=1; i--){
				for(lx=1; lx<=10; lx++){
					stage[i][lx] = stage[i-1][lx];
				}
			}
		}
		ly --;
	}
}

// タイマー処理
var tick = function(){
	sx = x; sy = y;
	y++;
	if(hitcheck()){
		y--;
		putblock();
		lockblock();
		linecheck();
		createblock();
	}
	putblock();
	linecheck();

	drawfield();
	clearblock();

	if(gameover == true){
		clearTimeout(timer1);
		gameover = false;
		speed -= 10;
		if(speed < 10) speed = 10;
		init();
		createblock();
	}
	timer1 = setTimeout("tick()", speed);
}

// マウスボタンを押したときの処理
var mousedownfunc = function(event){
}

コメント

タイトルとURLをコピーしました