Почему мои бои стремятся к мировому происхождению, когда соответствуют скорости?
У меня проблема с реализацией псевдокода Конрада Паркера.
Я реализую правило1, правило2 и правило3. Проблема в том, что всякий раз, когда правило 3 активно (то есть matchSpeed в моем коде ниже), боиды стремятся к центру мира (0, 0, 0), а затем стекаются вокруг этого места. Это происходит независимо от того, где они начинаются в мире.
Но когда rule3 не работает, boids стекаются и дрейфуют, как и ожидалось. Что я делаю неправильно?
Мой код написан на Scala, и я использую jMonkeyEngine, но я подозреваю, что проблема носит общий характер.
val sepDistance = 10f
val clumpFactor = 100f
val avoidFactor = 3f
val alignFactor = 800f
val speedLimit = 2f
def moveAgents(target: Node)
{
agents.foreach(a => {
a.velocity.addLocal(clump(a)) //rule1
a.velocity.addLocal(keepAway(a)) //rule2
a.velocity.addLocal(matchSpeed(a)) //rule3
a.velocity = limitSpeed(a.velocity)
a.move(a.velocity)
})
}
def clump (a: Agent): Vector3f = // rule1
{
val centre = Vector3f.ZERO.clone
for (oA <- agents if oA != a) yield
centre.addLocal(oA.position)
centre.divideLocal(agents.length.toFloat - 1f)
centre.subtractLocal(a.position)
centre.divideLocal(clumpFactor)
return centre
}
def keepAway (a: Agent): Vector3f = // rule2
{
val keepAway = Vector3f.ZERO.clone
for (oA <- agents if oA != a) {
if (Math.abs(oA.position.distance(a.position)) < sepDistance)
keepAway.subtractLocal(oA.position.subtract(a.position))
}
return keepAway.divide(avoidFactor)
}
def matchSpeed (a: Agent): Vector3f = // rule3
{
val matchSpeed = Vector3f.ZERO.clone
for (oA <- agents if oA != a)
matchSpeed.addLocal(oA.velocity)
matchSpeed.divideLocal(agents.length.toFloat - 1f)
matchSpeed.subtractLocal(a.position)
matchSpeed.divideLocal(alignFactor)
return matchSpeed
}
1 ответ
Решение
Проблема состоит в том, что метод matchSpeed вычитает положение фокального стержня из средней скорости, а не его скорости.
Так:
matchSpeed.subtractLocal(a.position)
Должно быть:
matchSpeed.subtractLocal(a.velocity)