matter.js 中我自己的模型

问题描述 投票:0回答:2

我正在使用 Matter.js 编写一个简单的游戏。我无法弄清楚如何最好地将我的模型挂接到 Matter.js 中。

我的游戏以细菌为特色,我想上一堂课

Bacterium
,这样我就可以管理这些家伙。在我当前的实现中,此类创建并存储它自己的
Matter.Body
,我将其传递给引擎。这就是我遇到麻烦的地方。当细菌相互碰撞以及与墙壁碰撞时,我想更新模型的某些方面,但我找不到有效的方法来定位模型中的哪些细菌在物质碰撞处理程序中发生碰撞。

我应该扩展

Matter.Body
的原型来做到这一点吗?我应该看看网上有什么建议或更大的项目吗?

javascript matter.js
2个回答
2
投票

看一下

Render.collisions
类中的
Render.js
函数。该函数渲染正在渲染的帧中发生的所有碰撞。我认为通过了解他们如何在那里呈现它,您可以弄清楚您在情况下需要什么。

请记住,matterjs 使用游戏循环,这与网页通常使用的基于事件的设置非常不同。查看

Render.js
类,以更好地了解如何使用 Matterjs 提供的引擎。


0
投票

不要扩展不属于您的原型。将 MJS 主体添加为类中的字段是一种很好的方法,您可以使用

Map
将每个 MJS 主体与其对应的类实例关联起来,跟踪哪些主体发生碰撞。

这是一个挂钩

collisionStart
collisionEnd
MJS 事件以调用在 MJS 主体上组成的自定义类上的方法的示例。

class Box {
  constructor(x, y, w, h, bodyOpts) {
    // composition, not inheritance
    this.body = Matter.Bodies.rectangle(
      x, y, w, h, {
        ...bodyOpts,
        render: {fillStyle: "green"}
      },
    );

    // ... other properties relevant to your app ...
  }

  highlight() {
    this.body.render.fillStyle = "red";
  }
  unhighlight() {
    this.body.render.fillStyle = "green";
  }
}

const engine = Matter.Engine.create();
engine.gravity.y = 0; // enable top-down
const map = {width: 300, height: 300};
const render = Matter.Render.create({
  element: document.body,
  engine,
  options: {...map, wireframes: false},
});
const rnd = n => ~~(Math.random() * n);
const boxes = [...Array(40)].map(() => new Box(
  rnd(map.width),  // x
  rnd(map.height), // y
  rnd(10) + 15,    // w
  rnd(10) + 15,    // h
  {angle: rnd(Math.PI * 2)}
));
const walls = new Set([
  Matter.Bodies.rectangle(
    0, map.height / 2, 20, map.height, {isStatic: true}
  ),
  Matter.Bodies.rectangle(
    map.width / 2, 0, map.width, 20, {isStatic: true}
  ),
  Matter.Bodies.rectangle(
    map.width, map.height / 2, 20, map.height, {isStatic: true}
  ),
  Matter.Bodies.rectangle(
    map.width / 2, map.height, map.width, 20, {isStatic: true}
  ),
]);
const mouseConstraint = Matter.MouseConstraint.create(
  engine, {element: document.body}
);
Matter.Composite.add(engine.world, [
  ...boxes.map(e => e.body), ...walls, mouseConstraint
]);
const bodiesToBoxes = new Map(boxes.map(e => [e.body, e]));

Matter.Events.on(engine, "collisionStart", event => {
  for (const {bodyA, bodyB} of event.pairs) {
    if (bodiesToBoxes.has(bodyA)) {
      bodiesToBoxes.get(bodyA).highlight();
    }

    if (bodiesToBoxes.has(bodyB)) {
      bodiesToBoxes.get(bodyB).highlight();
    }
  }
});
Matter.Events.on(engine, "collisionEnd", event => {
  for (const {bodyA, bodyB} of event.pairs) {
    if (bodiesToBoxes.has(bodyA)) {
      bodiesToBoxes.get(bodyA).unhighlight();
    }

    if (bodiesToBoxes.has(bodyB)) {
      bodiesToBoxes.get(bodyB).unhighlight();
    }
  }
});
Matter.Render.run(render);
Matter.Runner.run(Matter.Runner.create(), engine);
<script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.20.0/matter.min.js"></script>

Body.label
属性可以帮助区分主体类型,但最终 MJS 不提供除此之外的任何类型的实体管理解决方案。我警告不要过度依赖
.label
。最终,您可以选择适合您的应用程序需求的设计。

© www.soinside.com 2019 - 2024. All rights reserved.