2015-07-01 4 views
1

Я пытаюсь заставить игрока вращаться и сталкиваться с целевой позицией, и столкнулся с проблемой, которую я не могу исправить.Libgdx, вращающийся к углу с Vector2s

Когда корабль вращается в направлении целевого положения, когда он достигает непосредственно под целевым положением, он сходит с ума и движется влево и вправо, идя вниз (вдали от позиции цели) и в конечном итоге от экрана.

Я не хочу ограничивать экран, поскольку он будет выглядеть странным, когда он медленно вращается, если он находится вблизи предела экрана. В этом случае, если я ограничу экран, он все равно застрянет внизу, поскольку он продолжает поворачиваться влево и вправо. Я загрузил изображение на imgur, чтобы попытаться лучше объяснить мою проблему.

Желтый корабль направления движения (он вращается в направлении целевого положения, но пересекает красную линию), зеленый - это воображаемый вектор в направлении целевого положения, красный - другой воображаемый вектор, который представляет всякий раз, когда корабль сходит с ума. Когда зеленая линия идет вверх по красной линии, корабль начинает выходить из строя и выходить на экран.

public void ai() { 
    switch (playerArrived()) { 
     case 0: 
      break; 
     case 1: 
      pTargetPos.set(ran(0, Gdx.graphics.getWidth()), ran(0, Gdx.graphics.getHeight())); 
      System.out.println("Player Destination Reached: " + pPos.x + "," + pPos.y + " Moving to new point: " + pTargetPos.x + "," + pTargetPos.y); 
      break; 
    } 
    turn(); 
    move(); 
    ePlayerBody.set(pPos.x, pPos.y, pWidth); 
} 

public int playerArrived() { 
    if (pTargetPos.x < pPos.x + pWidth && pTargetPos.x > pPos.x - pWidth && pTargetPos.y < pPos.y + pHeight && pTargetPos.y > pPos.y - pHeight) { 
     return 1; 
    } else { 
     return 0; 
    } 
} 

public float ran(float low, float high) { 
    return (float) (Math.random() * (high - low + 1)) + low; 
} 

public void move() { 
    pVel.set(pTargetPos.x - pPos.x, pTargetPos.y - pPos.y); 
    pVel.nor(); 
    pVel.x *= sMaxSpeed + Gdx.graphics.getDeltaTime(); 
    pVel.y *= sMaxSpeed + Gdx.graphics.getDeltaTime(); 
    pVel.setAngle(pNewRotation + 90); 
    pPos.add(pVel); 
} 

public void turn() { 
    pRotation = ((Math.atan2(pTargetPos.x - pPos.x, -(pTargetPos.y - pPos.y)) * 180.0d/Math.PI)+180.0f); 
    pNewRotation += (pRotation - pNewRotation) * Gdx.graphics.getDeltaTime(); 
    System.out.println(pRotation+" "+pNewRotation); 
} 

Я загрузил изображение на Imgur, чтобы попытаться лучше объяснить мою проблему

image

+0

Первый вопрос: Javadoc для 'Math.atan2()' говорит, что первый аргумент 'y' и второй аргумент' x'. Вы, кажется, называете это в обратном порядке ... вы уверены, что это то, что вы хотите? – dcsohl

ответ

1

Когда судно находится непосредственно ниже, и только немного левее, мишень, то звонок Math.atan2(pTargetPos.x - pPos.x, -(pTargetPos.y - pPos.y)) вернет значение, очень близкое к π/2. Когда ваш корабль находится прямо под и чуть правее, цель, этот звонок вернется - π/2. Когда вы пересечете красную линию, ваше направление будет переворачиваться на 180 градусов (π радианов). Вот почему он «сходит с ума».

Вам нужно выяснить, какой способ выбрать угол наклона. Я бы предложил предложения по этому поводу, но я все еще не совсем понимаю, какое поведение вы ожидаете.

+0

То, что у меня есть, это корабль игрока, который летает сам по себе, он имеет целевое положение (случайное x, случайное y) на экране и начинает двигаться к этому месту. Он имеет скорость вращения, так что там есть рулевое поведение. То, что у меня было, это скорость, перемещающая корабль вперед, и поворот видит, какой угол нужно исправить, чтобы начать вращаться над целевой точкой и превратить игрока в точку. Я пробовал другие методы получения угла, но поскольку libgdx y перевернулся, это было бесполезно. –

+0

Итак, вы обнаружите, что, помимо проблемы с переворачиванием, код работает правильно? Я не слишком знаком с libgdx, но мне кажется, что в вашем коде много странности. Например, 'move()': вы вычисляете вектор цели, нормализуете его, умножаете на коэффициент скорости и затем перезаписываете все это, вызывая 'setAngle()'? Почему бы просто не называть 'setLength()' с вашим коэффициентом скорости и 'setAngle()' в вашем направлении? – dcsohl

+0

И затем возьмите 'turn()': все, что вам действительно нужно сделать, это выяснить, находится ли цель слева или справа от вашего текущего заголовка (создайте «Вектор» для цели и используйте 'angle() 'для сравнения этого' Vector' с вашим 'pRotation') и вызовом' pRotation.rotate() 'с положительным или отрицательным значением, соответственно. Если вы согласитесь с этим, я соответствующим образом обновлю ответ. – dcsohl

0

Это работает для меня:

public void turn() { 
    pRotation = ((tPos.y - pPos.y)/(tPos.x - pPos.x) * 180.0d/Math.PI); 
    pNewRotation += (pRotation - pNewRotation) * Gdx.graphics.getDeltaTime(); 
} 

public void move() { 
    pVel.set(pDir); 
    pVel.nor(); 
    pVel.x *= sMaxSpeed + Gdx.graphics.getDeltaTime(); 
    pVel.y *= sMaxSpeed + Gdx.graphics.getDeltaTime(); 
    pVel.setAngle(pNewRotation + 90); 
    pPos.add(pVel); 
} 
+0

this.pDir.set (tPos.x - pPos.x, tPos.y - pPos.y); –