section5_3lock
フィールドを黒背景に。
回転すると配列に残るから、回転時にもrefreshする。
さっきと比べてほしい。
ただ固定時間がきたときに1にするだけだと、nextTetriminoの形ぶん0にされる。
minoDigitalYもリセット。
section5_3lock.js
const canvas = document.getElementById(('myCanvas')) const context = canvas.getContext('2d') const bgColor = '#222' let screenX = screenY = 0 const nextNumber = 3 let size = 24 let nextTetrimino = [] let current = { name: 'a', color: '#000', shape: [[]], condition: 0 } // mino.. 配列ベースの位置関係 // location.. sizeベースの位置関係 = size * mono const minoOffsetLeft = 5 let minoDigitalX = minoOffsetLeft let locationX = size * minoOffsetLeft const minoOffsetTop = 1 let minoDigitalY = minoOffsetTop // next表示分にheaderとってあるからminoOffsetTopよりズレる // next分ってことを明示するconst置けばよくない? const nextMinoOffsetTop = 3 let locationY = size * (minoOffsetTop + nextMinoOffsetTop) let dy = 1 let LockDelayTime = 0 let LockDelayLimit = 30 const testSize = 5 const sizeOffsetTop = 4 const sizeOffsetLeft = 1 const empty = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1] let field = [ [0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0] ] for (let i = 0; i < 21; i++) { field.unshift(empty.concat()) } function onDown(e) { if (screenX < canvas.width / 2) { rotation(false) current.condition += 1 }else{ rotation(true) current.condition += 3 } } function onClick(e) {} function onMouseMove(e) { screenX = e.clientX - canvas.offsetLeft screenY = e.clientY - canvas.offsetTop } function shuffle() { let arr = ['T', 'J', 'L', 'Z', 'S', 'I', 'O'] for (let i = arr.length - 1; i > 0; i--){ let r = Math.floor(Math.random() * (i + 1)) let tmp = arr[i] arr[i] = arr[r] arr[r] = tmp } return arr } function setTetrimino(obj, target) { switch (target) { case 'T': obj.name = 'T' obj.color = '#0ff' obj.shape = [ [0, 0, 0], [1, 1, 1], [0, 1, 0]] break; case 'J': obj.name = 'J' obj.color = '#00f' obj.shape = [ [0, 0, 0], [1, 1, 1], [0, 0, 1]] break; case 'L': obj.name = 'L' obj.color = '#f60' obj.shape = [ [0, 0, 0], [1, 1, 1], [1, 0, 0]] break; case 'Z': obj.name = 'Z' obj.color = '#0f0' obj.shape = [ [0, 0, 0], [1, 1, 0], [0, 1, 1]] break; case 'S': obj.name = 'S' obj.color = '#f0f' obj.shape = [ [0, 0, 0], [0, 1, 1], [1, 1, 0]] break; case 'I': obj.name = 'I' obj.color = '#f00' obj.shape = [ [0, 0, 0, 0], [1, 1, 1, 1], [0, 0, 0, 0], [0, 0, 0, 0]] break; case 'O': obj.name = 'O' obj.color = '#ff0' obj.shape = [ [0, 0, 0], [0, 1, 1], [0, 1, 1]] break; } obj.condition = 0 return obj } function drawTetrimino() { for (let i = 0; i < current.shape.length; i++) { for (let j = 0; j < current.shape[i].length; j++) { if (current.shape[i][j] === 1) { field[minoDigitalY + i - 1][minoDigitalX + j - 1] = 1 context.fillStyle = current.color context.fillRect(locationX + j * size, locationY + i * size, size, size) } } } } function drawNext() { let next = { name: 'a', color: '#000', shape: [[]], condition: 0 } let nextShowX = minoOffsetLeft * size let nextShowY = 2 * size let nextShowWidth = 4 * size let nextShowHeight = 2 * size context.clearRect(nextShowX, nextShowY, nextShowWidth, nextShowHeight) setTetrimino(next, nextTetrimino[0]) for (let i = 0; i < next.shape.length; i++) { for (let j = 0; j < next.shape[i].length; j++) { if (next.shape[i][j] === 1) { context.fillStyle = next.color context.fillRect(size * (minoOffsetLeft + j),size * (minoOffsetTop + i), size, size) } } } } function debugPointing() { for (let i = 0; i < field.length; i++) { for (let j = 0; j < field[i].length; j++) { if (field[i][j] === 1) { context.fillStyle = '#333' context.fillRect((j + sizeOffsetLeft) * size, (i + sizeOffsetTop) * size, testSize, testSize) }else{ context.fillStyle = '#fff' context.fillRect((j + sizeOffsetLeft) * size, (i + sizeOffsetTop) * size, testSize, testSize) } } } } function roll(clockwise) { let rows = current.shape.length let columns = current.shape.length let baffer = new Array(rows) for (let i = 0; i < columns; i++) { baffer[i] = new Array(rows).fill(0) } if (clockwise) { for (let i = 0; i < rows; i++) { for (let j = 0; j < columns; j++) { baffer[j][i] = current.shape[columns - i - 1][j] } } }else{ for (let i = 0; i < rows; i++) { for (let j = 0; j < columns; j++) { baffer[j][i] = current.shape[i][rows - j - 1] } } } current.shape = baffer } function rotation(clockwise) { refreshCurrent() current.condition %= 4 switch (current.name) { case 'O': break; case 'Z': if(current.condition % 2) { roll(true) }else{ roll(false) } break; case 'S': case 'I': if(current.condition % 2) { roll(false) }else{ roll(true) } break; default: if (clockwise) { if (current.condition === 2) { let buffer = current.shape.shift() current.shape.push(buffer) } roll(true) if (current.condition === 3) { let buffer = current.shape.pop() current.shape.unshift(buffer) } }else{ if (current.condition === 2) { let buffer = current.shape.shift() current.shape.push(buffer) } roll(false) if (current.condition === 1) { let buffer = current.shape.pop() current.shape.unshift(buffer) } } break; } } function judgment() { // landing if (size * 22 <= locationY) { LockDelayTime += 1 if(LockDelayLimit <= LockDelayTime){ for (let i = 0; i < current.shape.length; i++) { for (let j = 0; j < current.shape[i].length; j++) { if (current.shape[i][j] === 1) { field[minoDigitalY + i - 1][minoDigitalX + j - 1] = 1 context.fillStyle = current.color context.fillRect(locationX + j * size, locationY + i * size, size, size) } } } LockDelayTime = 0 // nextTetrimino.shift() // lottery if (nextTetrimino.length < nextNumber) { nextTetrimino.push(...shuffle()) } setTetrimino(current, nextTetrimino.shift()) locationY = size * (minoOffsetTop + nextMinoOffsetTop) minoDigitalY = minoOffsetTop drawNext() } }else{ // falling locationY += dy minoDigitalY = Math.floor(locationY / size) - nextMinoOffsetTop if(!LockDelayTime === 0) { LockDelayTime = 0 } } } function refreshCurrent() { for (let i = 0; i < current.shape.length; i++) { for (let j = 0; j < current.shape[i].length; j++) { if (current.shape[i][j] === 1) { field[minoDigitalY + i - 1][minoDigitalX + j - 1] = 0 context.fillStyle = bgColor context.fillRect(locationX + j * size, locationY + i * size, size, size) } } } } function refresh() { //context.clearRect(size * 2, size * 5, size * 10, size * 20) refreshCurrent() } !function() { context.fillStyle = '#ccc' context.fillRect(size, size, size * field[0].length, size * (nextMinoOffsetTop + field.length)) context.fillStyle = bgColor const fieldOffsetLeft = size * 2 const fieldOffsetTop = size * 5 const fieldWidth = size * 10 const fieldHeight = size * 20 context.fillRect(fieldOffsetLeft, fieldOffsetTop, fieldWidth, fieldHeight) nextTetrimino.push(...shuffle()) setTetrimino(current, nextTetrimino.shift()) drawNext() }()// setup function draw(){ refresh() judgment() drawTetrimino() debugPointing() requestAnimationFrame(draw) } draw(); canvas.addEventListener('mousedown', onDown, false) canvas.addEventListener('click', onClick, false) canvas.addEventListener('mousemove', onMouseMove, false)
ていうかわかりにくい変数作りすぎ、配列ベースでわかりやすくなるように、
及び、一時しのぎのマジックナンバーを整理。