使用libgdx平滑移动和转动游戏对象

时间:2014-06-30 09:33:59

标签: java scala libgdx

我正在尝试学习一些游戏开发,而我正在回忆一下有关线性代数和矢量数学的一切,我在生活中学到了一些东西,我也开始玩libgdx。

我想要开始的第一件事是一个简单的旋转运动,我想出了如何通过计算从当前方向到所需方向的角度来完成这项工作。虽然它对静止精灵起作用,但是向它添加运动证明它是错误的,因为精灵正在进行U型转弯(不是指向点,而是点的方向)

此示例在Scala中实现https://github.com/pbuda/libgdx-movement。相关代码位于Spaceship类。

仅供快速参考,以下是该课程的主要部分:

def update(delta: Float) {
  rotate(delta)
  move(delta)
}

private def move(delta: Float) {
  velocity.set(direction).scl(movementSpeed)
  position.add(velocity.scl(delta))
}

private def rotate(delta: Float) {
  val current = direction.angle()
  val target = targetDirection.angle()
  if (current != target) {
    val rotateAngle = rotationSpeed * delta
    val left = distance(current, target)
    val right = distance(target, current)
    if (left < right) rotateLeft(current, left, rotateAngle)
    else rotateRight(current, right, rotateAngle)
  }
}

private def distance(start: Float, end: Float): Float = {
  val angle = start - end
  if (angle < 0) angle + 360 else if (angle > 360) angle - 360 else angle
}

private def rotateLeft(current: Float, target: Float, angle: Float) {
  if (target - angle < 0) direction.set(targetDirection)
  else direction.setAngle(direction.angle() - angle)
}

private def rotateRight(current: Float, target: Float, angle: Float) {
  if (target - angle < 0) direction.set(targetDirection)
  else direction.setAngle(direction.angle() + angle)
}

现在,我觉得有一个更清洁的解决方案,使用一些矢量(位置,速度,方向和可能的目的地),但我有点卡住,不知道从哪里去。

我想要一个你可以想象的rts空间游戏中的行为,在为船舶设置目的地后,它会采用那种方式,但不仅仅是切换方向,而是顺利转弯并从鼠标点击完全转到点。

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:0)

您需要有一个标题,定义为以弧度或度数表示的角度。让我们说一个0分直线向上,90分向右,180分直降,剩下270分。

根据您的航向和速度,每次使用基本触发来计算deltaX和deltaY。

找出你的目标位置,并再次使用基本触发来计算从你的船到目标位置的目标航向。

将每个帧的当前航向移向目标航向一小段增量。

如果您在上述过程的某个特定部分遇到问题,请发布MCVE(而非整个项目),以展示您目前所拥有的内容,并且我们将从那里开始。

答案 1 :(得分:0)

我找到了这个页面http://www.euclideanspace.com/,这有助于我理解这应该如何运作。我用矢量代数替换了我的天真实现,这是结果

private def rotate(delta: Float) {
  val targetHeading = destination.cpy.sub(position).nor
  val angle = angleBetween(heading, targetHeading)
  if (angle != 0) {
    if (Math.abs(angle) < rotationSpeed / 50) heading.set(targetHeading)
    else {
      val rotation: Float = Math.max(Math.abs(angle), rotationSpeed) * delta
      if (angle > 0) heading.rotate(rotation)
      else heading.rotate(-rotation)
    }
  }
}

我的问题是在设置目标点时计算了targetHeading(之前的targetDirection),而不是在每个更新循环中更新它(调用rotate)。 angleBetween 方法如下

private def angleBetween(v1: Vector2, v2: Vector2): Float = {
  val result = Math.toDegrees(Math.atan2(v2.y, v2.x) - Math.atan2(v1.y, v1.x)).toFloat
  if (result < -180) result + 360
  else if (result > 180) result - 360
  else result
}

所以它只是计算两个向量之间的角度。重要的是结果在范围内(-180,180)决定了转弯的方向。

现在当船到达目的地时,它开始绕目的地转,但实施停止行为将是微不足道的(只是防范位置)。