绘制不在画布上的元素 - 昂贵吗?

时间:2016-04-28 02:24:23

标签: javascript html5 canvas

我正在制作一个JavaScript游戏引擎 - demo - 而且我想知道哪些选项在画布上绘制最便宜:

  • 有条件检查物体的x和y坐标是否在高度和宽度范围内。
  • 无论如何绘制对象,尽管很多人都不会出现。

第一个选项需要比较每个对象和每个动画循环的四个或更多变量。我想知道这是否比绘制所有对象更便宜。

实际游戏中会有许多具有x和y坐标的物体,画布以较大的游戏地图为中心围绕人类玩家。

我使用requestAnimationFrame来进行绘制循环。我也没有使用任何框架。

1 个答案:

答案 0 :(得分:0)

GPU会忽略屏幕外的绘图,因此渲染时间更短(嗯 - 不渲染!)。但是,CPU仍然会处理绘图命令,因此屏幕外的图形不会自由"。

但是你的第二次表现很受欢迎。您正在绘制自己路径中的每个圆圈:

ctx.beginPath();
ctx.arc(p.x,p.y,p.r,0,PI2);
ctx.fillStyle=p.color;
ctx.fill();       

在单个(多圈)路径中绘制所有常见颜色的弧线效率更高:

ctx.fillStyle='red';
ctx.beginPath();
for(var i=0;i<len;i++){
    var p=players[i];
    if(p.color=='red'){
        ctx.moveTo(p.x,p.y);
        ctx.arc(p.x,p.y,p.r,0,PI2);
    }
}
ctx.fill();

这是一组高度非优化的性能测试,显示:

  • 使用单独的beginPath路径绘制屏幕上的圈子。
  • 使用单独的beginPath路径绘制离屏圈。
  • 使用每种颜色1个多圈路径绘制屏幕上的圆圈。
  • 使用每种颜色1个多圈路径绘制离屏圆圈。

在我适度的开发计算机上,这些是性能结果:

  • 屏幕/个人路径:1050ms
  • 离屏/个别路径:427毫秒

  • 屏幕/每种颜色一条路径:528毫秒

  • 离屏/每种颜色一条路径:220毫秒

高度非优化的性能测试:

&#13;
&#13;
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;

var colors=['red','green','blue','gold'];
var playersOnscreen=[];
var playersOffscreen=[];
for(var c=0;c<colors.length;c++){
    var color=colors[c];
    for(var p=0;p<100;p++){
        playersOnscreen.push({x:50,y:50,r:10,color:color});
    }
}
for(var c=0;c<colors.length;c++){
    var color=colors[c];
    for(var p=0;p<100;p++){
        playersOffscreen.push({x:-50,y:50,r:10,color:color});
    }
}

var count=100;
var t1=performance.now();
for(var i=0;i<count;i++){ drawIndividualPaths(playersOnscreen); }
var t2=performance.now();
for(var i=0;i<count;i++){ drawIndividualPaths(playersOffscreen); }
var t3=performance.now();
for(var i=0;i<count;i++){ drawColorPaths(playersOnscreen); }
var t4=performance.now();
for(var i=0;i<count;i++){ drawColorPaths(playersOffscreen); }
var t5=performance.now();
alert('onscreen/individual='+parseInt(t2-t1)+', offscreen/individual='+parseInt(t3-t2)+', onscreen/by color='+parseInt(t4-t3)+', offscreen/by color='+parseInt(t5-t4));

function drawIndividualPaths(players){
    var len=players.length;
    var PI2=Math.PI*2;
    for(var i=0;i<len;i++){
        var p=players[i];
        ctx.beginPath();
        ctx.arc(p.x,p.y,p.r,0,PI2);
        ctx.fillStyle=p.color;
        ctx.fill();       
    }
}

function drawColorPaths(players){
    var len=players.length;
    var PI2=Math.PI*2;
    var clen=colors.length;
    for(var c=0;c<clen;c++){
        var color=colors[c];
        ctx.fillStyle=color;
        ctx.beginPath();
        for(var i=0;i<len;i++){
            var p=players[i];
            if(p.color==color){
                ctx.moveTo(p.x,p.y);
                ctx.arc(p.x,p.y,p.r,0,PI2);
            }
        }
        ctx.fill();
    }
}
&#13;
body{ background-color: ivory; }
#canvas{border:1px solid red; margin:0 auto; }
&#13;
<h2>Please wait for perf tests to complete</h2>
<canvas id="canvas" width=300 height=300></canvas>
&#13;
&#13;
&#13;