Search code examples
actionscript-3mathtrigonometrydegreesradians

As3: Math, I'm too stupid for this. (trigonometry)


Okay, so I made some ai where a guard is following my character.

I am using this code:

    private function getDegrees(radians:Number):Number
    {
        //return Math.floor(radians/(Math.PI/180));

        return radians / 0.01745 | 0;
    }

    private function getRadians(delta_x:Number, delta_y:Number):Number
    {
        var r:Number = Math.atan2(delta_y, delta_x);

        if (delta_y < 0)
        {
            //r += (2 * Math.PI);

            r += 6.283;
        }

        return r;
    }

And then in the loop

        if(isShooting)
        {
            // calculate rotation based on mouse X & Y
            _dx = this.x - _root.assassin.x;
            _dy = this.y - _root.assassin.y;

            // which way to rotate
            _rotateTo = getDegrees(getRadians(_dx, _dy));   

            // keep rotation positive, between 0 and 360 degrees
            if (_rotateTo > this.rotation + 180) _rotateTo -= 360;
            if (_rotateTo < this.rotation - 180) _rotateTo += 360;

            // ease rotation
            _trueRotation = (_rotateTo - this.rotation) / _rotateSpeedMax;

            // update rotation
            this.rotation += _trueRotation;         


            gotoAndStop(5);
            isWalking = false;
            isStanding = false;
        }

The thing is, the guard rotates weirdly, it's as if he isn't looking at the player. It's as if the player is somewhere else. Dunno, it just doesn't work.. I have no idea what is wrong with the code!


Solution

  • You should just compute the relative angle

     _rotateTo = getDegrees(getRadians(_dx, _dy));   
     _trueRotation = (_rotateTo - this.rotation) / _rotateSpeedMax;
    

    then normalize this to be as close to zero as possible

      _trueRotation = (_trueRotation+900) %360 - 180;
    

    and then cut this to the maximal rotation per step

      _trueRotation = max(_trueRotation,_rotateSpeedMax* _timestep);
      _trueRotation = min(_trueRotation,-_rotateSpeedMax*_timestep);
    

    and use this then to update the forward direction

      this.rotation += _trueRotation;         
    

    Speed usually is change per time, so there should be a multiplication with some time step for semantic consistency. Of course, you may have the time step equal to 1, or rotateSpeedMax is really a rotateMaxAngle (per step), then the multiplication with timestep can be removed.