Matter.js 如何制作一个正确落地的盒子?

Posted

技术标签:

【中文标题】Matter.js 如何制作一个正确落地的盒子?【英文标题】:Matter.js How can I make a box that is correctly landing? 【发布时间】:2022-01-01 15:34:59 【问题描述】:

我通过 Matter.js 创建了如下两个矩形

我正在尝试将“a”框移到“b”框上方。

我想我此时应该写applyForce,如何计算合适的X、Y Force值来放入因子?

下面的代码是由粗略的近似值组成的代码。我如何计算它的适应性?

var Engine = Matter.Engine,
  Render = Matter.Render,
  Bodies = Matter.Bodies,
  Body = Matter.Body,
  Composite = Matter.Composite,
  Runner = Matter.Runner;

var canvas = document.createElement('canvas'),
  context = canvas.getContext('2d');
var bodies = [];
canvas.width = 500;
canvas.height = 200;
var count = 0;
document.body.appendChild(canvas);
var engine = Engine.create();
var render = Render.create(
    canvas: canvas,
  engine: engine,
  options: 
    width: canvas.width,
    height: canvas.height,
    showAngleIndicator: true,
    showCollisions: true,
    showVelocity: true
  
)
var world = engine.world

Render.run(render)
var runner = Runner.create();
Runner.run(runner, engine)

Composite.add(world, Bodies.rectangle(250, 180, 500, 20,  isStatic: true ));
// random position
var b = Bodies.rectangle(200, 80, 50, 25,  isStatic: true );
Composite.add(world, b);

var a = Bodies.rectangle(50, 50, 30, 30);
Composite.add(world, a);

setTimeout(function() 
    // how to calculate it???
    Body.applyForce(a, a.position, x: 0.012, y: -0.032);
, 1000)
<script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.17.1/matter.min.js"></script>

【问题讨论】:

我很困惑......当我运行代码 sn-p 时,它似乎做了你想要的。究竟是什么你要求/你的代码不符合你的喜好? 是的,代码可以正常工作。但是代码中使用的力是硬编码的。我只想知道当目标位置发生变化时如何计算力值。 哦,有道理,我看看我以后能不能解决这个问题 我想知道你尝试了什么? ...看起来您只是绘制了框,但您的代码没有尝试计算,您是否查看了 matter-js 代码? ...在我下面的回答中,我指出这是一个大问题,您需要先将其分解并回答较小的问题 理解力是硬编码的。它是恒定的引力。如果您想获得这种逼真的效果,力将始终垂直指向并且始终保持恒定大小。要执行跳跃,您需要通过适当计算的初始速度添加动量。为此,您需要解决以下问题:给定第一个盒子的位置和您希望它着陆的位置,计算允许盒子从一个位置跳到另一个位置的初始速度的大小和角度。 【参考方案1】:

我不认为这里有很多matter.js专家:https://***.com/questions/tagged/matter.js?tab=Newest 看看带有那个标签的问题,只有几个,而且很多都没有答案......

项目的所有者:https://github.com/liabru 最近不太活跃,所以你唯一的选择是对那里发生的事情进行逆向工程,好在代码是开源的。

现在回答你的问题

如果我理解正确,您对原力进行了硬编码:Body.applyForce(a, a.position, x: 0.012, y: -0.032) 并且您正在寻找一种方法来计算这些值,而不是仅仅对其进行硬编码。

我正在使用该代码来查看它的行为,在增加框“A”的大小并施加相同​​的力之后,它并没有超过框“B”,所以有一个隐藏的重量/质量这里没有明确定义的组件,显然与这些框的大小相关。

var Bodies = Matter.Bodies
var Body = Matter.Body
var Composite = Matter.Composite

var canvas = document.createElement('canvas')
canvas.width = canvas.height = 200;
var context = canvas.getContext('2d')
document.body.appendChild(canvas)

