首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >JS画布经常获得像素值

JS画布经常获得像素值
EN

Stack Overflow用户
提问于 2015-02-12 02:23:28
回答 2查看 725关注 0票数 0

我正在创建一个基于Node.js/WebGL/画布/PIXI.js的电子游戏。

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

代码语言:javascript
代码运行次数:0
运行
复制
function isWall(x, y):
    return canvas.getImageData(x, y, 1, 1).data[3] != 0;

然而,这是非常缓慢的(根据Chrome分析,它占用了游戏CPU时间的70% )。而且,由于我引入了这个函数,我有时会在没有任何其他建议的情况下得到错误"Oops,WebGL崩溃“。

是否有更好的方法来访问像素的值?我想把所有的东西都存储在一个静态的位数组中(墙有固定的大小),其中一个对应于一个墙,一个对应于一个非墙。在内存中有一个1000万个单元的数组合理吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-02-12 03:34:23

我使用位数组来存储0 \x\ 1信息,它工作得很好。

信息存储紧凑,获取/集非常快。

下面是我使用的位库:

https://github.com/drslump/Bits-js/blob/master/lib/Bits.js

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

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

是一种替代测试数据范围,而不是测试每个像素:

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

代码语言:javascript
代码运行次数: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});

然后,您可以像这样快速测试x,y的运行情况(警告未经测试的代码!):

代码语言:javascript
代码运行次数:0
运行
复制
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);

}

这需要很少的测试,因为x&y准确地指定了需要测试的xRuns和yRuns数组。

它可能(或不可能)比测试“平面”模型更快,因为访问平面模型的指定元素需要开销。你必须使用这两种方法进行测试。

墙壁运行的方法可能需要更少的内存。

希望这个helps...Keep在我的脑海中--墙壁运行的替代方案--刚刚结束,可能需要调整一下;-)

票数 1
EN

Stack Overflow用户

发布于 2015-02-13 21:18:58

一些想法:

  • 首先检查:对所有对象使用碰撞区域。这些区域甚至可以根据形状为每一方定义。复杂的形状)。只检查相交区域内的碰撞。
  • 使用一半分辨率的命中测试位图(甚至25%,如果你的方案允许)。当物体移动时,我们的大脑无法检测像素精确的碰撞,所以这是可以利用的。
  • 对于复杂的形状,预存储整个位图(基于其区域),但将其转换为具有高值和低值的单一值类型数组,如Uint8Array (重复使用此方法,而不是通过上下文获取一个像素)。减去对象的位置,并将结果用作形状区域的增量,然后点击-测试“位图”。如果形状旋转,则相应地转换传入的检查点(这里可能有一个更新位图比转换一组点更快的地方。您需要测试您的场景)。
  • 对于接近正方形的物体,做折中操作,并使用简单的矩形检查。
  • 对于圆和椭圆,使用不平方值来检查半径的距离。
  • 在某些情况下,您也许可以使用在游戏开始之前计算的碰撞预测,以及当知道所有物体的位置、方向和速度时(计算完整的运动路径,找到这些路径的交叉点,计算到这些交叉口的时间/距离)。如果您的对象由于其他事件而改变方向等,这当然不会很好地工作(或者尝试重新计算是否有益)。

我知道为什么你需要10百万存储在内存中,虽然这是可行的,但你需要使用类似四叉树的东西,然后把数组分开,这样才能有效地查找像素状态。IMO您只需要存储复杂形状的“位”,并且可以通过定义每个形状的多个区域来进一步限制它。对于简单的形状,只需使用向量(矩形、半径/距离)。经常进行性能测试以找到正确的平衡。

在任何情况下-这类事情必须手工优化的非常场景,所以这只是一个一般性的看法。其他因素会影响该方法,如高速、旋转、反射等,并且很快就会变得非常广泛。希望这能提供一些投入。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28468202

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档