1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

テトリス

Posted at

#tetris.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>テトリス</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="stylesheet" type="text/css" href="css/tetris.css">
<script type="text/javascript" src="js/tetris.js"></script>
</head>
<body>
<h1>テトリス</h1>
<div class="wrapper-container">
<span class="tetris-container">
<canvas id="stage" width="250px" height="500px" style="background-color:black;">
</canvas>
<span class="tetris-panel-container">
<p>Next:</p>
<canvas id="next" width="150px" height="150px" style="background-color:black;">
</canvas>
<p>LINES:<span id="lines">0</span></p>
<p><span id="message"></span></p>
<div class="tetris-panel-container-padding"></div>
<table class="tetris-button-panel">
<tr>
<td></td>
<td id="tetris-rotate-button" class="tetris-button"></td>
<td></td>
</tr>
<tr>
<td id="tetris-move-left-button"class="tetris-button"></td>
<td id="tetris-fall-button"class="tetris-button"></td>
<td id="tetris-move-right-button"class="tetris-button"></td>
</tr>
</table>
</span>
</span>
</div>
<script>
var tetris = new Tetris();
tetris.startGame();
</script>
</body>
</html>

#css/tetris.css

html {
touch-action: manipulation;
}

.wrapper-container {
display: inline-block;
}


.tetris-container {
display: flex;

flex-direction: row;
margin: 10px;
background-color: #333333;
}

.tetris-panel-container {
display: flex;
padding-left: 10px;
padding-right: 10px;
flex-direction: column;
color: white;
background-color: #333333;
}

.tetris-panel-container-padding {
flex-grow: 1;
}

.tetris-panel-container p {
margin: 0;
padding: 0;
}

.tetris-button-panel {
border-style: none;
width: 100%;
}

.tetris-button {
padding-top: 10px;
padding-bottom: 10px;
text-align: center;
background: #444444;
 }

#js/tetris.js

