【问题标题】:How do you access a body by its label in MatterJS?您如何通过 MatterJS 中的标签访问正文?
【发布时间】:2022-07-31 05:50:23
【问题描述】:

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

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

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

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

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

【问题讨论】:

    标签: javascript matter.js


    【解决方案1】:

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

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

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

    【讨论】:

      【解决方案2】:

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

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

      几种常见的方法是:

      1. 使用 composition 模式:编写自己的类并将 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. 直接使用body,但是将它们放入一个按标签组织的数组对象中:

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

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

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

      【讨论】:

      • 感谢您提供一种绕过它的方法,但我觉得奇怪的是,您竟然对@bonvee99 提出的原始问题发表评论,评论我的问题副本告诉我要投票给另一个而不是问一个新的,在 github 上评论这个问题,然后只有在我发布答案后才来回答这个问题。都没有赞成我的问题或@bonvee99s?我不明白,但无论如何,谢谢你的回答,我希望它对某人有所帮助。
      • 我在 GH 和这里查看 MJS 标签并回复我觉得有趣或被问到的问题。旧问题没有答案,如果您有相同的问题并发现它有用,通常的方法是不要重新提出问题。但是既然这已经发生并且新问题已经得到解答(这是一个稍微好一点,更普遍的问题),我决定这将是两者之间的规范线程,希望我们可以关闭那个作为骗子,一旦这个问题得到点赞或回答。
      • 我很高兴支持这个问题,这个问题问得好,前提是合理的。然而,犹豫是正如我在另一个 SO 线程和 GH 问题上评论的那样,它闻起来像 XY problem。这两个问题都没有为应用程序是什么或应该实现什么行为标签搜索提供上下文。我的这个答案的目标是让人们远离标签对识别实体很有用的想法,或者 MJS 根本没有规定的实体管理系统。
      • 无论如何,感谢您的回复。这个标签中的大多数人(以及一般情况下都是如此)从不回应澄清请求,就像在另一个线程中发生的那样,这就是为什么我从来没有回答那个问题。另外,有一段时间我真的不确定是否没有内置的按标签搜索的方法,但你在 GH 线程中的研究和对文档的梳理让我确信没有。
      • 我强烈同意这是一个 XY 问题,好眼力。正是出于这个原因,我最终重新编写了我的代码,以避免需要一起搜索主体。很高兴看到这个标签,因为关于这个包的问题并不多,而且文档不是最好的。不客气,也谢谢你。
      猜你喜欢
      • 2017-11-28
      • 2015-04-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-21
      • 1970-01-01
      • 2017-08-29
      • 1970-01-01
      相关资源
      最近更新 更多