我正在尝试编写js tetris应用程序作为我的第一个独立应用程序。我大部分都是我自己写的,遇到了麻烦。我有一个朋友来看看它,他的经验比我多得多,但我们无法解决问题。 我希望tetromino触及底部时重新启动主要功能(drawOnCanvas()),但是我尝试过的所有操作都表现得很奇怪。我认为这是因为其中存在递归。我的朋友认为这是由于事件侦听器导致该功能无法正常工作。 我将不胜感激。非常感谢。
这是我第一次运行后遇到的唯一错误:未捕获的TypeError:无法读取未定义的属性“ height” 在drawOnCanvas(script.js:89) 动画时(script.js:167)
P.S .:如果有人想运行代码,我可以发送图像。
代码如下:
const tetro = {
i: [document.getElementById('tetro_i'), document.getElementById('tetro_i1')],
j: [document.getElementById('tetro_j'), document.getElementById('tetro_j1'), document.getElementById('tetro_j2'), document.getElementById('tetro_j3')],
l: [document.getElementById('tetro_l'), document.getElementById('tetro_l1'), document.getElementById('tetro_l2'), document.getElementById('tetro_l3')],
o: [document.getElementById('tetro_o')],
s: [document.getElementById('tetro_s'), document.getElementById('tetro_s1')],
t: [document.getElementById('tetro_t'), document.getElementById('tetro_t1'), document.getElementById('tetro_t2'), document.getElementById('tetro_t3')],
z: [document.getElementById('tetro_z'), document.getElementById('tetro_z1')]
}
let temp = 0;
const [space, left, up, right, down] = [32, 37, 38, 39, 40];
// -- Removes arrow keys function in browser //
window.addEventListener("keydown", function(e) {
// space and arrow keys
if([space, left, up, right, down].indexOf(e.keyCode) > -1) {
e.preventDefault();
}
}, false);
// Creates an array of tetro.keys
const createArray = function(obj) {
var keys = [];
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
keys.push(prop[0]);
}
}
return keys;
}
// setup canvas
const canvas = document.getElementById('main_canvas');
canvas.width = 250;
canvas.height = 500;
const ctx = canvas.getContext("2d");
function setCanvas(c) {
c.fillStyle = "solid black";
c.fillRect(0, 0, canvas.width, canvas.height);
for (let i = 25; i < canvas.height; i += 25) {
c.beginPath();
c.moveTo(i, 0);
c.lineTo(i, canvas.height);
c.strokeStyle = "white";
c.lineWidth = 0.5;
c.stroke();
}
for (let i = 25; i < canvas.height; i += 25) {
c.beginPath();
c.moveTo(0, i);
c.lineTo(canvas.width, i);
c.strokeStyle = "white";
c.lineWidth = 0.5;
c.stroke();
}
c.beginPath();
c.moveTo(0, canvas.height);
c.lineTo(canvas.width, canvas.height);
c.strokeStyle = "yellow";
c.lineWidth = 5;
c.stroke();
}
drawOnCanvas();
function drawOnCanvas() {
let randNum, randTetro, x, y, finalTet;
// 1. select random tetromino
randNum = Math.floor(Math.random() * 7);
randTetro = createArray(tetro)[randNum];
console.log(randTetro);
// 2. draw on canvas
y = -(tetro[`${randTetro}`][temp].height);
x = 100;
finalTet = tetro[`${randTetro}`][temp];
console.log(tetro[`${randTetro}`].length)
ctx.clearRect(0, 0, canvas.width, canvas.height);
setCanvas(ctx);
ctx.drawImage(finalTet, x, y);
// 3. Move left and right & rotate
document.addEventListener('keydown', function(event) {
if (event.keyCode === up || event.which === up) {
if (tetro[`${randTetro}`].length > 0) {
if(temp === tetro[`${randTetro}`].length - 1) {
temp = 0;
} else {
temp += 1;
}
console.log('gor')
finalTet = tetro[`${randTetro}`][temp];
ctx.clearRect(0, 0, canvas.width, canvas.height);
setCanvas(ctx);
ctx.drawImage(finalTet, x, y);
console.log(temp)
}
//drawImageRot(finalTet, x, y, finalTet.width, finalTet.height);
} else if (event.keyCode === left || event.which === left) {
if (x >= 0 + 25) {
console.log('levo');
ctx.clearRect(0, 0, canvas.width, canvas.height);
setCanvas(ctx);
ctx.drawImage(finalTet, x -= 25, y);
}
} else if (event.keyCode === right || event.which === right) {
if (x <= canvas.width - finalTet.width -25) {
console.log('desno');
ctx.clearRect(0, 0, canvas.width, canvas.height);
setCanvas(ctx);
ctx.drawImage(finalTet, x += 25, y);
}
} else if (event.keyCode === down || event.which === down) {
if (y <= (canvas.height - (finalTet.height + 25))) {
console.log('doj');
ctx.clearRect(0, 0, canvas.width, canvas.height);
setCanvas(ctx);
ctx.drawImage(finalTet, x, y += 25);
}
}
});
function animate() {
// const animationFrame = requestAnimationFrame(animate);
requestAnimationFrame(animate);
if (y % 25 === 0) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
setCanvas(ctx);
ctx.drawImage(finalTet, x, y);
}
// 4. stop when reaching bottom
if (y >= (500 - (finalTet.height))) {
// cancelAnimationFrame();
ctx.save();
return drawOnCanvas()
}
y += 1;
// 5. draw new tetromino
}
animate();
}
#main_canvas {
border: 1px solid black
}
.tetrominoes {
display: none;
}
.canvas{
margin: 20px 40px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div class="canvas">
<canvas id="main_canvas" tabindex='1'>
</canvas>
</div>
<div class="tetrominoes">
<img id="tetro_i" src="./img/tetro_i.png" alt="">
<img id="tetro_i1" src="./img/tetro_i1.png" alt="">
<img id="tetro_j" src="./img/tetro_j.png" alt="">
<img id="tetro_j1" src="./img/tetro_j1.png" alt="">
<img id="tetro_j2" src="./img/tetro_j2.png" alt="">
<img id="tetro_j3" src="./img/tetro_j3.png" alt="">
<img id="tetro_l" src="./img/tetro_l.png" alt="">
<img id="tetro_l1" src="./img/tetro_l1.png" alt="">
<img id="tetro_l2" src="./img/tetro_l2.png" alt="">
<img id="tetro_l3" src="./img/tetro_l3.png" alt="">
<img id="tetro_o" src="./img/tetro_o.png" alt="">
<img id="tetro_s" src="./img/tetro_s.png" alt="">
<img id="tetro_s1" src="./img/tetro_s1.png" alt="">
<img id="tetro_t" src="./img/tetro_t.png" alt="">
<img id="tetro_t1" src="./img/tetro_t1.png" alt="">
<img id="tetro_t2" src="./img/tetro_t2.png" alt="">
<img id="tetro_t3" src="./img/tetro_t3.png" alt="">
<img id="tetro_z" src="./img/tetro_z.png" alt="">
<img id="tetro_z1" src="./img/tetro_z1.png" alt="">
</div>
<script src="script.js"></script>
</body>
</html>