你如何通过 MatterJS 中的标签访问 body?

How do you access a body by its label in MatterJS?

有人问了这个问题here,但没有给出答案。

为了澄清问题,一旦创建了 body,它就会存储在 World/Composite 中。

问题是,假设 body 是这样创建的:

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

如何使用标签访问 body? (假设 body 被添加到世界)

简单的回答是否定的,没有允许您通过标签检索正文的内置函数。原因是因为标签不是唯一的并且通过标签检索主体可能需要很长时间。想象一下,如果有成千上万的尸体...

无论如何,如果您仍想通过标签检索尸体,您可以这样做以在线性时间内搜索尸体:

// 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))

如果你只有几具尸体可以看,那还不错。

来源:MatterJS GitHub Question 信用:grantjenkins GitHub

works, but it involves a linear search over all bodies for each label lookup, O(n). As I mentioned in a couple of comments,MJS 确实提供了 label 属性 为了方便起见,但并不声称是一个整体的实体管理解决方案;它只是一个物理引擎库。标签似乎没有任何支持数据结构,这可能是一件好事。严重依赖于这个单一的字符串 属性 似乎是一种反模式,期望 MJS 在不希望的时候处理实体管理。

因此,独立使用 MJS 时的一般方法是推出您自己的 application-specific 满足您需求的实体管理解决方案,或者使用像 Phaser 这样提供 off-the-shelf 解决方案的固执己见的框架。

一些常见的方法是:

  1. 使用组合模式:编写你自己的类并保留MJS主体的字段作为实现细节(可能是tightly-coupled 对于大多数用例),以及您的应用程序所需的任何其他数据。根据需要对数据结构进行分组,并可选择像普通 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(), ...],
      ...
    };
    

    ...甚至跳过对象并通过松散变量名称 playerwalls 等查找它们

  3. 将 gfdb 的方法用于上述选项可能是过早优化的简单用例(尽管我认为选项 2 的工作量不大)。