Matter.js计算所需力量

13
我正试图向一个物体施加力,使其按照鼠标位置相对于该物体产生的角度移动。我已经有了这个角度。
 targetAngle = Matter.Vector.angle(myBody.pos, mouse.position);

现在我需要施加一个力,以使物体沿着那个角度移动。对于applyForce方法中的下面这些值,我应该输入什么?

  // applyForce(body, position, force)

  Body.applyForce(myBody, {
    x : ??, y : ??
  },{
    x:??, y: ?? // how do I derive this force??
  });

我需要在这里放置x和y值,以便使物体沿着鼠标和物体之间的角度移动。

3个回答

8
你可以依靠 Matter.Vector 模块,用它来减去、标准化和乘以位置向量:
var force = 10;
var deltaVector = Matter.Vector.sub(mouse.position, myBody.position);
var normalizedDelta = Matter.Vector.normalise(deltaVector);
var forceVector = Matter.Vector.mult(normalizedDelta, force);
Body.applyForce(myBody, myBody.position, forceVector);

3
这个答案比brennanenanen的方法更可取,尽管他的方法是正确的,但使用三角函数将角度(反)转换为向量并不是最佳选择。 - isnot2bad

8
为了施加力使您的物体朝某个方向移动,您需要取弧度角的正弦和余弦。您可以将物体的位置作为第一个矢量直接传递,以避免施加扭矩(旋转)。
var targetAngle = Matter.Vector.angle(myBody.pos, mouse.position);
var force = 10;

Body.applyForce(myBody, myBody.position, {
  x: cos(targetAngle) * force, 
  y: sin(targetAngle) * force
});

如果需要的话,applyForce() 的文档在 这里

(我知道这个问题有点老了,但我还是为所有遇到同样问题的人解答一下)


1
这很有帮助,但旋转是什么?他不想将鼠标X和鼠标Y作为方向输入吗?另外,在180之后你错过了一些分号。如果这在维基或示例中就好了。 - Danny Cullen
1
我认为你的“theta”变量与“targetAngle”相同。因此,你只需将目标角度输入“cosine()”和“sine()”函数即可。 - Danny Cullen
theta的值是将targetAngle转换为弧度。 - brennanenanen
1
targetAngleе·Із»ҸжҳҜд»Ҙеј§еәҰдёәеҚ•дҪҚзҡ„ - иҜ·еҸӮиҖғж–ҮжЎЈ http://brm.io/matter-js/docs/classes/Vector.html#method_angle - Danny Cullen

0

计算振幅:您必须在模拟循环中应用力量

关注力的振幅/持续时间部分,重要的是要知道您应该在每个模拟步骤中一次性地施加力量,这可以通过beforeUpdate回调函数完成:

所以类似于:

const moveForce = 0.01
const keysDown = new Set()
const keyHandlers = {
  KeyW: () => {
    Matter.Body.applyForce(boxA, {
      x: boxA.position.x,
      y: boxA.position.y
    }, { x: 0, y: -moveForce } )
  },
  KeyS: () => {
    Matter.Body.applyForce(boxA, {
      x: boxA.position.x,
      y: boxA.position.y
    }, { x: 0, y: moveForce } )
  },
}
document.addEventListener("keydown", event => {
  keysDown.add(event.code)
});
document.addEventListener("keyup", event => {
  keysDown.delete(event.code)
});
Matter.Events.on(engine, 'beforeUpdate', event => {
  ;[...keysDown].forEach(k => {
    keyHandlers[k]?.();
  });
});

这是一个完整的最小可运行示例,它修改了 Matter.js 你好,世界,让你可以使用ASDW键移动其中一个框。

asdw.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ASDW</title>
<script src="node_modules/matter-js/build/matter.min.js"></script>
</head>
<body>
<script>
// module aliases
var Engine = Matter.Engine,
    Render = Matter.Render,
    Runner = Matter.Runner,
    Bodies = Matter.Bodies,
    Composite = Matter.Composite;

