Как оптимизировать игру на Canvas JS
Появились трудности с созданием игры на чистом JS. Реализую собственную змейку) Да, я старомодный, но для меня это уже достижение.
В чем вопрос, я в массив добавляю хвост и первым элементом массива змейки является голова змейки. Когда я отрисовываю змейку, будь то через setInterval, или же через requestAnimation, при большом количестве точек хвоста, фпс значительно падает. Ребят, я хочу максимальную оптимизацию, спасайте )))
Код:
const c = document.getElementById("ctx");
c.width = 700;
c.height = 500;
const ctx = c.getContext("2d");
function random(max, v = 0, ) {
let r = Math.floor(Math.random() * max);
if (v === 1 && r % 5 !== 0 || r % 10 === 0 && v === 1) {
r = random(max, 1)
}
return r;
}
function Snake() {
this.Ox = 10, // Направление змейки
this.Oy = 0;
this.speed = 10;
this.r = 5, // Радиус и длина змейки
this.length = [{
"x": 5,
"y": 5,
"color": "black"
}];
this.lastX,
this.lastY;
this.head = null;
}
Snake.prototype.add = function() {
let num = this.length.length;
this.length[num] = {
"x": 0,
"y": 0,
"color": "silver"
}
}
Snake.prototype.move = function() {
if (this.length[0].x === c.width - this.r && this.Ox === this.speed) {
this.Ox = 0;
} else if (this.length[0].x === 0 + this.r && this.Ox === -this.speed) {
this.Ox = 0;
} else if (this.length[0].y === c.height - this.r && this.Oy === this.speed) {
this.Oy = 0;
} else if (this.length[0].y === 0 + this.r && this.Oy === -this.speed) {
this.Oy = 0;
}
// for (let i = 0; i < this.length.length; i++) {
// if (i !== 0) {
// if (this.length[0].x === this.length[i].x && this.length[0].y === this.length[i].y) {
// this.Oy = 0;
// this.Ox = 0;
// }
// }
// }
for (let i = this.length.length - 1; i >= 0; --i) {
if (i === 0) {
this.length[i].x += this.Ox;
this.length[i].y += this.Oy;
} else {
this.length[i].x = this.length[i - 1].x;
this.length[i].y = this.length[i - 1].y;
}
ctx.fillStyle = this.length[i].color;
ctx.beginPath();
ctx.arc(this.length[i].x, this.length[i].y, this.r, 0, 2 * Math.PI)
ctx.fill();
}
}
let s = new Snake();
let x = random(c.width, 1, s.length),
y = random(c.height, 1, s.length);
function direction(l = 0, r = 0, u = 0, d = 0) {
if (l === 1) {
if (s.Ox === 0) {
s.Ox = -s.speed;
}
s.Oy = 0;
} else if (r === 1) {
if (s.Ox === 0) {
s.Ox = s.speed;
}
s.Oy = 0;
} else if (u === 1) {
if (s.Oy === 0) {
s.Oy = -s.speed;
}
s.Ox = 0;
} else if (d === 1) {
if (s.Oy === 0) {
s.Oy = s.speed;
}
s.Ox = 0;
}
}
document.addEventListener("keydown", (e) => {
switch (e.keyCode) {
case 83:
direction(0, 0, 0, 1);
break;
case 87:
direction(0, 0, 1, 0);
break;
case 65:
direction(1, 0, 0, 0);
break;
case 68:
direction(0, 1, 0, 0);
break;
case 82:
for (let i = 0; i < 1000; i++) {
s.add()
}
}
})
function bot() {
if (s.length[0].x < x) {
if (s.Ox === -s.speed) {
direction(0, 0, 1, 0);
}
direction(0, 1, 0, 0);
}
if (s.length[0].x > x) {
if (s.Ox === s.speed) {
direction(0, 0, 1, 0);
}
direction(1, 0, 0, 0);
}
if (s.length[0].y > y) {
if (s.Oy === -s.speed) {
direction(0, 1, 0, 0);
}
direction(0, 0, 1, 0);
}
if (s.length[0].y < y) {
if (s.Ox === s.speed) {
direction(0, 1, 0, 0);
}
direction(0, 0, 0, 1);
}
}
function apple() {
if (s.length[0].x === x && s.length[0].y === y) {
x = random(c.width, 1);
y = random(c.height, 1);
s.add();
}
for (let i = 0; i < s.length.length; i++) {
if (s.length[0].y === x && s.length[0].x === y) {
x = random(max, 1);
y = random(c.height, 1);
}
}
ctx.fillStyle = "black";
ctx.beginPath();
ctx.arc(x, y, 5, 0, 2 * Math.PI)
ctx.fill();
}
// setInterval(() => {
// ctx.fillStyle = "white";
// ctx.fillRect(0, 0, c.width, c.height);
// apple()
// bot();
// s.move();
// }, 40);
function anim() {
window.requestAnimationFrame(() => {
ctx.fillStyle = "white";
ctx.fillRect(0, 0, c.width, c.height);
apple()
bot();
s.move();
anim();
});
}
anim();
<canvas id="ctx"></canvas>