javascript
1<!DOCTYPE html> 2<html lang="ja"> 3<head><meta charset="utf-8"></head> 4<body> 5<canvas id="can"></canvas> 6<script> 7 8//落ちるスピード 9const GAME_SPEED = 300; 10 11//フィールドサイズ 12const FIELD_COL = 10; 13const FIELD_ROW = 20; 14 15//ブロック一つのサイズ(ピクセル) 16const BLOCK_SIZE = 30; 17 18//スクリーンサイズ 19const SCREEN_W = BLOCK_SIZE * FIELD_COL; 20const SCREEN_H = BLOCK_SIZE * FIELD_ROW; 21 22//テトロミノのサイズ 23const TETRO_SIZE =4; 24 25const TETRO_COLORS =[ 26 // "#000", //0空 27 "#6CF", //1水色 28 "#F92", //2オレンジ 29 "#66F", //3青 30 "#C5C", //4紫 31 "#FD2", //5黄色 32 "#F44", //6赤 33 "#5B5" //7緑 34]; 35 36const TETRO_TYPES = [ 37 // [], // 0.空っぽ 38 39 [ // 1.I 40 [ 0, 0, 0, 0 ], 41 [ 1, 1, 1, 1 ], 42 [ 0, 0, 0, 0 ], 43 [ 0, 0, 0, 0 ] 44 ], 45 [ // 2.L 46 [ 0, 1, 0, 0 ], 47 [ 0, 1, 0, 0 ], 48 [ 0, 1, 1, 0 ], 49 [ 0, 0, 0, 0 ] 50 ], 51 [ // 3.J 52 [ 0, 0, 1, 0 ], 53 [ 0, 0, 1, 0 ], 54 [ 0, 1, 1, 0 ], 55 [ 0, 0, 0, 0 ] 56 ], 57 [ // 4.T 58 [ 0, 1, 0, 0 ], 59 [ 0, 1, 1, 0 ], 60 [ 0, 1, 0, 0 ], 61 [ 0, 0, 0, 0 ] 62 ], 63 [ // 5.O 64 [ 0, 0, 0, 0 ], 65 [ 0, 1, 1, 0 ], 66 [ 0, 1, 1, 0 ], 67 [ 0, 0, 0, 0 ] 68 ], 69 [ // 6.Z 70 [ 0, 0, 0, 0 ], 71 [ 1, 1, 0, 0 ], 72 [ 0, 1, 1, 0 ], 73 [ 0, 0, 0, 0 ] 74 ], 75 [ // 7.S 76 [ 0, 0, 0, 0 ], 77 [ 0, 1, 1, 0 ], 78 [ 1, 1, 0, 0 ], 79 [ 0, 0, 0, 0 ] 80 ] 81]; 82 83//初期位置 84const START_X = FIELD_COL/2 - TETRO_SIZE/2; 85const START_Y = 0; 86 87//テトロミノ本体 88let tetro; 89//テトロミノの形 90let tetro_t; 91 92//テトロミノの座標 93let tetro_x = START_X; 94let tetro_y = START_Y; 95 96//フィールド本体 97let field = []; 98 99//ゲームオーバーフラグ 100let over = false; 101 102let can = document.getElementById("can"); 103let con = can.getContext("2d"); 104 105can.width = SCREEN_W; 106can.height = SCREEN_H; 107can.style.border = "4px solid #555"; 108 109tetro_t = Math.floor( Math.random()*(TETRO_TYPES.length-1) ); 110tetro = TETRO_TYPES[ tetro_t ]; 111 112init(); 113drawAll(); 114 115setInterval( dropTetro, GAME_SPEED ); 116 117//初期化 118function init() 119{ 120 //フィールドのクリア 121 for(let y=0; y<FIELD_ROW ; y++ ) 122 { 123 field[y] = []; 124 for(let x=0; x<FIELD_COL ; x++ ) 125 { 126 field[y][x] =0; 127 } 128 } 129 /* 130 field[5][8] = 1; 131 field[19][9] = 1; 132 field[19][0] = 1; 133 */ 134} 135 136//ブロック一つを描画する 137function drawBlock(x,y,c) 138{ 139 let px = x * BLOCK_SIZE; 140 let py = y * BLOCK_SIZE; 141 con.fillStyle=TETRO_COLORS[c]; 142 con.fillRect(px,py,BLOCK_SIZE,BLOCK_SIZE); 143 con.strokeStyle="black"; 144 con.strokeRect(px,py,BLOCK_SIZE,BLOCK_SIZE); 145} 146 147//全部描画する 148function drawAll() 149{ 150 con.clearRect(0,0,SCREEN_W,SCREEN_H); 151 152 for(let y=0; y<FIELD_ROW ; y++ ) 153 { 154 for(let x=0; x<FIELD_COL ; x++ ) 155 { 156 if( field[y][x] ) 157 { 158 drawBlock(x,y,field[y][x]); 159 } 160 } 161 } 162 for(let y=0; y<TETRO_SIZE ; y++ ) 163 { 164 for(let x=0; x<TETRO_SIZE ; x++ ) 165 { 166 if( tetro[y][x] ) 167 { 168 drawBlock(tetro_x+x, tetro_y+y,tetro_t); 169 } 170 } 171 } 172 173 if(over) 174 { 175 let s="GAME OVER"; 176 con.font = "40px 'MS ゴシック'"; 177 let w = con.measureText(s).width; 178 let x = SCREEN_W/2 - w/2; 179 let y = SCREEN_H/2 - 20; 180 con.lineWidth = 4; 181 con.strokeText(s,x,y); 182 con.fillStyle="white"; 183 con.fillText(s,x,y); 184 } 185} 186 187// ブロックの衝突判定 188function checkMove( mx,my ,ntetro) 189{ 190 if( ntetro == undefined ) ntetro = tetro; 191 192 for(let y=0; y<TETRO_SIZE ; y++ ) 193 { 194 for(let x=0; x<TETRO_SIZE ; x++ ) 195 { 196 if( ntetro[y][x] ) 197 { 198 let nx = tetro_x + mx + x; 199 let ny = tetro_y + my + y; 200 201 if( ny < 0 || 202 nx < 0 || 203 ny >= FIELD_ROW || 204 nx >= FIELD_COL || 205 field[ny][nx] ) 206 { 207 return false; 208 } 209 } 210 } 211 } 212 213 return true; 214} 215 216// テトロの回転 217function rotate() 218{ 219 let ntetro = []; 220 221 for(let y=0; y<TETRO_SIZE ; y++ ) 222 { 223 ntetro[y]=[]; 224 for(let x=0; x<TETRO_SIZE ; x++ ) 225 { 226 ntetro[y][x] = tetro[TETRO_SIZE-x-1][y]; 227 } 228 } 229 230 return ntetro; 231} 232 233//テトロを固定する 234function fixTetro() 235{ 236 for(let y=0; y<TETRO_SIZE ; y++ ) 237 { 238 for(let x=0; x<TETRO_SIZE ; x++ ) 239 { 240 if( tetro[y][x] ) 241 { 242 field[tetro_y + y][tetro_x + x] = tetro_t; 243 } 244 } 245 } 246} 247 248//ラインが揃ったかチェックして消す 249function checkLine() 250{ 251 let linec=0; 252 for(let y=0; y<FIELD_ROW ; y++ ) 253 { 254 let flag=true; 255 256 for(let x=0; x<FIELD_COL ; x++ ) 257 { 258 if( !field[y][x] ) 259 { 260 flag=false; 261 break; 262 } 263 } 264 265 if(flag) 266 { 267 linec++; 268 269 for(let ny = y; ny>0 ;ny-- ) 270 { 271 for(let nx=0;nx<FIELD_COL ; nx++) 272 { 273 field[ny][nx] = field[ny-1][nx]; 274 } 275 } 276 } 277 } 278} 279 280// ブロックの落ちる処理 281function dropTetro() 282{ 283 if(over)return; 284 285 if( checkMove( 0, 1 ) )tetro_y++; 286 else 287 { 288 fixTetro(); 289 checkLine(); 290 tetro_t = Math.floor( Math.random()*(TETRO_TYPES.length-1) ); 291 tetro = TETRO_TYPES[ tetro_t ]; 292 tetro_x = START_X; 293 tetro_y = START_Y; 294 295 if( !checkMove(0,0) ) 296 { 297 over=true; 298 } 299 } 300 drawAll(); 301} 302 303//キーボードが押された時の処理 304document.onkeydown = function(e) 305{ 306 if(over)return; 307 308 switch( e.keyCode ) 309 { 310 case 37:// 左 311 if( checkMove( -1, 0 ) )tetro_x--; 312 break; 313 case 38:// 上 314 //if( checkMove( 0,-1 ) )tetro_y--; 315 break; 316 case 39:// 右 317 if( checkMove( 1, 0 ) )tetro_x++; 318 break; 319 case 40:// 下 320 if( checkMove( 0, 1 ) )tetro_y++; 321 break; 322 case 32:// スペース 323 let ntetro = rotate(); 324 if( checkMove( 0, 0, ntetro) ) tetro = ntetro; 325 break; 326 } 327 328 drawAll(); 329} 330 331</script> 332</body> 333</html>
上記のようにTETRO_TYPESを0番目の空の配列をコメントアウトしてtetro_tのlengthを番号が合うように修正すると
0番目(I型)のブロックが下まで落ちると消えてしまいます。
左右と下の当たり判定は問題なく回転も問題なくできているため、fixTetroの記述が問題だと思うのですが…
配列0番目のからの配列を作らずにする方法となぜ消えてしまうのかおしえてほしいです
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/01/01 12:17
2020/01/01 12:18
2020/01/01 13:03
2020/01/01 13:05