Вычисление угла с использованием закона косинуса, учитывая 2 балла и вычисление 1 балла - PullRequest
0 голосов
/ 28 декабря 2011

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

Обнаружение нового бонуса и перемещение ботов работает нормально, но что-то не так с манипуляцией, когда новый бонус выходит на сцену.

По сути, так оно и есть (или я пытаюсь заставить его работать):

Мой бот движется вместе со своим вращением в качестве параметра. (отлично работает)

private function moveToNextLocation():void
{
    var angle:Number = _rotation * 0.0174532925; // 1 degree = 0.0174532925 radians
    var speedX:Number = Math.sin(angle) * _speed; 
    var speedY:Number = -Math.cos(angle) * _speed;

    if (_turnLeft && !_moveToBonus){
        _rotation -= _rotationStep * (_speed / _maxSpeed);
    }
    else if (_turnRight && !_moveToBonus){
        _rotation += _rotationStep * (_speed / _maxSpeed);
    }

    this.x += speedX; this.y += speedY;
}

Итак, чтобы узнать, появляется ли новый бонус, я сначала поймаю событие:

protected function onNewBonusAppeared(event:BonusEvent):void
{
    trace("new bonus appeared!");
    _moveToBonus = true;
    _rotation = getRotation(new Point(event.bonus.x, event.bonus.y));
    trace("Heading to " + event.bonus.type + " with new rotation: "  + _rotation);
}

Мой бот сейчас находится в точке A и обычно переходит в точку B (normalNextLocation). Затем новый бонус появляется в точке C (nextLocation). Я хотел решить это с помощью закона косинусов, так как мне нужен угол А, чтобы узнать новое вращение моего бота. Вот как я пытался вычислить это:

// calculate new rotation 
private function getRotation(nextLocation:Point):Number
{
    //sources:
    //http://www.teacherschoice.com.au/maths_library/trigonometry/triangle_given_3_points.htm
    //http://en.wikipedia.org/wiki/Law_of_cosines
    //http://stackoverflow.com/questions/1211212/how-to-calculate-an-angle-from-three-points

    //Calculate current angle and corners
    var angle:Number = _rotation * 0.0174532925;
    var currentLocation:Point = new Point(this.x, this.y);
    var normalNextLocation:Point = new Point(Math.sin(angle) * _speed, -Math.cos(angle) * _speed);

    //Calculate lengths of the 3 sides of the triangle  
    var lengthA:Number = calculateLength(normalNextLocation, nextLocation);
    var lengthB:Number = calculateLength(currentLocation, nextLocation);
    var lengthC:Number = calculateLength(currentLocation, normalNextLocation);

    //Calculate the difference in rotation  
    //-------------THIS IS WHERE IT GOES WRONG-----------
    var deltaRotation:Number = calculateAndInverseCosineRule(lengthA, lengthB, lengthC);

    //positive or negative rotation difference
    if (normalNextLocation.y < nextLocation.y)
        return _rotation - deltaRotation;
    else
        return _rotation + deltaRotation;
}
private function calculateLength(a:Point, b:Point):Number
{
    //SQRT((x2 - x1)² + (y2 - y1)²)
    return Math.sqrt(Math.pow(b.x - a.x, 2) + Math.pow(b.y - a.y, 2));
}
private function calculateAndInverseCosineRule(lengthA:Number, lengthB:Number, lengthC:Number):Number
{
    //a² = b² + c² - 2*b*c*cos(alpha)
    //cos(alpha) = (b² + c ² - a²) / (2 * b * c)
    //alpha = cos^-1(cos(alpha))
    var cos:Number = (Math.pow(lengthB, 2) + Math.pow(lengthC, 2) - Math.pow(lengthA, 2))
                         / (2 * lengthB * lengthC);
    trace("cos: ", cos); //returns NAN at some point... don't know why
    return Math.acos(cos);
}

Я уже давно искал этот вопрос, но не могу найти ответ ... Кто-нибудь видит, что я делаю неправильно? - [Исправлено]

1 Ответ

1 голос
/ 28 декабря 2011

У вас есть опечатка здесь:

var cos:Number = (Math.pow(lengthB, 2) + Math.pow(lengthC, 2) - Math.pow(lengthC, 2))

Количество для вычитания должно быть Math.pow(lengthA, 2). Как есть, вы рассчитываете (по модулю погрешности с плавающей запятой) lengthB^2/(2*lengthB*lengthC). Это произвело бы NaN, если lengthB == 0, что, как я подозреваю, и происходит. Это означает, что nextLocation идентично или, по крайней мере, очень близко к currentLocation.

На другой ноте, не должно ли normalNextLocation быть currentLocation + timeStep*velocity? Насколько я вижу, вы установили velocity.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...