如何在MatterJS中通过其标签访问主体?



这里有人问过这个问题,但是没有给出答案。

为了澄清这个问题,一旦创建了主体,它就存储在World/Composite中。

问题是,给定一个像这样创建的主体:

Bodies.rectangle(0, 1000, 0, 100, {
isStatic: true,
label: "floor",
friction: 0,
render: {
fillStyle: 'light blue'
},
})

如何使用标签访问正文?(假设身体被添加到世界中)

简单的答案是否定的,没有允许您通过标签检索正文的内置函数。原因是标签不是唯一的,按标签检索一个主体可能会花费很长时间。想象一下,如果有成千上万的尸体……

在任何情况下,如果您仍然希望通过其标签检索正文,您可以这样做,以线性时间搜索正文:

// retrieve all bodies in the world and filter on label
// returns an array containing all bodies that have that label
function getBodiesByLabel(label, world) {
return Composite.allBodies(world).filter(body => body.label === label)
}
const floorBodies = getBodiesByLabel('floor')
floorBodies.forEach(floorBody => console.log(floorBody))

如果你只需要浏览几个body,也没有那么糟糕。

来源:MatterJS GitHub问题图片来源:grantjenkins on GitHub

gfdb的答案是有效的,但它涉及到对每个标签查找的所有主体进行线性搜索,O(n)。正如我在几个评论中提到的,MJS确实提供了一个label属性以方便,但并不声称是一个整体的实体管理解决方案;它只是一个物理引擎库。标签似乎没有任何后备数据结构,这可能是一件好事。严重依赖于这个单一属性似乎是一种反模式,期望MJS在不打算处理实体管理的时候处理实体管理。

因此,使用MJS独立时的一般方法是推出满足您需求的特定于应用程序的实体管理解决方案,或者使用像Phaser这样提供现成解决方案的固执己见的框架。

常用的方法有:

  1. 使用组合模式:编写自己的类并保留MJS主体的字段作为实现细节(对于大多数用例可能可以紧耦合),以及应用程序所需的任何其他数据。根据需要在数据结构中分组,并可选择从基类继承,就像在正常的OOP中一样。

    class Enemy {
    constructor(x, y, width, height, opts) {
    this.body = Matter.Bodies.rectangle(x, y, width, height, opts);
    this.kills = 0;
    this.cooldown = 30;
    // ... other important data that isn't necessarily MJS-related
    }
    update() {...}
    draw() {...}
    ...
    }
    const entities = {
    enemies: [new Enemy(...), ...],
    walls: [...],
    ...
    };
    
  2. 直接使用主体,但将它们放入按标签组织的数组对象中:

    const bodiesByType = {
    walls: [Matter.Bodies.rectangle(), ...],
    enemies: [Matter.Bodies.rectangle(), ...],
    players: [Matter.Bodies.rectangle(), ...],
    ...
    };
    

    …或者甚至跳过对象,通过松散变量名player,walls等查找它们

  3. 对于上述选项可能是过早优化的简单用例,使用gfdb的方法(尽管我不认为选项2有很多工作)。

最新更新