JavaScript中一帧的冲突检测

Collision detection for one frame in JavaScript

本文关键字:一帧 冲突检测 JavaScript      更新时间:2023-09-26

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

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

我试图解决的其他问题:我还考虑不断测量玩家离起点的距离,然后我可以(通过划分)告诉玩家在哪个平台上(因为平台垂直间隔相等)。然而,这是一个问题,因为Crafty在给我球员的当前位置时遇到了问题。

我认为可行的方法:我想如果我可以在玩家击中每个平台的第一帧启动一个事件,那么这可能可行。(旁注,如果玩家停留在一个平台上,第二次跳上并降落在同一平台上,我只想添加一个点。而不是双跳)

我需要你们做什么:你们有过这个问题吗?我真的需要完成这场比赛。这个小技术问题使我无法完成它。我希望有人能提供意见。

最简单的解决方案似乎是为每个平台设置一个变量,跟踪玩家是否已登录该平台。然后,每当球接触到一个还没有落地的平台时,奖励一分,并将该平台标记为落地。

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

我想扩展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>