8 Replies Latest reply on Mar 7, 2009 10:04 PM by Newsgroup_User

# Trigonometric imprecision

I'm having a slight problem with some trig functions. I'm trying to get a
sprite to move along a specific line based on its rotation. It *almost*
works, but it tends to creep out of alignment at certain angles. The code
doing the moving is:

my.loc = my.loc + point(xi,yi)

(my is a property equal to sprite(me.spriteNum), and degToRad is a function
which returns deg * (pi/180.0))

In theory, this should move the sprite the equivalent of 5 pixels in the
direction of rotation, but it's definitely a little bit off. It's not
noticeable over short distances, but over a longer stretch, it's very
definitely wrong. I tried to make sure it's doing everything in floats, and
not converting anything to integers anywhere, but I think there's some
rounding going on, and I can't figure out where. Anyone know what I'm doing
wrong here?

• ###### 1. Re: Trigonometric imprecision
Hi Darrel,

have you tried to set "the floatPrecision" to a value higher than 4?
You can go up to 15 max.

In your example it could look like this:

the floatPrecision = 15
my.loc = my.loc + point(xi,yi)
the floatPrecision = 4 -- set back to default value of 4

Hope that helps.

Cheers,
Martin
• ###### 2. Re: Trigonometric imprecision
> xi = float(cos(degToRad(my.rotation - 90))*5.0)
> yi = float(sin(degToRad(my.rotation - 90))*5.0)
> my.loc = my.loc + point(xi,yi)

my.loc = my.loc + ...
Right there you are compounding rounding errors. A sprite's loc is
always integer values, so any floats returned by your movement functions
are rounded to integers. It's better to store the value returned and
then set the loc, something like:
--
property myCalculatedLoc

on beginSprite me
-- ...
myCalculatedLoc = [my.locH, my.locV]
end

-- ...
myCalculatedLoc = myCalculatedLoc + point(xi, yi)
my.loc = myCalculatedLoc
• ###### 3. Re: Trigonometric imprecision
> have you tried to set "the floatPrecision" to a value higher than 4?
> You can go up to 15 max.
>
> In your example it could look like this:
>
> the floatPrecision = 15
> xi = float(cos(degToRad(my.rotation - 90))*5.0)
> yi = float(sin(degToRad(my.rotation - 90))*5.0)
> my.loc = my.loc + point(xi,yi)
> the floatPrecision = 4 -- set back to default value of 4

I thought the floatPrecision thing was just a display setting. Mathematical
caluclations are the same regardless of the setting. Just try this:

the floatPrecision = 1
put 1.125 + 1.125
--2.3
put 1.125 + 1.124
--2.2

The math comes out the same regardless of the setting. I'm pretty sure it's
only when you want to put a float value into a string or text display of
some sort that that's relevant.

• ###### 4. Re: Trigonometric imprecision
This seems to do it - there's still a bit of annoying jitter, which I'm not
sure there's much I can do about, but it stays on the path at least. The
jitter I probably have to live with, unless I can come up with some sort of
anti-aliasing method, but that's probably way more complicated than it needs
to be.

• ###### 5. Re: Trigonometric imprecision
The annoying jitter is doubtless due to Director rounding the loc of the sprite to the nearest integer. You might find that using a shockwave3d sprite gives you a smoother animation... at the cost of a high CPU overhead. Other possible solutions include:

* Using Imaging Lingo to draw your animation into an oversize image, then downscaling it for display
* Setting the drawRect of the Stage and larger sprites, getting Director to do the downscaling for you
• ###### 6. Re: Trigonometric imprecision
> my.loc = my.loc + ...
> Right there you are compounding rounding errors. A sprite's loc is always
> integer values, so any floats returned by your movement functions are
> rounded to integers. It's better to store the value returned and then set
> the loc, something like:
> --
> property myCalculatedLoc
>
> on beginSprite me
> -- ...
> myCalculatedLoc = [my.locH, my.locV]
> end
>
> -- ...
> xi = float(cos(degToRad(my.rotation - 90))*5.0)
> yi = float(sin(degToRad(my.rotation - 90))*5.0)
> myCalculatedLoc = myCalculatedLoc + point(xi, yi)
> my.loc = myCalculatedLoc

I'll try it, but I'm pretty sure I've moved a sprite's loc by non-integral
values before without a problem. Let's see if this works...

• ###### 7. Re: Trigonometric imprecision
> The annoying jitter is doubtless due to Director rounding the loc of the
> sprite
> to the nearest integer. You might find that using a shockwave3d sprite
> gives
> you a smoother animation... at the cost of a high CPU overhead. Other
> possible
> solutions include:
>
> * Using Imaging Lingo to draw your animation into an oversize image, then
> downscaling it for display
> * Setting the drawRect of the Stage and larger sprites, getting Director
> to do
> the downscaling for you

Unfortunately, all of those solutions basically require me to redesign the
whole project from scratch, so no dice there. I think I can live with the
jitters...

• ###### 8. Re: Trigonometric imprecision
> I'll try it, but I'm pretty sure I've moved a sprite's loc by non-integral
> values before without a problem. Let's see if this works...

I'm sure you have, but you weren't storing your calculated (ideal) loc,
you were starting from an integer value each time you set it rather than
adding floats and rounding once (at display time)