Javascript 我的游戏有性能漏洞,我找不到

Javascript 我的游戏有性能漏洞,我找不到,javascript,Javascript,我写了一篇关于这个问题的文章,但意识到它说得不太好,所以我删除了它,我正在使这篇文章更具信息性。不久前我做了这个游戏,它是一个游戏,一个人作为一种颜色玩,收集其他颜色的球,然后得分。您可以在下面用我的工作代码片段播放它。过了一段时间,比如说30秒或45秒,游戏落后了很多,玩得不太好。我到处都查过了,但似乎找不到任何地方可以让我每一帧都重复一些事情,这会让事情变慢。我有没有办法找到性能问题所在 以下是片段: 让ctx=document.getElementById(“can”).getConte

我写了一篇关于这个问题的文章,但意识到它说得不太好,所以我删除了它,我正在使这篇文章更具信息性。不久前我做了这个游戏,它是一个游戏,一个人作为一种颜色玩,收集其他颜色的球,然后得分。您可以在下面用我的工作代码片段播放它。过了一段时间,比如说30秒或45秒,游戏落后了很多,玩得不太好。我到处都查过了,但似乎找不到任何地方可以让我每一帧都重复一些事情,这会让事情变慢。我有没有办法找到性能问题所在

以下是片段:

让ctx=document.getElementById(“can”).getContext(“2d”);
让can=document.getElementById(“can”);
让宽度=罐宽;
让高度=罐的高度;
让disp=document.getElementById(“dis”);
ctx.fillStyle=“黑色”;
ctx.rect(0,0,罐宽,罐高);
ctx.fill();
ctx.font=“30px ComicSans”;
让颜色=[“红”、“绿”、“蓝”];
让Player=function(){
这个x=250;
这个y=400;
this.colornum=0;
这个.xspeed=10;
这个.yspeed=10;
this.pressRight=false;
this.pressLeft=false;
this.pressUp=false;
this.pressDown=false;
这个半径=30;
this.num=0;
this.draw=函数(){
ctx.save();
ctx.beginPath();
ctx.arc(this.x,this.y,this.radius,0,2*Math.PI,false);
ctx.fillStyle=colors[this.colornum];
ctx.fill();
ctx.closePath();
//数字样式
ctx.beginPath();
ctx.fillStyle=“黑色”;
ctx.fillText(this.num,this.x-15,this.y+10);
ctx.fill();
ctx.restore();
}
this.updatePosition=函数(){
如果(此时按右键){
if(此.x+此.radius<罐宽){
this.x+=this.xspeed;
}
}否则如果(此。按左){
如果(this.x-this.radius>0){
this.x-=this.xspeed;
}
}否则,如果(此。按UP){
如果(this.y-this.radius>0){
this.y-=this.y速度;
}
}否则,如果(此。按下){
if(此.y+此.radius<罐高){
this.y+=this.y速度;
}
}
}
this.update=函数(){
this.updatePosition();
这个.draw();
}
}
让实体=函数(){
this.x=Math.floor(Math.random()*500);
this.y=Math.floor(Math.random()*500);
this.colornum=Math.floor(Math.random()*3);
this.xspeed=Math.floor(Math.random()*7);
this.yspeed=Math.floor(Math.random()*7);
this.collide=函数(){
if(this.x>can.width | | this.x<0){
this.xspeed=-this.xspeed;
}
如果(this.y>can.height | | this.y<0){
this.yspeed=-this.yspeed;
}
}
this.updatePosition=函数(){
这个.collide();
this.x+=this.xspeed;
this.y+=this.y速度;
}
this.draw=函数(){
ctx.save();
ctx.beginPath();
ctx.arc(this.x,this.y,20,0,2*Math.PI,false);
ctx.fillStyle=colors[this.colornum];
ctx.fill();
ctx.closePath();
}
this.update=函数(){
this.updatePosition();
这个.draw();
}
}
let player1=新玩家();
设enemylist={};
for(设i=0;i<20;i++){
设id=Math.floor(Math.random()*100);
enemylist[id]=新实体();
}
功能冲突检测(x1、y1、x2、y2){
如果(数学sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1))<(player1.radius+20)){
返回true;
}否则
返回false;
}
函数更新(){
ctx.clearRect(0,0,宽度,高度);
ctx.fillStyle=“白色”;
ctx.rect(0,0800600);
ctx.fill();
for(输入enemylist){
让collided=CollideDetect(enemylist[key].x,enemylist[key].y,player1.x,player1.y);
if(collized&&player1.colornum==enemylist[key].colornum){
player1.半径+=5;
player1.num+=1;
删除enemylist[键];
}else if(已碰撞&&player1.colornum!=enemylist[key].colornum){

如果(player1.num在使用了一些代码之后,我发现了问题

问题 您调用的
disp.innerHTML
太多。垃圾收集器无法跟上它更新dom的次数

因此,如果我们将这段代码移出更新循环,并将其放入自己的
setInterval(…,500)
中,游戏将继续进行,dom也可以继续进行

这使得:

if (Object.keys(enemylist).length == 0) {
  disp.innerHTML = "Game Over";
} else if (Object.keys(enemylist).length != 0) {
  disp.innerHTML = "Start";
}
变成这样:

setInterval(() = > {
  if (Object.keys(enemylist).length == 0) {
    disp.innerHTML = "Game Over";
  } else if (Object.keys(enemylist).length != 0) {
    disp.innerHTML = "Start";
  }
}, 500)
我是怎么找到这个的
在chrome dev工具中运行性能测试时,我看到有800多个节点,但在查看元素时,页面中只有几个元素。然而,
p
元素更新了很多。因此,我们只是降低了更新速度并解决了问题,现在我们将节点数保持在100个以下!

在玩代码的时候,我发现了问题

问题 您调用的
disp.innerHTML
太多。垃圾收集器无法跟上它更新dom的次数

因此,如果我们将这段代码移出更新循环,并将其放入自己的
setInterval(…,500)
中,游戏将继续进行,dom也可以继续进行

这使得:

if (Object.keys(enemylist).length == 0) {
  disp.innerHTML = "Game Over";
} else if (Object.keys(enemylist).length != 0) {
  disp.innerHTML = "Start";
}
变成这样:

setInterval(() = > {
  if (Object.keys(enemylist).length == 0) {
    disp.innerHTML = "Game Over";
  } else if (Object.keys(enemylist).length != 0) {
    disp.innerHTML = "Start";
  }
}, 500)
我是怎么找到这个的 在chrome dev工具中运行性能测试时,我看到有800多个节点,但在查看元素时,页面中只有几个元素。然而,
p
元素更新了很多。因此,我们只是降低了更新速度并解决了问题,现在我们将节点数保持在100个以下!

Remove
ctx.save()
ctx.restore()

在游戏中,它们基本上是无用的,因为你在每次更新时都会清理画布并从头开始重新绘制所有内容。我们不需要在下一帧中保存任何信息

保存到堆栈中的文件包括:

  • 电流变换矩阵
  • 当前剪辑区域
  • 当前的破折号列表
  • 以下属性的当前值:
    • strokeStyle
    • 填充样式