【发布时间】:2021-05-05 19:57:05
【问题描述】:
我正在用java脚本(一个光线投射器)制作一个游戏,它真的很慢,因为有很多嵌套的for循环和间隔,有很大的数组,有没有办法优化它,如果有,会吗当我开始做更大的数学来计算线-线交点时仍然很慢,我只是不认为我以最好的方式这样做。
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
</head>
<body>
<canvas width="500px" height="500px" id="c"></canvas>
</body>
<script>
c = document.getElementById("c");
w = c.width;
h = c.height;
ctx = c.getContext("2d");
var tilesize = 50;
var walls = [];
var player = {
x: 80,
y: 80,
size: 10,
speed: 1,
dir: 0,
rot: 0,
rotSpeed: 0.05,
rotDir: 0,
}
var map = [
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1, ],
[1, 0, 1, 1, 0, 0, 0, 0, 0, 1, ],
[1, 0, 1, 1, 0, 0, 0, 0, 0, 1, ],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1, ],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1, ],
[1, 0, 0, 0, 0, 0, 1, 0, 0, 1, ],
[1, 0, 0, 0, 0, 0, 1, 0, 0, 1, ],
[1, 0, 0, 0, 0, 0, 1, 0, 0, 1, ],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ]
]
function keydown(event) {
switch (event.keyCode) {
case 87:
player.dir = 1;
break;
case 83:
player.dir = -1;
break;
case 68:
player.rotDir = -1;
break;
case 65:
player.rotDir = 1;
break;
}
}
function keyup(event) {
switch (event.keyCode) {
case 87:
player.dir = 0;
break;
case 83:
player.dir = 0;
break;
case 68:
player.rotDir = 0;
break;
case 65:
player.rotDir = 0;
break;
}
}
var gameloop = setInterval(function() {
ctx.clearRect(0, 0, w, h);
//move
rotstep = player.rotSpeed * player.rotDir
movestep = player.speed * player.dir;
player.rot += rotstep;
newY = player.y - Math.cos(player.rot) * movestep;
newX = player.x - Math.sin(player.rot) * movestep;
leftbY = (player.y - 10) - Math.cos(player.rot) * movestep;
leftbX = (player.x - 10) - Math.sin(player.rot) * movestep;
rightbY = (player.y + 10) - Math.cos(player.rot) * movestep;
rightbX = (player.x + 10) - Math.sin(player.rot) * movestep;
//borders
var leftcol = Math.floor((leftbX) / tilesize)
var leftrow = Math.floor((leftbY) / tilesize)
var rightcol = Math.floor((rightbX) / tilesize)
var rightrow = Math.floor((rightbY) / tilesize)
if (map[rightcol][rightrow] == 0 && map[leftcol][leftrow] == 0) {
player.y = newY;
player.x = newX;
}
//map
for (y = 0; y < map.length; y++) {
for (x = 0; x < map[y].length; x++) {
if (map[y][x] == 1) {
var wallSeg = {
coordX: x * tilesize,
coordY: y * tilesize,
sizeX: tilesize,
sizeY: 0,
}
var wallSeg2 = {
coordX: x * tilesize,
coordY: y * tilesize,
sizeX: 0,
sizeY: tilesize,
}
var wallSeg3 = {
coordX: x * tilesize,
coordY: (y * tilesize) + tilesize,
sizeX: tilesize,
sizeY: 0,
}
var wallSeg4 = {
coordX: (x * tilesize) + tilesize,
coordY: y * tilesize,
sizeX: 0,
sizeY: tilesize,
}
walls.push(wallSeg)
walls.push(wallSeg2)
walls.push(wallSeg3)
walls.push(wallSeg4)
}
}
}
for (i = 0; i < walls.length; i++) {
var currentwall = walls[i]
ctx.strokeStyle = "black"
ctx.beginPath()
ctx.moveTo(currentwall.coordX, currentwall.coordY);
ctx.lineTo((currentwall.coordX) + currentwall.sizeX, (currentwall.coordY) + currentwall.sizeY);
ctx.stroke();
}
//player
markerY = player.y - Math.cos(player.rot) * 30;
markerX = player.x - Math.sin(player.rot) * 30;
ctx.fillStyle = "red";
ctx.beginPath();
ctx.ellipse(player.x, player.y, player.size, player.size, player.rot * (Math.PI / 180), 0, 2 * Math.PI);
ctx.fill();
//marker
ctx.beginPath();
ctx.moveTo(player.x, player.y)
ctx.lineTo(markerX, markerY)
ctx.strokeStyle = "Blue"
ctx.stroke();
}, 1000 / 30)
document.addEventListener("keydown", function(event) {
keydown(event);
})
document.addEventListener("keyup", function(event) {
keyup(event);
})
</script>
</html>
【问题讨论】:
-
WebWorkers 可能是一个很好的用例。生成进程以在主进程处理 UI 时进行计算和报告结果。先看看example
-
这里是一个相关项目:github.com/ercang/raytracer-js
-
你需要在每个游戏循环中做所有
walls的事情吗,你不能一开始就做一次吗?此外,您似乎一直在每个游戏循环都附加到walls数组而没有清除它,使其变得越来越大。
标签: javascript html performance optimization canvas