Я пытаюсь выяснить, почему хвостовая часть моей змеи вытягивается только один блок за раз, когда я ем еду.Я хочу, чтобы втянуться все вместе и следовать за головой змеи (чтобы сделать полную змею).Только один прямоугольник рисуется поверх того места, где была еда, когда моя змеиная голова пробегала над ней;и голова только начинает тянуться, куда бы я ни шел.
Это похоже на то, как будто хвостовой массив змеи рисуется по всей карте, а на самом деле не рисуется «подключенным».
Ниже мой код.
СпасибоВы за любую помощь!
Весь код:
<!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>
<style>
.new-div {
display:flex;
justify-content: center;
align-items: center;
width:400px;
height:400px;
position:absolute;
top:0;
z-index:4000;
}
.game-content {
position:relative;
top:35px;
right:0px;
border:none;
border-radius:5px;
padding:10px;
background-color:teal;
color:white;
}
</style>
</head>
<body>
<canvas id="canvas" width="400" height="400" style="border:1px solid black"></canvas>
<script type="text/javascript">
window.onload = function() {
fruit.generateNewFruit();
window.requestAnimationFrame(main);
}
var tools = {
canvas: document.getElementById('canvas'),
ctx: canvas.getContext('2d'),
drawRect: function(x, y, sizeX, sizeY, color, type, stroke, strokeColor) {
if (type == 'fill') {
this.ctx.fillStyle = color;
this.ctx.fillRect(x, y, sizeX, sizeY);
if (stroke == true) {
this.ctx.strokeStyle = strokeColor;
this.ctx.strokeRect(x, y, sizeX, sizeY);
}
} else {
this.ctx.fillStyle = color;
this.ctx.strokeRect(x, y, sizeX, sizeY);
}
},
writeText: function(text, x, y, font, fontStyle, color) {
if (font) {
this.ctx.font = fontStyle;
}
this.ctx.fillStyle = color;
this.ctx.fillText(text, x, y);
}
}
let game = {
x: tools.canvas.width / 2 - 40,
y: tools.canvas.height / 2,
gameOver: false,
gameOverMsg: function(msg, font) {
let newDiv = document.createElement('div');
let button = document.createElement('button');
let btnText = document.createTextNode('Play Again');
button.className = "game-content";
newDiv.className = "new-div";
tools.writeText(msg, this.x, this.y, true, "16px bold sans-serif", "#fff");
button.appendChild(btnText);
newDiv.appendChild(button);
document.body.appendChild(newDiv);
document.getElementsByClassName('game-content')[0].addEventListener('click', function() {
game.gameOver = true;
});
}
}
let map = {
tileX: 0,
tileY: 0,
tileRow: 20,
tileCol: 20,
tileSize: 20,
tileColor: 'gray',
drawMap: function() {
for (let col = 0; col < this.tileCol; col++) {
for (let row = 0; row < this.tileRow; row++) {
tools.drawRect(this.tileX, this.tileY, this.tileSize, this.tileSize, this.tileColor, 'fill');
this.tileX += this.tileSize;
}
this.tileX = 0;
this.tileY += this.tileSize;
}
this.tileY = 0;
},
outOfBounds: function() {
if (snake.x < 0 || snake.x > tools.canvas.width || snake.y < 0 || snake.y > tools.canvas.height) {
game.gameOver = true;
}
}
}
let fruit = {
x: 0,
y: 0,
size: 20,
fillColor: 'hotpink',
strokeColor: 'black',
drawFruit: function() {
tools.drawRect(this.x, this.y, this.size, this.size, this.fillColor, 'fill', true, this.strokeColor);
},
generateNewFruit: function() {
this.x = Math.floor(Math.random() * 20) * 20;
this.y = Math.floor(Math.random() * 20) * 20;
}
}
let snake = {
x: 0,
y: 0,
size: 20,
color: 'black',
direction: '',
bodySize: 0,
init: false,
tail: [],
drawSnake: function() {
for (let i=0; i < this.bodySize; i++) {
tools.drawRect(this.tail[i].x, this.tail[i].y, this.size, this.size, this.color, 'fill', true, 'lime');
}
tools.drawRect(this.x, this.y, this.size, this.size, this.color, 'fill', true, 'lime');
},
move: function() {
if (this.direction == 'left') {
this.x-=this.size;
}
else if (this.direction == 'up') {
this.y-=this.size;
}
else if (this.direction == 'right') {
this.x+=this.size;
}
else if (this.direction == 'down') {
this.y+=this.size;
}
}
}
let drawEverything = function() {
if (game.gameOver) {
window.cancelAnimationFrame(main);
}
if (snake.x === fruit.x && snake.y === fruit.y) {
fruit.generateNewFruit();
snake.bodySize++;
if (snake.bodySize === snake.tail.length) {
for (let i=0; i < snake.tail.length - 1; i++) {
snake.tail[i] = snake.tail[i+1];
}
}
snake.tail[snake.bodySize-1] = {x: snake.x, y: snake.y};
}
tools.ctx.clearRect(0, 0, tools.canvas.width, tools.canvas.height);
map.drawMap();
map.outOfBounds();
snake.drawSnake();
snake.move();
fruit.drawFruit();
}
let main = function() {
if (game.gameOver) {
game.gameOverMsg("Game Over");
cancelAnimationFrame(main);
return;
} else {
drawEverything();
setTimeout(function() {
requestAnimationFrame(main);
}, 1000/20);
}
}
window.addEventListener('keydown', function(e) {
let key = e.keyCode;
switch(key) {
case 65: snake.direction = 'left';
break;
case 87: snake.direction = 'up';
break;
case 68: snake.direction = 'right';
break;
case 83: snake.direction = 'down';
break;
}
});
</script>
</body>
</html>
Здесь я сдвигаю змею вниз
let drawEverything = function() {
if (game.gameOver) {
window.cancelAnimationFrame(main);
}
if (snake.x === fruit.x && snake.y === fruit.y) {
fruit.generateNewFruit();
snake.bodySize++;
if (snake.bodySize === snake.tail.length) {
for (let i=0; i < snake.tail.length - 1; i++) {
snake.tail[i] = snake.tail[i+1];
}
}
snake.tail[snake.bodySize-1] = {x: snake.x, y: snake.y};
}
tools.ctx.clearRect(0, 0, tools.canvas.width, tools.canvas.height);
map.drawMap();
map.outOfBounds();
snake.drawSnake();
snake.move();
fruit.drawFruit();
}
Здесь я рисую обновленное смещенное внизхвост и змеиная голова
drawSnake: function() {
for (let i=0; i < this.bodySize; i++) {
tools.drawRect(this.tail[i].x, this.tail[i].y, this.size, this.size, this.color, 'fill', true, 'lime');
}
tools.drawRect(this.x, this.y, this.size, this.size, this.color, 'fill', true, 'lime');
}
Я не знаю, является ли это проблемой с моей функцией drawSnake или нет;но по какой-то причине он не хочет рисовать хвостовой массив все вместе как один набор блоков.