Javascript JS画布经常获取像素值

Javascript JS画布经常获取像素值,javascript,canvas,webgl,pixi.js,Javascript,Canvas,Webgl,Pixi.js,我正在创建一个基于Node.js/WebGL/Canvas/PIXI.js的视频游戏 在这个游戏中,块有一个通用的大小:它们可以是圆、多边形或任何东西。所以,我的物理引擎需要知道东西到底在哪里,什么像素是墙,什么像素不是。因为我认为PIXI不允许这样做,所以我创建了一个不可见的画布,在那里我放置了地图的所有墙壁图像。然后,我使用函数getImageData在(x,y)处创建函数“isWall”: 然而,这是非常缓慢的(根据Chrome评测,它占用了游戏70%的CPU时间)。此外,由于我引入了这个

我正在创建一个基于Node.js/WebGL/Canvas/PIXI.js的视频游戏

在这个游戏中,块有一个通用的大小:它们可以是圆、多边形或任何东西。所以,我的物理引擎需要知道东西到底在哪里,什么像素是墙,什么像素不是。因为我认为PIXI不允许这样做,所以我创建了一个不可见的画布,在那里我放置了地图的所有墙壁图像。然后,我使用函数getImageData在(x,y)处创建函数“isWall”:

然而,这是非常缓慢的(根据Chrome评测,它占用了游戏70%的CPU时间)。此外,由于我引入了这个函数,有时在没有任何额外建议的情况下出现错误“Oops,WebGL崩溃”


是否有更好的方法访问像素值?我考虑将所有内容存储在一个静态位数组中(墙有固定的大小),1对应于墙,0对应于非墙。内存中有1000万个单元的数组合理吗?

我使用位数组来存储0 | 1信息,效果非常好

信息存储紧凑,获取/设置速度非常快

以下是我使用的位库:

我没有尝试使用10m位,所以您必须在自己的数据集上尝试

您提出的解决方案非常“平坦”,这意味着每个像素必须有相应的位。这导致需要大量内存——即使信息以位的形式存储

替代测试数据范围而不是测试每个像素的方法:

如果墙像素的数量相对于像素总数来说很小,您可以尝试将每面墙存储为一系列“运行”。例如,墙运行可能存储在如下对象中(警告:未测试的代码!):

然后,您可以像下面这样在墙上快速测试[x,y]运行(警告未测试的代码!):

函数isWall(x,y){
如果(x运行[y]){
var a=xRuns[y];
var i=a.长度;
请稍等(我--){
var run=a[i];

如果(x>=run.start&&x=run.start&&y我使用位数组来存储0 | | 1信息,它工作得非常好

信息存储紧凑,获取/设置速度非常快

以下是我使用的位库:

我没有尝试使用10m位,所以您必须在自己的数据集上尝试

您提出的解决方案是非常“平坦”的,这意味着每个像素必须有一个对应的位。这会导致需要大量内存,即使信息是以位的形式存储的

替代测试数据范围而不是测试每个像素的方法:

如果墙像素数相对于总像素数较小,您可以尝试将每面墙存储为一系列“运行”。例如,墙运行可能存储在如下对象中(警告:未测试的代码!):

然后,您可以像下面这样在墙上快速测试[x,y]运行(警告未测试的代码!):

函数isWall(x,y){
如果(x运行[y]){
var a=xRuns[y];
var i=a.长度;
请稍等(我--){
var run=a[i];

如果(x>=run.start&&x=run.start&&y我使用位数组来存储0 | | 1信息,它工作得非常好

信息存储紧凑,获取/设置速度非常快

以下是我使用的位库:

我没有尝试使用10m位,所以您必须在自己的数据集上尝试

您提出的解决方案是非常“平坦”的,这意味着每个像素必须有一个对应的位。这会导致需要大量内存,即使信息是以位的形式存储的

替代测试数据范围而不是测试每个像素的方法:

如果墙像素数相对于总像素数较小,您可以尝试将每面墙存储为一系列“运行”。例如,墙运行可能存储在如下对象中(警告:未测试的代码!):

然后,您可以像下面这样在墙上快速测试[x,y]运行(警告未测试的代码!):

函数isWall(x,y){
如果(x运行[y]){
var a=xRuns[y];
var i=a.长度;
请稍等(我--){
var run=a[i];

如果(x>=run.start&&x=run.start&&y我使用位数组来存储0 | | 1信息,它工作得非常好

信息存储紧凑,获取/设置速度非常快

以下是我使用的位库:

我没有尝试使用10m位,所以您必须在自己的数据集上尝试

您提出的解决方案是非常“平坦”的,这意味着每个像素必须有一个对应的位。这会导致需要大量内存,即使信息是以位的形式存储的

替代测试数据范围而不是测试每个像素的方法:

如果墙像素数相对于总像素数较小,您可以尝试将每面墙存储为一系列“运行”。例如,墙运行可能存储在如下对象中(警告:未测试的代码!):

然后,您可以像下面这样在墙上快速测试[x,y]运行(警告未测试的代码!):

函数isWall(x,y){
如果(x运行[y]){
var a=xRuns[y];
var i=a.长度;
请稍等(我--){
var run=a[i];
如果(x>=run.start&&x=run.start&&y一些想法:

  • 对于第一个检查:对所有对象使用碰撞区域。甚至可以根据形状(即复杂形状)为每一侧定义区域。仅检查相交区域内的碰撞
  • 对命中测试位图使用半分辨率(如果您的场景允许,甚至是25%),我们的大脑无法在物体移动时检测到像素级的碰撞,因此可以利用这一点
  • 对于复杂形状,预存储整个位图(基于其区域),但将其转换为单值类型的数组,如具有高值和低值的Uint8Array(请重新使用)
    function isWall(x, y):
        return canvas.getImageData(x, y, 1, 1).data[3] != 0;
    
    // an object containing all horizontal wall runs
    var xRuns={}
    
    // an object containing all vertical wall runs
    var yRuns={}
    
    // define a wall that runs on y=50 from x=100 to x=185
    // and then runs on x=185 from y=50 to y=225
    var y=50;
    var x=185;
    
    if(!xRuns[y]){ xRuns[y]=[]; }
    
    xRuns[y].push({start:100,end:185});
    
    if(!yRuns[x]){ yRuns[x]=[]; }
    
    yRuns[x].push({start:50,end:225});
    
    function isWall(x,y){
    
        if(xRuns[y]){
            var a=xRuns[y];
            var i=a.length;
            do while(i--){
                var run=a[i];
                if(x>=run.start && x<=run.end){return(true);}
            }
        }
    
        if(yRuns[x]){
            var a=yRuns[x];
            var i=a.length;
            do while(i--){
                var run=a[i];
                if(y>=run.start && y<=run.end){return(true);}
            }
        }
    
        return(false);
    
    }