javascript 如何冻结/停止机构使用暂停按钮和恢复机构后,在Matter.js?

lnlaulya  于 2023-02-28  发布在  Java
关注(0)|答案(1)|浏览(139)

我为一个叫海盗入侵的游戏设计了一个暂停按钮,我尝试着在他们的位置暂停/冻结身体,然后从他们所处的位置恢复。
我已经使用了setStaticisStatic使用function mousePressed()。但是,他们都显示错误Uncaught TypeError: Matter.Bodies.setStatic is not a function
我是错过了什么,还是这与保存头寸或类似的事情有关?
船是不得不“暂停/冻结”的身体。

function mousePressed(playButton) { // this is my play button which works perfectly
  gameState = "play"
  World.remove(world, playButton)
  World.remove(world, playImage)
}

function mousePressed(pauseButton) { // pause button which gives an error
  Matter.Bodies.setStatic(boats, true)
}
fv2wmkja

fv2wmkja1#

首先,World已被弃用,因此您应该使用Composite.remove而不是World.remove
至于错误,setStaticBody方法,而不是Bodies方法,您可以在每个主体上循环并调用setStaticboats.forEach(e => Matter.Body.setStatic(e, true));,但是根据this issue,如果不实现主体缓存或其他解决方案,您将无法安全地切换静态。
您确定要通过将主体设置为静态来实现暂停吗?这实际上并不暂停模拟--时间在流逝,各种属性可能会以意外的方式继续更改。
由于您使用的是自己的渲染器(p5.js),暂停整个模拟非常简单。您可以在渲染循环中停止调用MJS代码,模拟将暂停。在p5.js中,这可以通过在draw的开头执行布尔检查来完成。或者将draw临时设置为不运行MJS更新的函数(可能会显示一个菜单或"暂停"屏幕)。有关该方法的详细信息,请参见使用p5. js从一个场景过渡到下一个场景。
下面是根据复选框的值在draw()循环中通过早期返回切换暂停的基本示例:

class Ball {
  constructor(x, y, r) {
    const options = {
      restitution: 0.1,
      density: 1.5,
      friction: 1,
    };
    this.body = Matter.Bodies.circle(x, y, r, options);
  }

  draw() {
    const {position: {x, y}, circleRadius: r} = this.body;
    fill("white");
    ellipse(x, y, r * 2);
  }
}

const engine = Matter.Engine.create();
const balls = [...Array(20)].map((_, i) =>
  new Ball(
    50 + ~~(Math.random() * 450),
    50 + ~~(Math.random() * 150),
    ~~(Math.random() * 5) + 10,
  )
);
const walls = [
  Matter.Bodies.rectangle(
    250, 200, 500, 50, {isStatic: true}
  ),
  Matter.Bodies.rectangle(
    250, 0, 500, 50, {isStatic: true}
  ),
  Matter.Bodies.rectangle(
    0, 100, 50, 200, {isStatic: true}
  ),
  Matter.Bodies.rectangle(
    500, 100, 50, 200, {isStatic: true}
  ),
];
const bodies = [...walls, ...balls.map(e => e.body)];
Matter.Composite.add(engine.world, bodies);
let checkbox;

function setup() {
  checkbox = createCheckbox("running?", true);
  checkbox.position(0, 0);
  createCanvas(500, 200);
  noStroke();
}

function draw() {
  if (!checkbox.checked()) { // check for pause
    return;
  }

  background(30, 30, 30, 60);
  balls.forEach(e => e.draw());
  fill(160);

  for (const e of walls) {
    beginShape();
    e.vertices.forEach(({x, y}) => vertex(x, y));
    endShape();
  }

  if (random(2)) {
    Matter.Body.applyForce(
      balls[~~random(balls.length)].body,
      {
        x: random(0, 500),
        y: random(0, 200),
      },
      {
        x: random(-3, 3),
        y: random(-3, 3),
      }
    );
  }

  Matter.Engine.update(engine);
}
body {
  margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.19.0/matter.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.6.0/p5.min.js"></script>

如果要使用鼠标暂停/取消暂停,请将复选框替换为

let running = true;

function mousePressed() {
  running = !running;
}

并在draw函数中测试running

function draw() {
  if (!running) { // check for pause
    return;
  }

  // ... rerender ...
}

我不确定您的代码是否与项目中的代码完全相同,但如最初的帖子所示,如果第二个函数与第一个函数在相同的作用域中,它们将覆盖第一个函数。
p5中的另一个选项是调用noLoop()来暂停draw循环,调用loop()来恢复循环,您可以使用isLooping()来确定调用哪一个。
如果你使用的是内置渲染器,创建一个Runner并使用runner.enabled来切换暂停。
如果只想暂时暂停引擎,请参见engine.enabled
...虽然我相信engine.enabled是指runner.enabled的错别字。我有一个PR可以修复这个错误。
有关暂停内部渲染器的示例,请参见this answer

相关问题