{"id":72,"date":"2023-10-05T15:56:29","date_gmt":"2023-10-05T06:56:29","guid":{"rendered":"https:\/\/finady.jp\/demo-04\/?page_id=72"},"modified":"2023-10-05T16:27:04","modified_gmt":"2023-10-05T07:27:04","slug":"tetris","status":"publish","type":"page","link":"https:\/\/finady.jp\/demo-04\/tetris\/","title":{"rendered":"\u30c6\u30c8\u30ea\u30b9"},"content":{"rendered":"\n<div class=\"wrapper-container\">\n    <span class=\"tetris-container\">\n        <canvas id=\"stage\" width=\"250px\" height=\"500px\" style=\"background-color:black;\">\n        <\/canvas>\n        <span class=\"tetris-panel-container\">\n            <p>Next:<\/p>\n            <canvas id=\"next\" width=\"150px\" height=\"150px\" style=\"background-color:black;\">\n            <\/canvas>\n            <p>LINES:<span id=\"lines\">0<\/span><\/p>\n            <p><span id=\"message\"><\/span><\/p>\n            <div class=\"tetris-panel-container-padding\"><\/div>\n            <table class=\"tetris-button-panel\">\n                <tr>\n                    <td><\/td>\n                    <td id=\"tetris-rotate-button\" class=\"tetris-button\">\u21bb<\/td>\n                    <td><\/td>\n                <\/tr>\n                <tr>\n                    <td id=\"tetris-move-left-button\" class=\"tetris-button\">\u2190<\/td>\n                    <td id=\"tetris-fall-button\"class=\"tetris-button\">\u2193<\/td>\n                    <td id=\"tetris-move-right-button\" class=\"tetris-button\">\u2192<\/td>\n                <\/tr>\n            <\/table>\n        <\/span>\n    <\/span>\n    <!-- \u30b2\u30fc\u30e0\u3092\u958b\u59cb\u3059\u308b\u30dc\u30bf\u30f3\u3092\u8ffd\u52a0 -->\n    <button id=\"startGameButton\">\u30b2\u30fc\u30e0\u3092\u958b\u59cb<\/button>\n<\/div>\n<script>\ndocument.getElementById(\"startGameButton\").addEventListener(\"click\", function() {\n    var tetris = new Tetris();\n    tetris.startGame();\n});\n<\/script>\n\n\n\n<style>\n.wrapper-container {\n    display: inline-block;\n}\n\n.tetris-container {\n    display: flex;\n    flex-direction: row;\n    margin: 10px;\n    background-color: #333333;\n}\n\n.tetris-panel-container {\n    display: flex;\n    padding-left: 10px;\n    padding-right: 10px;\n    flex-direction: column;\n    color: white;\n    background-color: #333333;\n}\n\n.tetris-panel-container-padding {\n    flex-grow: 1;\n}\n\n.tetris-panel-container p {\n    margin: 0;\n    padding: 0;\n}\n\n.tetris-button-panel {\n    border-style: none;\n    width: 100%;\n}\n\n.tetris-button {\n    padding-top: 10px;\n    padding-bottom: 10px;\n    text-align: center;\n    background: #444444;\n}\n<\/style>\n\n\n\n<script>\nclass Tetris {\n    constructor() {\n        this.stageWidth = 10;\n        this.stageHeight = 20;\n        this.stageCanvas = document.getElementById(\"stage\");\n        this.nextCanvas = document.getElementById(\"next\");\n        let cellWidth = this.stageCanvas.width \/ this.stageWidth;\n        let cellHeight = this.stageCanvas.height \/ this.stageHeight;\n        this.cellSize = cellWidth < cellHeight ? cellWidth : cellHeight;\n        this.stageLeftPadding = (this.stageCanvas.width - this.cellSize * this.stageWidth) \/ 2;\n        this.stageTopPadding = (this.stageCanvas.height - this.cellSize * this.stageHeight) \/ 2;\n        this.blocks = this.createBlocks();\n        this.deletedLines = 0;\n\n        window.onkeydown = (e) => {\n            if (e.keyCode === 37) {\n                this.moveLeft();\n            } else if (e.keyCode === 38) {\n                this.rotate();\n            } else if (e.keyCode === 39) {\n                this.moveRight();\n            } else if (e.keyCode === 40) {\n                this.fall();\n            }\n        }\n\n        document.getElementById(\"tetris-move-left-button\").onmousedown = (e) => {\n            this.moveLeft();\n        }\n        document.getElementById(\"tetris-rotate-button\").onmousedown = (e) => {\n            this.rotate();\n        }\n        document.getElementById(\"tetris-move-right-button\").onmousedown = (e) => {\n            this.moveRight();\n        }\n        document.getElementById(\"tetris-fall-button\").onmousedown = (e) => {\n            this.fall();\n        }\n    }\n\n    createBlocks() {\n        let blocks = [\n            {\n                shape: [[[-1, 0], [0, 0], [1, 0], [2, 0]],\n                        [[0, -1], [0, 0], [0, 1], [0, 2]],\n                        [[-1, 0], [0, 0], [1, 0], [2, 0]],\n                        [[0, -1], [0, 0], [0, 1], [0, 2]]],\n                color: \"rgb(0, 255, 255)\",\n                highlight: \"rgb(255, 255, 255)\",\n                shadow: \"rgb(0, 128, 128)\"\n            },\n            {\n                shape: [[[0, 0], [1, 0], [0, 1], [1, 1]],\n                        [[0, 0], [1, 0], [0, 1], [1, 1]],\n                        [[0, 0], [1, 0], [0, 1], [1, 1]],\n                        [[0, 0], [1, 0], [0, 1], [1, 1]]],\n                color: \"rgb(255, 255, 0)\",\n                highlight: \"rgb(255, 255, 255)\",\n                shadow: \"rgb(128, 128, 0)\"\n            },\n            {\n                shape: [[[0, 0], [1, 0], [-1, 1], [0, 1]],\n                        [[-1, -1], [-1, 0], [0, 0], [0, 1]],\n                        [[0, 0], [1, 0], [-1, 1], [0, 1]],\n                        [[-1, -1], [-1, 0], [0, 0], [0, 1]]],\n                color: \"rgb(0, 255, 0)\",\n                highlight: \"rgb(255, 255, 255)\",\n                shadow: \"rgb(0, 128, 0)\"\n            },\n            {\n                shape: [[[-1, 0], [0, 0], [0, 1], [1, 1]],\n                        [[0, -1], [-1, 0], [0, 0], [-1, 1]],\n                        [[-1, 0], [0, 0], [0, 1], [1, 1]],\n                        [[0, -1], [-1, 0], [0, 0], [-1, 1]]],\n                color: \"rgb(255, 0, 0)\",\n                highlight: \"rgb(255, 255, 255)\",\n                shadow: \"rgb(128, 0, 0)\"\n            },\n            {\n                shape: [[[-1, -1], [-1, 0], [0, 0], [1, 0]],\n                        [[0, -1], [1, -1], [0, 0], [0, 1]],\n                        [[-1, 0], [0, 0], [1, 0], [1, 1]],\n                        [[0, -1], [0, 0], [-1, 1], [0, 1]]],\n                color: \"rgb(0, 0, 255)\",\n                highlight: \"rgb(255, 255, 255)\",\n                shadow: \"rgb(0, 0, 128)\"\n            },\n            {\n                shape: [[[1, -1], [-1, 0], [0, 0], [1, 0]],\n                        [[0, -1], [0, 0], [0, 1], [1, 1]],\n                        [[-1, 0], [0, 0], [1, 0], [-1, 1]],\n                        [[-1, -1], [0, -1], [0, 0], [0, 1]]],\n                color: \"rgb(255, 165, 0)\",\n                highlight: \"rgb(255, 255, 255)\",\n                shadow: \"rgb(128, 82, 0)\"\n            },\n            {\n                shape: [[[0, -1], [-1, 0], [0, 0], [1, 0]],\n                        [[0, -1], [0, 0], [1, 0], [0, 1]],\n                        [[-1, 0], [0, 0], [1, 0], [0, 1]],\n                        [[0, -1], [-1, 0], [0, 0], [0, 1]]],\n                color: \"rgb(255, 0, 255)\",\n                highlight: \"rgb(255, 255, 255)\",\n                shadow: \"rgb(128, 0, 128)\"\n            }\n        ];\n        return blocks;\n    }\n\n    drawBlock(x, y, type, angle, canvas) {\n        let context = canvas.getContext(\"2d\");\n        let block = this.blocks[type];\n        for (let i = 0; i < block.shape[angle].length; i++) {\n            this.drawCell(context,\n                     x + (block.shape[angle][i][0] * this.cellSize),\n                     y + (block.shape[angle][i][1] * this.cellSize),\n                     this.cellSize,\n                     type);\n        }\n    }\n\n    drawCell(context, cellX, cellY, cellSize, type) {\n        let block = this.blocks[type];\n        let adjustedX = cellX + 0.5;\n        let adjustedY = cellY + 0.5;\n        let adjustedSize = cellSize - 1;\n        context.fillStyle = block.color;\n        context.fillRect(adjustedX, adjustedY, adjustedSize, adjustedSize);\n        context.strokeStyle = block.highlight;\n        context.beginPath();\n        context.moveTo(adjustedX, adjustedY + adjustedSize);\n        context.lineTo(adjustedX, adjustedY);\n        context.lineTo(adjustedX + adjustedSize, adjustedY);\n        context.stroke();\n        context.strokeStyle = block.shadow;\n        context.beginPath();\n        context.moveTo(adjustedX, adjustedY + adjustedSize);\n        context.lineTo(adjustedX + adjustedSize, adjustedY + adjustedSize);\n        context.lineTo(adjustedX + adjustedSize, adjustedY);\n        context.stroke();\n    }\n\n    startGame() {\n        let virtualStage = new Array(this.stageWidth);\n        for (let i = 0; i < this.stageWidth; i++) {\n            virtualStage[i] = new Array(this.stageHeight).fill(null);\n        }\n        this.virtualStage = virtualStage;\n        this.currentBlock = null;\n        this.nextBlock = this.getRandomBlock();\n        this.mainLoop();\n    }\n\n    mainLoop() {\n        if (this.currentBlock == null) {\n            if (!this.createNewBlock()) {\n                return;\n            }\n        } else {\n            this.fallBlock();\n        }\n        this.drawStage();\n        if (this.currentBlock != null) {\n            this.drawBlock(this.stageLeftPadding + this.blockX * this.cellSize,\n                this.stageTopPadding + this.blockY * this.cellSize,\n                this.currentBlock, this.blockAngle, this.stageCanvas);\n        }\n        setTimeout(this.mainLoop.bind(this), 500);\n    }\n\n    createNewBlock() {\n        this.currentBlock = this.nextBlock;\n        this.nextBlock = this.getRandomBlock();\n        this.blockX = Math.floor(this.stageWidth \/ 2 - 2);\n        this.blockY = 0;\n        this.blockAngle = 0;\n        this.drawNextBlock();\n        if (!this.checkBlockMove(this.blockX, this.blockY, this.currentBlock, this.blockAngle)) {\n            let messageElem = document.getElementById(\"message\");\n            messageElem.innerText = \"GAME OVER\";\n            return false;\n        }\n        return true;\n    }\n\n    drawNextBlock() {\n        this.clear(this.nextCanvas);\n        this.drawBlock(this.cellSize * 2, this.cellSize, this.nextBlock,\n            0, this.nextCanvas);\n    }\n\n    getRandomBlock() {\n        return  Math.floor(Math.random() * 7);\n    }\n\n    fallBlock() {\n        if (this.checkBlockMove(this.blockX, this.blockY + 1, this.currentBlock, this.blockAngle)) {\n            this.blockY++;\n        } else {\n            this.fixBlock(this.blockX, this.blockY, this.currentBlock, this.blockAngle);\n            this.currentBlock = null;\n        }\n    }\n\n    checkBlockMove(x, y, type, angle) {\n        for (let i = 0; i < this.blocks[type].shape[angle].length; i++) {\n            let cellX = x + this.blocks[type].shape[angle][i][0];\n            let cellY = y + this.blocks[type].shape[angle][i][1];\n            if (cellX < 0 || cellX > this.stageWidth - 1) {\n                return false;\n            }\n            if (cellY > this.stageHeight - 1) {\n                return false;\n            }\n            if (this.virtualStage[cellX][cellY] != null) {\n                return false;\n            }\n        }\n        return true;\n    }\n\n    fixBlock(x, y, type, angle) {\n        for (let i = 0; i < this.blocks[type].shape[angle].length; i++) {\n            let cellX = x + this.blocks[type].shape[angle][i][0];\n            let cellY = y + this.blocks[type].shape[angle][i][1];\n            if (cellY >= 0) {\n                this.virtualStage[cellX][cellY] = type;\n            }\n        }\n        for (let y = this.stageHeight - 1; y >= 0; ) {\n            let filled = true;\n            for (let x = 0; x < this.stageWidth; x++) {\n                if (this.virtualStage[x][y] == null) {\n                    filled = false;\n                    break;\n                }\n            }\n            if (filled) {\n                for (let y2 = y; y2 > 0; y2--) {\n                    for (let x = 0; x < this.stageWidth; x++) {\n                        this.virtualStage[x][y2] = this.virtualStage[x][y2 - 1];\n                    }\n                }\n                for (let x = 0; x < this.stageWidth; x++) {\n                    this.virtualStage[x][0] = null;\n                }\n                let linesElem = document.getElementById(\"lines\");\n                this.deletedLines++;\n                linesElem.innerText = \"\" + this.deletedLines;\n            } else {\n                y--;\n            }\n        }\n    }\n\n    drawStage() {\n        this.clear(this.stageCanvas);\n\n        let context = this.stageCanvas.getContext(\"2d\");\n        for (let x = 0; x < this.virtualStage.length; x++) {\n            for (let y = 0; y < this.virtualStage[x].length; y++) {\n                if (this.virtualStage[x][y] != null) {\n                    this.drawCell(context,\n                        this.stageLeftPadding + (x * this.cellSize),\n                        this.stageTopPadding + (y * this.cellSize),\n                        this.cellSize,\n                        this.virtualStage[x][y]);\n                }\n            }\n        }\n    }\n\n    moveLeft() {\n        if (this.checkBlockMove(this.blockX - 1, this.blockY, this.currentBlock, this.blockAngle)) {\n            this.blockX--;\n            this.refreshStage();\n        }\n    }\n\n    moveRight() {\n        if (this.checkBlockMove(this.blockX + 1, this.blockY, this.currentBlock, this.blockAngle)) {\n            this.blockX++;\n            this.refreshStage();\n        }\n    }\n\n    rotate() {\n        let newAngle;\n        if (this.blockAngle < 3) {\n            newAngle = this.blockAngle + 1;\n        } else {\n            newAngle = 0;\n        }\n        if (this.checkBlockMove(this.blockX, this.blockY, this.currentBlock, newAngle)) {\n            this.blockAngle = newAngle;\n            this.refreshStage();\n        }\n    }\n\n    fall() {\n        while (this.checkBlockMove(this.blockX, this.blockY + 1, this.currentBlock, this.blockAngle)) {\n            this.blockY++;\n            this.refreshStage();\n        }\n    }\n\n    refreshStage() {\n        this.clear(this.stageCanvas);\n        this.drawStage();\n        this.drawBlock(this.stageLeftPadding + this.blockX * this.cellSize,\n                this.stageTopPadding + this.blockY * this.cellSize,\n                this.currentBlock, this.blockAngle, this.stageCanvas);\n    }\n\n    clear(canvas) {\n        let context = canvas.getContext(\"2d\");\n        context.fillStyle = \"rgb(0, 0, 0)\";\n        context.fillRect(0, 0, canvas.width, canvas.height);\n    }\n}\n\n<\/script>\n","protected":false},"excerpt":{"rendered":"<p>Next: LINES:0 \u21bb \u2190 \u2193 \u2192 \u30b2\u30fc\u30e0\u3092\u958b\u59cb<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"swell_btn_cv_data":"","footnotes":""},"class_list":["post-72","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/finady.jp\/demo-04\/wp-json\/wp\/v2\/pages\/72","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/finady.jp\/demo-04\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/finady.jp\/demo-04\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/finady.jp\/demo-04\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/finady.jp\/demo-04\/wp-json\/wp\/v2\/comments?post=72"}],"version-history":[{"count":7,"href":"https:\/\/finady.jp\/demo-04\/wp-json\/wp\/v2\/pages\/72\/revisions"}],"predecessor-version":[{"id":82,"href":"https:\/\/finady.jp\/demo-04\/wp-json\/wp\/v2\/pages\/72\/revisions\/82"}],"wp:attachment":[{"href":"https:\/\/finady.jp\/demo-04\/wp-json\/wp\/v2\/media?parent=72"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}