JavaScript中一帧的碰撞检测

时间:2013-08-15 19:05:47

标签: javascript collision craftyjs

我正在玩Crafty.js游戏引擎。我有一个小游戏,玩家是一个球,他下降到平台。每次他打到下一个平台,他都会得到一分。分数存储为变量并显示在屏幕上。我正在使用Crafty的碰撞检测来检测玩家何时遇到新平台。如果你不熟悉Crafty,那很简单,只要玩家遇到新平台,就会触发一个事件,我可以在分数中添加一个。

我的问题: 游戏运行速度约为60fps。每次画布重新加载时,Crafty都会检测玩家是否真正触摸平台。这导致我的得分变量在玩家接触某个等级的每一帧增加1。这远非我想要的。我希望每个平台的分数增加 ONCE 。这是一个我不知道如何解决的问题。

我试图解决的其他问题: 我还考虑不断测量玩家距起点的距离,然后我可以(通过分区)判断玩家所处的平台(因为平台是垂直间隔的)。然而,这是一个问题,因为Crafty在向我提供播放器的当前位置时遇到了问题。

我认为可行的方法:我想如果我可以在播放器击中每个平台的第一帧上触发事件,那么这可能会有效。 (旁注,如果玩家停留在一个平台上并且第二次跳起并落在同一平台上,我只想要添加 ONE 点。不是双跳)

我需要你们这些人:你有过这个问题吗?我真的需要完成这个游戏。而这个小技术问题阻碍了我完成它。我喜欢某些人的输入。

2 个答案:

答案 0 :(得分:0)

最简单的解决方案似乎是为每个平台设置一个变量,用于跟踪玩家是否已登陆该平台。然后,每当球与尚未着陆的平台接触时,奖励一个点并将该平台标记为落地。

如果平台是线性序列,你甚至可以有一个整数变量来跟踪玩家所在的平台。

答案 1 :(得分:0)

我想扩展Taymon的答案,因为它似乎是解决这个问题的一个非常好的解决方案。我只需在平台组件中添加一个布尔属性标志,以确定它是否已被计数。

Crafty.c('Platform', { isCounted: false })

然后,处理该命中的逻辑将在计算之前检查该标志。

这是一个实例:

var score = 0;

Crafty.init(800, 600, $('#game')[0])
Crafty.background('blue')

/**
 * because of the way gravity works
 * (or maybe I just don't really understand it),
 * I had to make separate entities for the
 * gravity and the actual hit testing for each
 * platform.
 **/
Crafty.c('Platform', {
  platform: function(x, y, visId) {
    this.addComponent('2D, DOM')
      .attr({
        h: 20,
        w: 200,
        x: x,
        y: y - 10,
        visId: visId
      });
    return this;
  },
  isCounted: false,
  visId: 0,
  vis: function() {
    return Crafty(this.visId);
  }
});

Crafty.c('PlatformVis', {
  platformVis: function(x, y) {
    this.addComponent('2D, DOM, Color, PlatformVis')
      .color('green')
      .attr({
        h: 20,
        w: 200,
        x: x,
        y: y
      });
    return this;
  }
});


// make some platforms
for (var i = 0; i < 5; ++i) {
  var x = i * 200;
  var y = i * 75 + 92;
  var vis = Crafty.e('PlatformVis').platformVis(x, y)
  Crafty.e('Platform').platform(x, y, vis.getId());
}


// player
Crafty.e('2D, DOM, Color, Twoway, Gravity, Collision')
  .color('red')
  .twoway(6, 14)
  .gravity('PlatformVis')
  .gravityConst(.8)
  .attr({
    x: 0,
    y: 0,
    h: 32,
    w: 32
  })
  .checkHits('Platform')
  .bind('HitOn', function(e) {
    var platform = e[0].obj;
    if (!platform.isCounted) {
      platform.isCounted = true;
      platform.vis().color('yellow');
      Crafty('Score').text(++score);
    }
  }, this);


// score hud
Crafty.e('2D, DOM, Text, Score')
  .text(score)
  .textColor('white')
  .textFont({
    size: '32px'
  });
<script src="https://cdnjs.cloudflare.com/ajax/libs/crafty/0.6.3/crafty-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>Player uses the <b>Twoway</b> component, so use arrows/wasd to move/jump</p>
<div id="game"></div>