1

我目前正在玩狡猾的 js,并用实体对象创建了 2D 自上而下的世界。

当任何固体物体发生碰撞事件时,我希望我的玩家不再能够向所述物体的方向移动(因为有固体物体挡住了它的路径)。

我在网上找到了一些涵盖该主题的教程,但是它们调用的方法和函数已被贬低。

    .onHit("solid", function(from) {
        console.log("ouch");
     }

当我的玩家击中固体时,我可以记录碰撞,但我不知道如何停止运动。

我知道我可以为每次碰撞设置特定的解决方案(例如,顶部边框可以更新 y 以移出特定的顶部碰撞),但是我想要一种通用的方法,以便与任何可靠的结果发生碰撞,导致我的角色无法移动。

当我尝试打电话时,from.x我收到该元素是undefined,而其他元素(例如from.length确实起作用)对我来说没有意义。

或者提供一些与最新狡猾兼容的演示代码?

4

1 回答 1

2

碰撞数据

当我尝试打电话时,from.x我收到该元素是undefined,而其他元素(例如from.length确实起作用)对我来说没有意义。

onHit回调为您提供与hit函数相同的碰撞数据-碰撞结果数组。这就是您可以访问该length属性的原因。

命中 apidocs

返回的碰撞数据将是一个对象数组,其中包含使用的碰撞类型、碰撞的对象以及如果使用的类型是 SAT(使用多边形作为碰撞框),则有一定数量的重叠。


MBR 冲突

我知道我可以为每次碰撞设置特定的解决方案(例如,顶部边框可以更新 y 以移出特定的顶部碰撞),但是我想要一种通用的方法,以便与任何可靠的结果发生碰撞,导致我的角色无法移动。

水平和/或垂直碰撞是我所知道的两个轴对齐边界框之间碰撞的唯一两种情况。AABB 在 Crafty 的碰撞检测中被用作默认值(并且可以通过.mbr()访问)。
您提出的解决方案实际上是解决此类 AABB 冲突的常用方法。

使用箭头键或 WASD 移动绿色播放器。请注意黑色墙壁如何限制运动。

Crafty.init();

Crafty.e("2D, DOM, Color, Fourway, Collision, player")
      .attr({x: 32, y: 32, w: 32, h: 32})
      .color('green')
      .fourway()
      .bind('Moved', function(evt){
        if (this.hit('solid'))
          this[evt.axis] = evt.oldValue;
      });

Crafty.e("2D, DOM, Color, solid, top")
      .attr({x: 0, y: 0, w: 128, h: 1})
      .color('black');
Crafty.e("2D, DOM, Color, solid, bottom")
      .attr({x: 0, y: 127, w: 128, h: 1})
      .color('black');
Crafty.e("2D, DOM, Color, solid, left")
      .attr({x: 0, y: 0, w: 1, h: 128})
      .color('black');
Crafty.e("2D, DOM, Color, solid, right")
      .attr({x: 127, y: 0, w: 1, h: 128})
      .color('black');
<script src="https://github.com/craftyjs/Crafty/releases/download/0.7.1/crafty-min.js"></script>


SAT碰撞

Crafty 中有一个更复杂和更精确的碰撞检测变体,它使用分离轴定理,它适用于任何两个凸多边形。可以通过.collision()指定自定义多边形碰撞框。
类似的解决方案用于解决 SAT 碰撞 - 使用来自碰撞结果的信息将碰撞对象移回。

使用箭头键或 WASD 移动绿色播放器。请注意红线是如何限制移动的,红线代表凸多边形碰撞框。

Crafty.init();

Crafty.e("2D, Fourway, Collision, DOM, Color, WiredHitBox, player")
      .attr({x: 32, y: 32, w: 32, h: 32})
      .collision([0, 16, 16, 0, 32, 16, 16, 32])
      .color('green')
      .fourway()
      .bind('Moved', function(evt) {
        var hitDatas, hitData;
        if ((hitDatas = this.hit('solid'))) {
          // resolving collision for just one collider here and assuming SAT collision
          hitData = hitDatas[0];
          this.x -= hitData.overlap * hitData.normal.x;
          this.y -= hitData.overlap * hitData.normal.y;
        }
      });


Crafty.e("2D, Collision, DOM, Color, WiredHitBox, solid")
      .attr({x: 64, y: 64, w: 64, h: 64})
      .collision([0, 32, 32, 0, 64, 32, 32, 64])
      .color('black');
<script src="https://github.com/craftyjs/Crafty/releases/download/0.7.1/crafty-min.js"></script>


请务必阅读apidocs以获取有关使用的组件和事件的更多信息。

于 2016-03-03T18:29:58.450 回答