index.js:182 Uncaught TypeError: document.querySelector(...).keydown is not a function
at index.js:182
Uncaught TypeError: Cannot read property '0' of undefined
at Snake.move (index.js:82)
at setInterval (index.js:171)
const random = (max) => (Math.random() * (max + 1)) | 0;
let c = document.getElementById('c');
let ctx = c.getContext('2d');
let width = c.width;
let height = c.height;
let blockSize = 10;
let widthInBlocks = width / blockSize;
let heightInBlocks = height / blockSize;
let score = 0;
let drawBorder = () => {
ctx.fillStyle = 'Gray';
ctx.fillRect(0, 0, width, bBorderlockSize);
ctx.fillRect(0, height - blockSize, width, blockSize);
ctx.fillRect(width - blockSize, 0, blockSize, height);
};
let drawScore = () => {
ctx.font = '20px Courier';
ctx.fillStyle = 'Black';
ctx.textAlign = 'left';
ctx.textBaseline = 'top';
ctx.fillText('Счет: ' + score, blockSize, blockSize);
};
let gameOver = () => {
clearInterval(intervalId);
ctx.font = '60px Courier';
ctx.fillStyle = 'Black';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText('Конец игры: ', width / 2, height / 2);
};
let circle = (x, y, radius, fillCircle) => {
ctx.beginPath();
ctx.arc(x, y, radius, 0, Math.PI * 2, false);
if (fillCircle) {
ctx.fill();
} else {
ctx.stroke();
}
};
let Block = function(col, row) {
this.col = col;
this.row = row;
};
Block.prototype.drawSquare = (color) => {
let x = this.col * blockSize;
let y = this.row * blockSize;
ctx.fillStyle = color;
ctx.fillRect(x, y, blockSize, blockSize);
};
Block.prototype.drawCircle = (color) => {
let centerX = this.col * blockSize + blockSize / 2;
let centerY = this.row * blockSIze + blockSize / 2;
ctx.fillStyle = color;
circle(centerX, centerY, blockSize / 2, true);
};
Block.prototype.equal = (otherBlock) => {
return this.col === otherBlock.col && this.row === otherBlock.row;
};
let Snake = function() {
this.segments = [
new Block(7, 5),
new Block(6, 5),
new Block(5, 5)
];
this.direction = 'right';
this.nextDirection = 'right';
};
Snake.prototype.draw = () => {
for (let i = 0; i < this.segments.length; i++) {
this.segments[i].drawSquare('Blue');
}
};
Snake.prototype.move = () => {
let head = this.segments[0];
let newHead;
this.direction = this.nextDirection;
switch (this.direction) {
case 'right':
newHead = new Block(head.col + 1, head.row);
break;
case 'down':
newHead = new Block(head.col, head.row + 1);
break;
case 'left':
newHead = new Block(head.col - 1, head.row);
break;
case 'up':
newHead = new Block(head.col, head.row - 1);
break;
};
if (this.checkCollision(newHead)) {
gameOver();
return;
}
this.segments.unshift(newHead);
if (newHead.equal(apple.position)) {
score++;
apple.move();
} else {
this.segments.pop()
}
};
Snake.prototype.checkCollision = (head) => {
let leftCollusion = (head.col === 0);
let topCollusion = (head.row === 0);
let rightCollusion = (head.col === widthInBlocks - 1);
let bottomCollusion = (head.col === heightInBlocks - 1);
let wallCollusion = leftCollusion || topCollusion || rightCollusion || bottomCollusion;
let selfCollusion = false;
for (let i = 0; i < this.segments.length; i++) {
if (head.equal(this.segments[i])) {
selfCollusion = true;
}
}
return wallCollusion || selfCollusion;
};
Snake.prototype.setDirection = (newDirection) => {
if (this.direction === 'up' && newDirection === 'down') {
return;
} else if (this.direction === 'right' && newDirection === 'left') {
return;
} else if (this.direction === 'down' && newDirection === 'up') {
return;
} else if (this.direction === 'left' && newDirection === 'right') {
return;
}
this.nextDirection = newDirection;
};
let Apple = function() {
this.position = new Block(10, 10);
};
Apple.prototype.draw = () => {
this.position.drawCircle('LimeGreen');
};
Apple.prototype.move = () => {
let randomCol = Math.floor(random(widthInBlocks)) + 1;
let randomRow = Math.floor(random(heightInBlocks)) + 1;
this.position = new Block(randomCol, randomRow);
};
let snake = new Snake;
let apple = new Apple;
let intervalId = setInterval(() => {
ctx.clearRect(0, 0, width, height);
drawScore();
snake.move();
snake.draw();
apple.draw();
drawBorder();
}, 100);
let directions = {
37: 'left',
38: 'up',
39: 'right',
40: 'down'
};
document.querySelector('body').keydown((event) => {
let newDirection = directions[event.keyCode];
if (newDirection !== undefined) {
snake.setDirection(newDirection);
}
});
#canvas {
width: 400px;
height: 400px;
}
Ответ
Что касается первой ошибки:
document.querySelector('body').keydown((event) => {
keydown - это НЕ функция. Возможно тут сказалось влияние jQuery, в котором подписка на событие действительно выглядит так.
Для решения можно использовать метод addEventListener
document.querySelector('body').addEventListener('keydown',e => {...})
Что касается второй ошибки.
Проблема в чрезмерном увлечении стрелочными функциями.
this для стрелочных функций определяется в момент их создания (подробнее в вопросе Потеря контекста вызова)
В данном случае в момент создания, this ссылается на глобальный объект window, а не на ожидаемый объект sneak
Решение обычное - использование в этих случаях обычных функций, а не стрелочных.
Комментариев нет:
Отправить комментарий