Wobbly rotation

12 posts

Flag Post

I’m trying to get an arrow indicator (Sprite extension) to rotate to show the angle of movement (i.e., the angle between the last polled point of the cursor to the current polled point of the cursor). I am using Math.atan2, which works for the most part, but the indicator jitters and wobbles, like it is not sure of the exact angle, so it comes up with a random approximation.

I’ll post the code later this evening after I get home, but I was wondering if anyone knew of any approximation issues with atan/atan2, or had any other ideas why it would behave like this?

 
Flag Post

Check to make sure there is a difference between current point and last point. I assume you got it following your mouse or some such? Went thru the same prob when i started coding. One quick fix is to change at which distance the mouse moves to a new position (that is, when your real mouse has moved enough away
from it)

 
Flag Post

If indeed there is difference between last and current points (ie it isnt trying to find the angle of a line of zero length, which ofc has multiple results) then check if you have any controls on rotation per frame. For example it could be a target angle of 100, with current angle 98 but it moves in increments of say 5, so on next tick it is 103, then it moves back down to, 98, etc producing wobble

 
Flag Post

Yes, it follows the mouse cursor. Sorry, I thought I had mentioned that.

I do check that it isn’t the same point, and I don’t have a rotation per frame control (I need it to be able to accurately show sudden reversals in mouse movement direction or slow curves in direction).

 
Flag Post

Currently on phone at work myself still, so im not 100percent sure…but maybe it is something to do with the rotation and rounding? I encountered that problem once when converting a radian to degrees and was using the default result of such operations (rounding when casting as int). Fixed it by using math.floor instead for the rotation:Number param of DisplayObject

 
Flag Post

Is there an implicit cast to int in there somewhere? I have a constant that I use to convert. The value of the constant is 180/Math.PI. I multiply the result of atan2 with the constant for the converted value. AFAICS, there aren’t any casts or rounding. All variables that I’m using (related to this function) are Numbers.

 
Flag Post

Post the code and the result already.

 
Flag Post
public static const TO_DEGREES:Number = 180/Math.PI;

protected var cutAngInd:CutAngleIndicator;
protected var cutAngle:Number = 0;
protected var mausX:Number = 0;
protected var mausY:Number = 0;
protected var lastX:Number = 0;
protected var lastY:Number = 0;
protected var deltaX:Number;
protected var deltaY:Number;
protected var updateAng:Boolean;

// in init function:
addEventListener(Event.ENTER_FRAME, runGame, false, 0, true);

function runGame(event:Event):void
{
    mausX = mouseX;
    mausY = mouseY;
    deltaX = lastX - mausX;
    deltaY = mausY - lastY;
    lastX = mausX;
    lastY = mausY;
    updateAng = true;
    if (deltaX == 0)	  // vertical line (angle formula won't work, since slope will be undefined)
    {
        if (deltaY > 0)
        {
            cutAngle = 0;	
        }
        else if (deltaY < 0)
        {
            cutAngle = 180;
        }
        else
        {
            updateAng = false;
        }    // same point! use last angle (don't update angle)
    }
    else
    {
        cutAngle = Math.atan2(deltaY, deltaX) * TO_DEGREES;
        if (deltaY / deltaX < 0)    // adjust angle for negative slope
        {
            cutAngle -= 180;
        }
    }
    if (updateAng)
    {
        cutAngInd.setAngle(cutAngle);
    }
}

This was from about a month ago (aborted attempt for last GiTD). I originally tried using atan (atan2 apparently handles the undefined case, but I left the checks in anyway). Mouse movement is polled every frame (here, I’m getting the coordinates directly from the mouse, but I also tried with a mouse movement listener, with the same result).

I’ll post trace results later (assuming no one sees an issue in the code making it superfluous) after I get some sleep.

…oh, almost forgot:

public class CutAngleIndicator extends Sprite
{
    // variable declarations, etc.

    public function setAngle(newRot:Number):void
    {
        this.rotation = newRot;
    }
}
 
Flag Post

I don’t think I see the problem… Wait, yes I do! And if I’d been paying enough attention, I could have figured it out just from the first sentence of the OP.

Originally posted by dragon_of_celts:

(i.e., the angle between the last polled point of the cursor to the current polled point of the cursor)

Here’s your problem: this is inherently jittery.

You’ll want to average it over a few frames or something.


I was developing an Android game at one point, and I was wondering why my swipes were flinging things in the wrong directions. (Sometimes just 45° off, but sometimes it would go almost 180° from the direction of the swipe.)

Fortunately, I found a feature that draws a line onscreen showing the path you trace, and I realized the end of the path was often quite jittery, sometimes even turning around.

In the end, I based it on the start and end points of the swipe, and it worked a lot better.

 
Flag Post

Hmmm, interesting. I guess I could try updating position only every second or third frame. Thanks.

 
Flag Post
Originally posted by dragon_of_celts:


public class CutAngleIndicator extends Sprite
{
// variable declarations, etc.

public function setAngle(newRot:Number):void
{
this.rotation = newRot;
}
}

What’s the point of this method?

 
Flag Post

Point? We don’t need no stinkin’ point!

Well, I generally keep all variables protected, so I just wasn’t paying attention to the fact that this one happens to be public.

Edit: Now that I think about it, I believe I originally had it doing the angle calcs, but moved the calcs out when I decided that I needed to record angle data.