Страницы

Поиск по вопросам

воскресенье, 9 июня 2019 г.

многократный вывод ошибки в консоль (пишу змейку помогите js'еры)

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
Решение обычное - использование в этих случаях обычных функций, а не стрелочных.

Комментариев нет:

Отправить комментарий