6 Replies Latest reply on Nov 22, 2012 10:59 AM by Production Monkey

    Move sprite in straight line

    anjemalo Level 1

      Hello:

      I'm trying to move a sprite from one point to another in straight line direction, but I can't get it.

      For example:

       

      X1=0

      X2=500

      Y1=0

      Y2=300

      I need to move smoothly diagonally (straight line) I'm trying to use equation of the line formula but I can't do it.

      Can you help me, please?

      Many thanks

        • 1. Re: Move sprite in straight line
          Production Monkey Level 3

          Here is a behavior that may do what you are looking for. It moves a sprite form point A to point B over a specified time interval. You can have the sprite begin moving on beginSprite(), or not.  You can call moveTo(point(x,y)) to tell the sprite to move to a new point. And, you can change the time length of the animation. The animation runs asynchronous to the Tempo setting.

           

          I just wrote this. It is not well tested, but seems to work fine.

           

           

           

          --  Straight line Sprite Animator

           

          --  Moves a sprite from point "A" to "B" in specified timespan

           

           

          Property  pMe  -- sprite reference

          Property  pStartLoc  -- starting location point

          Property  pEndLoc  -- ending location point

          Property  pCurLoc  -- Point:  The current location of sprite during move. Note: This contains Floating point values.

          Property  pInc  -- Point:  x, y increments each update. Note: This contains Floating point values.

          Property  pTimeOb  -- holds reference to timeout object

          Property  pUpdatesPerSecond  -- number of screen updates per second

          Property  pTimeLength  -- amount of time the move takes

          Property  pMinIncDistance  -- the minimum distance to move the sprite

          Property  pBeginAnimationAtBeginsprite  -- bool:  true/false

           

           

          On GetBehaviorDescription me

            return "Moves a sprite from point A to B in the specified amount of time. "

          end GetBehaviorDescription me

           

           

          On GetPropertyDescriptionList me

            DefaultLoc = sprite(the currentspriteNum).loc

            Props = [:]

            Props[#pEndLoc] = [#default:DefaultLoc, #format:#point, #comment:"Point to move sprite to."]

            Props[#pTimeLength] = [#default:1.0, #format:#float, #Range:[#min:0.2, #max:10.0], #comment:"Length of time for the animation."]

            Props[#pBeginAnimationAtBeginsprite] = [#default:true, #format:#boolean, #comment:"Begin animation at begineSprite."]

            return Props

          end GetPropertyDescriptionList me

           

           

          -- setup

          on beginSprite me

            pMe = sprite(me.spriteNum)

            pStartLoc = pMe.loc

            pUpdatesPerSecond = 40

            if pBeginAnimationAtBeginsprite then me.move()

          end beginSprite

           

          -- change animation time length

          on setTimeLength me, val  -- float

            pTimeLength = val

          end setTimeLength

           

           

          -- Sets the start loc to the end loc and vice versa

          on toggleLocs me

            TempLoc = pStartLoc

            pStartLoc = pEndloc

            pEndLoc = TempLoc

          end toggleLocs

           

           

          -- animates sprite to point location

          on moveTo me, destinationLoc  -- point

            pEndloc = destinationLoc

            pStartLoc = pMe.loc

            me.move()

          end moveTo

           

           

          -- Begins the movement process

          on move me

            if pEndloc = pStartLoc then

              put "Error in move().  Start and End locations are the same"

              return

            end if

           

            -- Setup increments for x and y dimensions

            TotalNumberOfUpdates = float(pUpdatesPerSecond * pTimeLength)

            DeltaXandY = pEndLoc - pStartLoc

            --    pInc is a floating point Point object. Amount to increment animation each update.

            pInc = point(DeltaXandY[1]/TotalNumberOfUpdates, DeltaXandY[2]/TotalNumberOfUpdates)

           

            -- store the minimum distance the sprite must move. Determines when the animation is over.

            pMinIncDistance = sqrt(pInc[1] * pInc[1] + pInc[2] * pInc[2])   -- distance formula

           

            --  grab floating point version of the sprite's current location

            pCurLoc = point(float(pStartLoc[1]), float(pStartLoc[2]))

           

            -- begin updating process

            pTimeOb = timeout().new("Move_"&pMe, 1000/pUpdatesPerSecond, #updatePosition, me)

          end move

           

           

           

          -- Moves the sprite pInc distance towards its final destination location

          on updatePosition me, timeOb

            -- check if next move is less than or equal to remaining distance. If so then done

            DeltaX = pEndLoc[1] - pCurLoc[1]

            DelatY = pEndLoc[2] - pCurLoc[2]

            if sqrt(DeltaX * DeltaX + DelatY * DelatY ) <= pMinIncDistance then  -- done moving

              pMe.loc = pEndLoc

              pTimeOb.forget()

              pTimeOb = 0

              exit

            end if

           

            -- increment sprite location

            pCurLoc = pCurLoc + pInc

           

            -- set sprite  location

            pMe.loc = pCurLoc

          end updatePosition

           

           

          -- cleans up and timeout objects that may be hanging around.

          on endsprite me

            if pTimeOb.objectP Then

              pTimeOb.forget()

              pTimeOb = 0

            end if

          end endsprite

          • 2. Re: Move sprite in straight line
            James Newton, ACP Level 3


            anjemalo wrote:

            I'm trying to use equation of the line formula but I can't do it.

             

            Hi Anjemalo,

             

            If you want work with the formula of a line, here is a handler that might help you. 

             

            X1=0

            X2=500

            Y1=0

            Y2=300

             

            put LineFormula(point(X1, Y1), point(X2, Y2))

            -- [#slope: 0.6000, #zeroX: 0.0000, #x1: 0, #x2: 500]

             

             

            on LineFormula(aPoint1, aPoint2) ------------------------------------

              -- INPUT: <aPoint1> and <aPoint2> should be point objects.

              -- ACTION: Converts a 2D line defined by two points into a formula

              --         corresponding to:

              --         y = ax + b (or in Lingo : v = slope * h + zeroX).

              --

              --         The two points used to define the line may be considered

              --         to be the end points of a segment, or one of them may be

              --         the end point of a ray.

              -- OUTPUT: Returns a list with one of the following formats:

              --         Sloping or horizontal line

              --         [#slope: <float slope (a in y = ax+ b)>,

              --          #zeroX: <float value of y where line crosses x = 0 (b)>,

              --          #x1:    <float value of x at start of segment>,

              --          #x2:    <float value of x at end of segment>]

              --

              --         Vertical line

              --         [#x: <float value of x for entire line>,

              --          #y1: <float value of y at start of segment>,

              --          #y2: <float value of y at start of segment>]

              --

              --         In the first version, #slope corresponds to "a", #zeroX

              --         corresponds to "b" and #x1 and #x2 correspond to the

              --         values for x at the ends of the line segment.

              --

              --         The second version is a special case for a vertical line.

              --         #x corresponds to the constant value of x for all values

              --         of y. #y1 and #y2 give the y values at the ends of the

              --         line segment.

              --------------------------------------------------------------------

             

              -- Check parameters

              if ilk(aPoint1) <> #point then

                return #invalidPoint

              else if ilk(aPoint2) <> #point then

                return #invalidPoint

              else if aPoint1 = aPoint2 then

                return #identicalPoints

              end if

              -- End of checking

             

              h1 = aPoint1.locH

              v1 = aPoint1.locV

              h2 = aPoint2.locH

              v2 = aPoint2.locV

             

              tDeltaH = h1 - h2

              if tDeltaH = 0 then -- The line is vertical

                tFormula = [#x: h1]

               

                tFormula[#y1] = v1

                tFormula[#y2] = v2

               

              else

                tDeltaH = float(tDeltaH)

                -- The line is horizontal or sloping.  Solve y = ax + b for a,

                -- at (h1, v1) and (h2, v2).

                --

                --            v1 = a * h1 + b

                --            v2 = a * h2 + b

                -- =>          b = v2 - a * h2

                -- =>         v1 = a * h1 + v2 - a * h2

                -- => a(h1 - h2) = v1 - v2

               

               

                a = (v1 - v2) / tDeltaH

               

                -- When x = 0, y = b

                --            v1 = a * h1 + b

                --            v2 = a * h2 + b

                -- =>          a = (v2 - b) / h2

                -- =>         v1 = (v2 - b) * h1 / h2 + b

                -- =>    v1 * h2 = v2 * h1 - b * h1 + b * h2

                -- => b(h1 - h2) = v2 * h1 - v1 * h2

               

                b = ((h1 * v2) - (h2 * v1)) / tDeltaH

               

                tFormula = [#slope: a, #zeroX: b]

               

                tFormula[#x1] = h1

                tFormula[#x2] = h2

              end if

             

              return tFormula

            end LineFormula

            • 3. Re: Move sprite in straight line
              anjemalo Level 1

              Thank you very much.

               

              What I'm trying to do is a simple game where you drag an image to a specific position if not matched then return to its original position by straight line.

               

              Thanks for your code I'll try it

              • 4. Re: Move sprite in straight line
                anjemalo Level 1

                I don't know how to use this result:

                -- [#slope: 0.6000, #zeroX: 0.0000, #X1: 0, #X2: 500]

                to move my  sprite.

                Can you help me please?

                thanks

                • 5. Re: Move sprite in straight line
                  anjemalo Level 1

                  Hello:

                  I'm trying your code alone with a single sprite and it works, but I don't know how to incorporate to my own behavior with many other parameters.

                  Thanks.

                  • 6. Re: Move sprite in straight line
                    Production Monkey Level 3

                    You can attach multiple behaviors to a sprite and they will work together. So, you could attach the behavior I wrote to move a sprite and attach a behavior for drag-and-drop and several others if you want.

                     

                    What you then might do is: In the mouseup() handler of the drag-and-drop behavior you can call the moveTo() handler in the move behavior, if the sprite is not in the correct position.

                     

                    Something like:

                     

                    on mouseUp me

                         if (Not in correct spot) then

                              sprite(me.spriteNum).moveTo(me.pStartLoc)

                         end if    

                    end