var engine = Matter.Engine.create()
var runner = Matter.Runner.create()
Matter.Render.run(Matter.Render.create(
  canvas: canvas,
  engine: engine,
  options: 
    width: canvas.width,
    height: canvas.height,
    showAngleIndicator: true,
    showVelocity: true
  
))
Matter.Runner.run(runner, engine)

Composite.add(engine.world, Bodies.rectangle(250, 180, 500, 20,  isStatic: true ))
Composite.add(engine.world, Bodies.rectangle(200, 80, 50, 25,  isStatic: true ))
var a = Bodies.rectangle(50, 130, 40, 40)
Composite.add(engine.world, a)

setTimeout(function() 
  Body.applyForce(a, a.position,  x: 0.012, y: -0.032 )
, 2000)
<script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.17.1/matter.min.js"></script>

牛顿第二定律:

合力等于质量乘以加速度F = M * A

加速度和速度

最终速度等于初始速度加上加速时间经过的时间Vf = Vi + A * T


Matter.js 是一个 2D 物理引擎,要创建逼真的体验,它必须在代码中包含这些内容,您需要确定它们如何/在何处设置这些(质量、加速度和速度)并开始解决这个问题。

期待大量阅读,如果您不记得您的物理抛射运动课程,那么您就可以重新振作起来了。

开始回答简单的问题,试着计算如下:

盒子的质量如何计算? x 移动 100px 需要多大的力? 在 y 轴上跳跃 100 像素需要多大的力?

一旦你正确掌握了这些,你就可以开始结合跳跃和移动


这里有一些关于引擎使用的技术的文档: https://github.com/liabru/matter-js/wiki/References

从代码中可以看出,这就是魔法发生的地方:https://github.com/liabru/matter-js/blob/master/src/body/Body.js#L642-L644

// update velocity with Verlet integration
body.velocity.x = (velocityPrevX * frictionAir * correction) + (body.force.x / body.mass) * deltaTimeSquared;
body.velocity.y = (velocityPrevY * frictionAir * correction) + (body.force.y / body.mass) * deltaTimeSquared;

我正在对代码进行一些挖掘,这就是我得到的:https://heldersepu.github.io/hs-scripts/html/matter-js.html

在这里,我正在计算给定力的跳跃高度, 计算如下:

var force = 1 // change this to the value you need
var frictionAir = 0.99
var gravityScale = 0.001
var deltaTimeSquared = Math.pow((1000 / 60), 2)
var gravity = a.mass * gravityScale
var netForce = force + gravity

var velocity = (netForce / a.mass) * deltaTimeSquared
var height = 0
do 
  height += velocity
  velocity = velocity * frictionAir + (gravity / a.mass) * deltaTimeSquared
 while (velocity < -0.05)

console.log(height) // this is the height of the jump

我从阅读和调试matter-js中得到了所有这些

摩擦空气https://github.com/liabru/matter-js/blob/master/src/body/Body.js#L638 gravityScalehttps://github.com/liabru/matter-js/blob/master/src/core/Engine.js#L266 deltaTimeSquaredhttps://github.com/liabru/matter-js/blob/master/src/body/Body.js#L635 https://github.com/liabru/matter-js/blob/master/src/core/Engine.js#L92

全面披露

我以前从未使用过Matter.js,这是我第一次使用它... 这是一个复杂的问题,我的目标不是花几个小时(可能是几天)给你最终的公式/函数来计算你需要什么,而是向你展示如何在下次遇到某些事情时以这种方式解决这个问题类似的,你知道从哪里开始。

【讨论】:

以上是关于Matter.js 如何制作一个正确落地的盒子?的主要内容,如果未能解决你的问题,请参考以下文章

厉害!84 行 JavaScript 代码实现塔式堆叠游戏

Matter.js设置碰撞规则

使用 Phaser3+Matter.js 实现“合成大西瓜”游戏

如何用 PixiJS 渲染 SVG?

如何用java中的星号制作盒子?嵌套循环?

在 Phaser 3 中更改场景的问题