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

    Trigonometric imprecision

    Level 7
      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:

      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 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
          Martin Schaefer Level 1
          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
          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

          Hope that helps.

          Cheers,
          Martin
          • 2. Re: Trigonometric imprecision
            Level 7
            > 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

            -- ...
            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
            • 3. Re: Trigonometric imprecision
              Level 7
              > 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
                Level 7
                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
                  James Newton, ACP Level 3
                  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
                    Level 7
                    > 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
                      Level 7
                      > 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
                        Level 7
                        > 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)