// create an engine
var engine = Engine.create();

// create a renderer
var render = Render.create({
    element: document.body,
    engine: engine
});

// create two boxes and a ground
var boxA = Bodies.rectangle(400, 200, 80, 80);
var boxB = Bodies.rectangle(450, 50, 80, 80);
var ground = Bodies.rectangle(400, 610, 810, 60, { isStatic: true });

// add all of the bodies to the world
Composite.add(engine.world, [boxA, boxB, ground]);

// Move boxA with ASDW
const moveForce = 0.01
const keysDown = new Set()
const keyHandlers = {
  KeyW: () => {
    Matter.Body.applyForce(boxA, {
      x: boxA.position.x,
      y: boxA.position.y
    }, { x: 0, y: -moveForce } )
  },
  KeyS: () => {
    Matter.Body.applyForce(boxA, {
      x: boxA.position.x,
      y: boxA.position.y
    }, { x: 0, y: moveForce } )
  },
  KeyA: () => {
    Matter.Body.applyForce(boxA, {
      x: boxA.position.x,
      y: boxA.position.y
    }, { x: -moveForce, y: 0 } )
  },
  KeyD: () => {
    Matter.Body.applyForce(boxA, {
      x: boxA.position.x,
      y: boxA.position.y
    }, { x: moveForce, y: 0 } )
  },
}
document.addEventListener("keydown", event => {
  keysDown.add(event.code)
});
document.addEventListener("keyup", event => {
  keysDown.delete(event.code)
});
Matter.Events.on(engine, 'beforeUpdate', event => {
  ;[...keysDown].forEach(k => {
    keyHandlers[k]?.();
  });
});

// run the renderer
Render.run(render);

// create runner
var runner = Runner.create();

// run the engine
Runner.run(runner, engine);
</script>
</body>
</html>

enter image description here

约束

另一种方法是使用约束,它们会隐式地将力正确地添加到循环中。

特别是有一个鼠标约束助手可用于鼠标用例:如何使用Matter-js Mouse允许仅移动一个物体

鼠标约束非常容易使用,您只需要使用此代码即可:https://github.com/liabru/matter-js/blob/0.19.0/examples/constraints.js#L145

const mouse = Matter.Mouse.create(render.canvas)
const mouseConstraint = Matter.MouseConstraint.create(engine, {
  mouse,
  constraint: {
    // allow bodies on mouse to rotate
    angularStiffness: 0,
    render: {
      visible: false
    }
  }
})
Composite.add(engine.world, mouseConstraint)
render.mouse = mouse;

这使您可以通过单击并拖动它们来拖动任何块。

基于Matter.js hello world的最小可运行示例:

mouse.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>mouse</title>
<script src="node_modules/matter-js/build/matter.js"></script>
</head>
<body>
<script>
// module aliases
var Engine = Matter.Engine,
    Render = Matter.Render,
    Runner = Matter.Runner,
    Bodies = Matter.Bodies,
    Composite = Matter.Composite;

// create an engine
var engine = Engine.create();

// create a renderer
var render = Render.create({
    element: document.body,
    engine: engine
});

// create two boxes and a ground
var boxA = Bodies.rectangle(400, 200, 80, 80);
var boxB = Bodies.rectangle(450, 50, 80, 80);
var ground = Bodies.rectangle(400, 610, 810, 60, { isStatic: true });

// add all of the bodies to the world
Composite.add(engine.world, [boxA, boxB, ground]);

// Add mouse control
const mouse = Matter.Mouse.create(render.canvas)
const mouseConstraint = Matter.MouseConstraint.create(engine, {
  mouse,
  constraint: {
    // allow bodies on mouse to rotate
    angularStiffness: 0,
    render: {
      visible: false
    }
  }
})
Composite.add(engine.world, mouseConstraint)
render.mouse = mouse;

// run the renderer
Render.run(render);

// create runner
var runner = Runner.create();

// run the engine
Runner.run(runner, engine);
</script>
</body>
</html>

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接