class Tetris {
constructor() {
this.stageWidth = 10;
this.stageHeight = 20;
this.stageCanvas = document.getElementById("stage");
this.nextCanvas = document.getElementById("next");
let cellWidth = this.stageCanvas.width / this.stageWidth;
let cellHeight = this.stageCanvas.height / this.stageHeight;
this.cellSize = cellWidth < cellHeight ? cellWidth : cellHeight;
this.stageLeftPadding = (this.stageCanvas.width - this.cellSize * this.stageWidth) / 2;
this.stageTopPadding = (this.stageCanvas.height - this.cellSize * this.stageHeight) / 2;
this.blocks = this.createBlocks();
this.deletedLines = 0;

window.onkeydown = (e) => {
if (e.keyCode === 37) {
this.moveLeft();
} else if (e.keyCode === 38) {
this.rotate();
} else if (e.keyCode === 39) {
this.moveRight();
} else if (e.keyCode === 40) {
this.fall();
}
}
document.getElementById("tetris-move-left-button").onmousedown = (e) => {
this.moveLeft();
}
document.getElementById("tetris-rotate-button").onmousedown = (e) => {
this.rotate();

}
document.getElementById("tetris-move-right-button").onmousedown = (e) => {
this.moveRight();
}
document.getElementById("tetris-fall-button").onmousedown = (e) => {
this.fall();
}
}

createBlocks() {
let blocks = [
{
shape: [[[-1, 0], [0, 0], [1, 0], [2, 0]],
[[0, -1], [0, 0], [0, 1], [0, 2]],
[[-1, 0], [0, 0], [1, 0], [2, 0]],
[[0, -1], [0, 0], [0, 1], [0, 2]]],
color: "rgb(0, 255, 255)",
highlight: "rgb(255, 255, 255)",
shadow: "rgb(0, 128, 128)"
},
{
shape: [[[0, 0], [1, 0], [0, 1], [1, 1]],
[[0, 0], [1, 0], [0, 1], [1, 1]],
[[0, 0], [1, 0], [0, 1], [1, 1]],
[[0, 0], [1, 0], [0, 1], [1, 1]]],
color: "rgb(255, 255, 0)",
highlight: "rgb(255, 255, 255)",
shadow: "rgb(128, 128, 0)"
},
{
shape: [[[0, 0], [1, 0], [-1, 1], [0, 1]],
[[-1, -1], [-1, 0], [0, 0], [0, 1]],
[[0, 0], [1, 0], [-1, 1], [0, 1]],
[[-1, -1], [-1, 0], [0, 0], [0, 1]]],
color: "rgb(0, 255, 0)",
highlight: "rgb(255, 255, 255)",
shadow: "rgb(0, 128, 0)"
},
{
shape: [[[-1, 0], [0, 0], [0, 1], [1, 1]],
[[0, -1], [-1, 0], [0, 0], [-1, 1]],
[[-1, 0], [0, 0], [0, 1], [1, 1]],
[[0, -1], [-1, 0], [0, 0], [-1, 1]]],
color: "rgb(255, 0, 0)",
highlight: "rgb(255, 255, 255)",
shadow: "rgb(128, 0, 0)"
},
{
shape: [[[-1, -1], [-1, 0], [0, 0], [1, 0]],
[[0, -1], [1, -1], [0, 0], [0, 1]],
[[-1, 0], [0, 0], [1, 0], [1, 1]],
[[0, -1], [0, 0], [-1, 1], [0, 1]]],
color: "rgb(0, 0, 255)",
highlight: "rgb(255, 255, 255)",
shadow: "rgb(0, 0, 128)"
},
{
shape: [[[1, -1], [-1, 0], [0, 0], [1, 0]],
[[0, -1], [0, 0], [0, 1], [1, 1]],
[[-1, 0], [0, 0], [1, 0], [-1, 1]],
[[-1, -1], [0, -1], [0, 0], [0, 1]]],
color: "rgb(255, 165, 0)",
highlight: "rgb(255, 255, 255)",
shadow: "rgb(128, 82, 0)"
},
{
shape: [[[0, -1], [-1, 0], [0, 0], [1, 0]],
[[0, -1], [0, 0], [1, 0], [0, 1]],
[[-1, 0], [0, 0], [1, 0], [0, 1]],
[[0, -1], [-1, 0], [0, 0], [0, 1]]],
color: "rgb(255, 0, 255)",
highlight: "rgb(255, 255, 255)",
shadow: "rgb(128, 0, 128)"
}
];
return blocks;
}
drawBlock(x, y, type, angle, canvas) {
let context = canvas.getContext("2d");
let block = this.blocks[type];
for (let i = 0; i < block.shape[angle].length; i++) {
this.drawCell(context,
x + (block.shape[angle][i][0] * this.cellSize),
y + (block.shape[angle][i][1] * this.cellSize),
this.cellSize,
type);
}
}

drawCell(context, cellX, cellY, cellSize, type) {
let block = this.blocks[type];
let adjustedX = cellX + 0.5;
let adjustedY = cellY + 0.5;
let adjustedSize = cellSize - 1;
context.fillStyle = block.color;
context.fillRect(adjustedX, adjustedY, adjustedSize, adjustedSize);
context.strokeStyle = block.highlight;
context.beginPath();
context.moveTo(adjustedX, adjustedY + adjustedSize);
context.lineTo(adjustedX, adjustedY);
context.lineTo(adjustedX + adjustedSize, adjustedY);
context.stroke();
context.strokeStyle = block.shadow;
context.beginPath();
context.moveTo(adjustedX, adjustedY + adjustedSize);
context.lineTo(adjustedX + adjustedSize, adjustedY + adjustedSize);
context.lineTo(adjustedX + adjustedSize, adjustedY);
context.stroke();
}

startGame() {
let virtualStage = new Array(this.stageWidth);
for (let i = 0; i < this.stageWidth; i++) {
virtualStage[i] = new Array(this.stageHeight).fill(null);
}
this.virtualStage = virtualStage;
this.currentBlock = null;
this.nextBlock = this.getRandomBlock();
this.mainLoop();
}

mainLoop() {
if (this.currentBlock == null) {
if (!this.createNewBlock()) {
return;
}
} else {
this.fallBlock();
}
this.drawStage();
if (this.currentBlock != null) {
this.drawBlock(this.stageLeftPadding + this.blockX * this.cellSize,
this.stageTopPadding + this.blockY * this.cellSize,
this.currentBlock, this.blockAngle, this.stageCanvas);
}
setTimeout(this.mainLoop.bind(this), 500);
}

createNewBlock() {
this.currentBlock = this.nextBlock;
this.nextBlock = this.getRandomBlock();
this.blockX = Math.floor(this.stageWidth / 2 - 2);
this.blockY = 0;
this.blockAngle = 0;
this.drawNextBlock();
if (!this.checkBlockMove(this.blockX, this.blockY, this.currentBlock, this.blockAngle)) {
let messageElem = document.getElementById("message");
messageElem.innerText = "GAME OVER";
return false;
}
return true;
}

drawNextBlock() {
this.clear(this.nextCanvas);
this.drawBlock(this.cellSize * 2, this.cellSize, this.nextBlock,
0, this.nextCanvas);
}

getRandomBlock() {
return  Math.floor(Math.random() * 7);
}

fallBlock() {
if (this.checkBlockMove(this.blockX, this.blockY + 1, this.currentBlock, this.blockAngle)) {
this.blockY++;
} else {
this.fixBlock(this.blockX, this.blockY, this.currentBlock, this.blockAngle);
this.currentBlock = null;
}
}

checkBlockMove(x, y, type, angle) {
for (let i = 0; i < this.blocks[type].shape[angle].length; i++) {
let cellX = x + this.blocks[type].shape[angle][i][0];
let cellY = y + this.blocks[type].shape[angle][i][1];
if (cellX < 0 || cellX > this.stageWidth - 1) {
return false;
}
if (cellY > this.stageHeight - 1) {
return false;
}
if (this.virtualStage[cellX][cellY] != null) {
return false;
}
}
return true;
}

fixBlock(x, y, type, angle) {
for (let i = 0; i < this.blocks[type].shape[angle].length; i++) {
let cellX = x + this.blocks[type].shape[angle][i][0];
let cellY = y + this.blocks[type].shape[angle][i][1];
if (cellY >= 0) {
this.virtualStage[cellX][cellY] = type;
}
}
for (let y = this.stageHeight - 1; y >= 0; ) {
let filled = true;
for (let x = 0; x < this.stageWidth; x++) {
if (this.virtualStage[x][y] == null) {
filled = false;
break;
}
}
if (filled) {
for (let y2 = y; y2 > 0; y2--) {
for (let x = 0; x < this.stageWidth; x++) {
this.virtualStage[x][y2] = this.virtualStage[x][y2 - 1];
}
}
for (let x = 0; x < this.stageWidth; x++) {
this.virtualStage[x][0] = null;
}
let linesElem = document.getElementById("lines");
this.deletedLines++;
linesElem.innerText = "" + this.deletedLines;
} else {
y--;
}
}
}

drawStage() {
this.clear(this.stageCanvas);

let context = this.stageCanvas.getContext("2d");
for (let x = 0; x < this.virtualStage.length; x++) {
for (let y = 0; y < this.virtualStage[x].length; y++) {
if (this.virtualStage[x][y] != null) {
this.drawCell(context,
this.stageLeftPadding + (x * this.cellSize),
this.stageTopPadding + (y * this.cellSize),
this.cellSize,
this.virtualStage[x][y]);
}
}
}
}

moveLeft() {
if (this.checkBlockMove(this.blockX - 1, this.blockY, this.currentBlock, this.blockAngle)) {
this.blockX--;
this.refreshStage();
}
}

moveRight() {
if (this.checkBlockMove(this.blockX + 1, this.blockY, this.currentBlock, this.blockAngle)) {
this.blockX++;
this.refreshStage();
}
}

rotate() {
let newAngle;
if (this.blockAngle < 3) {
newAngle = this.blockAngle + 1;
} else {
newAngle = 0;
}
if (this.checkBlockMove(this.blockX, this.blockY, this.currentBlock, newAngle)) {
this.blockAngle = newAngle;
this.refreshStage();
}
}

fall() {
while (this.checkBlockMove(this.blockX, this.blockY + 1, this.currentBlock, this.blockAngle)) {
this.blockY++;
this.refreshStage();
}
}

refreshStage() {
this.clear(this.stageCanvas);
this.drawStage();
this.drawBlock(this.stageLeftPadding + this.blockX * this.cellSize,
this.stageTopPadding + this.blockY * this.cellSize,
this.currentBlock, this.blockAngle, this.stageCanvas);
}

clear(canvas) {
let context = canvas.getContext("2d");
context.fillStyle = "rgb(0, 0, 0)";
context.fillRect(0, 0, canvas.width, canvas.height);
}
}

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?