0

I am developing a game for mobile in AIR (as3). I have created some bots for this game that initially just wander around. But when a bonus enters the stage, they have to move to the bonus.

The detection of a new bonus and moving of the bots works fine, but there is something wrong with the manipulation when a new bonus enters the stage.

Basically, this is how it works (or I try to make it work):

My bot moves along with his rotation as a parameter. (works fine)

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;
}

So, to do know if a new bonus appears I catch an event first:

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);
}

My bot is now on point A and would normally go to point B (normalNextLocation). Then, the new bonus appears on point C (nextLocation). I wanted to solve this whit the Law of Cosines, since I needed A's angle to know the new rotation of my bot. This is how I tried to calculate this:

// 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);
}

I've searched on this matter for quite some time now, but can't find the answer... Does anybody see what I'm doing wrong? - [Fixed]

Diëgo
  • 103
  • 1
  • 9
  • Could you perhaps post a demo of what is happening, or an illustration on what the desired behaviour is? I'm not sure I understand what you are trying to do. It seems odd to me why the bot should need to use the "normalNextLocation" if it is no longer heading towards it. If you simply need the angle between two points, use `Math.atan2(target.y-bot.y, target.x-bot.x)` – Jonatan Hedborg Dec 27 '11 at 23:37
  • I needed the angle between 2 lines, and I had 2 points, and an estimated 3rd point – Diëgo Dec 28 '11 at 02:14
  • Since I don't have more than 10 rep, here you go: http://imgur.com/Bkl27 – Diëgo Dec 28 '11 at 02:25

1 Answers1

1

You have a typo here:

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

The quantity to subtract should be Math.pow(lengthA, 2). As is, you calculate (modulo floating point inaccuracies) lengthB^2/(2*lengthB*lengthC). That would produce a NaN if lengthB == 0, which I suspect is what happens. This means nextLocation is identical or at least very close to currentLocation.

On another note, shouldn't normalNextLocation be currentLocation + timeStep*velocity? You set it to velocity, as far as I can see.

Daniel Fischer
  • 181,706
  • 17
  • 308
  • 431
  • Thank you, NaN is solved! Will have a look on normalNextLocation thingie, because it doesn't work properly yet... thank you for noticing! :-) – Diëgo Dec 28 '11 at 02:13