section6_2slideIncomplete
S: LEFT
F: RIGHT
J, L: ROTATION A
K: ROTATION B
とりあえず単発押下で横移動。
未来読みして、重なるようだったらとどまるようにした。
section6_2slideIncomplete.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()) } let jFired = 0 let lFired = 0 let kFired = 0 let sFired = 0 let fFired = 0 let jEvent = true let lEvent = true let kEvent = true let sEvent = true let fEvent = true function onKeyDown(e) { // j or l if (e.keyCode === 74 ) { jFired += 1 } if (e.keyCode === 76) { lFired += 1 } if (e.keyCode === 75) { kFired += 1 } // s 83 if (e.keyCode === 83) { sFired += 1 } // f 70 if (e.keyCode === 70) { fFired += 1 } } function onKeyUp(e) { if (e.keyCode === 74) { jFired = 0 jEvent = true } if (e.keyCode === 76) { lFired = 0 lEvent = true } if (e.keyCode === 75) { kFired = 0 kEvent = true } if (e.keyCode === 83) { sFired = 0 sEvent = true } if (e.keyCode === 70) { fFired = 0 fEvent = true } } 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 rotation(clockwise) { refresh() current.condition %= 4 let originalShape = current.shape let isOverlap = false let rows = current.shape.length let columns = current.shape[0].length let buffer = new Array(rows) for (let i = 0; i < columns; i++) { buffer[i] = new Array(rows).fill(0) } function roll(clockwise) { if (clockwise) { for (let i = 0; i < rows; i++) { for (let j = 0; j < columns; j++) { buffer[j][i] = current.shape[columns - i - 1][j] } } }else{ for (let i = 0; i < rows; i++) { for (let j = 0; j < columns; j++) { buffer[j][i] = current.shape[i][rows - j - 1] } } } current.shape = buffer } 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: // ここで配列の破壊的な入れ替えをしてるからrollだけやっても付け焼き刃 if (clockwise) { if (current.condition === 2) { let bufferShape = current.shape.shift() current.shape.push(bufferShape) } roll(true) if (current.condition === 3) { let bufferShape = current.shape.pop() current.shape.unshift(bufferShape) } }else{ if (current.condition === 2) { let bufferShape = current.shape.shift() current.shape.push(bufferShape) } roll(false) if (current.condition === 1) { let bufferShape = current.shape.pop() current.shape.unshift(bufferShape) } } break; } for (let i = 0; i < rows; i++) { for (let j = 0; j < columns; j++) { if (buffer[i][j] === 1) { console.log(field[minoDigitalY + i - 1][minoDigitalX + j - 1]) if (field[minoDigitalY + i - 1][minoDigitalX + j - 1] === 1) { isOverlap = true } } } } if(lockDelayTime === 0){ isOverlap = chkUnder() } if (isOverlap) { current.shape = originalShape }else{ if (clockwise) { current.condition += 3 } else { current.condition += 1 } } } function chkUnder() { 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) { if (field[minoDigitalY + i][minoDigitalX + j - 1] === 1) { return true } } } } } function judgment() { // landing if (chkUnder()) { 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 // lottery if (nextTetrimino.length < nextNumber) { nextTetrimino.push(...shuffle()) } setTetrimino(current, nextTetrimino.shift()) minoDigitalX = minoOffsetLeft locationX = size * minoOffsetLeft minoDigitalY = minoOffsetTop locationY = size * (minoOffsetTop + nextMinoOffsetTop) drawNext() } }else{ // falling locationY += dy minoDigitalY = Math.floor(locationY / size) - nextMinoOffsetTop if(0 < lockDelayTime) { lockDelayTime = 0 } } } function refresh() { 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 slideLeft() { refresh() let detect = false 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) { if (field[minoDigitalY + i - 1][minoDigitalX + j - 2] === 1) { detect = true } } } } if (!detect) { minoDigitalX -= 1 locationX = size * minoDigitalX } } function slideRight() { refresh() let detect = false 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) { if (field[minoDigitalY + i - 1][minoDigitalX + j] === 1) { detect = true } } } } if (!detect) { minoDigitalX += 1 locationX = size * minoDigitalX } } // setup !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() }() function draw(){ console.log(lockDelayTime) refresh() judgment() drawTetrimino() debugPointing() if (0 < jFired && jEvent) { rotation(false) jEvent = false } if (0 < lFired && lEvent) { rotation(false) lEvent = false } if (0 < kFired && kEvent) { rotation(true) kEvent = false } if (0 < sFired && sEvent) { if (14 <= sFired) { slideLeft() }else{ slideLeft() sEvent = false } } if (0 < fFired && fEvent) { slideRight() fEvent = false } requestAnimationFrame(draw) } draw(); document.addEventListener('keydown', onKeyDown, false) document.addEventListener('keyup', onKeyUp, false)