1

Well... my issue comes from a quality of life preference to be honest. I'm currently at my day job so I can't provide specific code; however, I can give the pseudocode now and will provide the actual code when I get home.

I have created a virtual joystick and I want to map an object that circles the screen to the math.atan2 angle.

This works perfectly if I use obj.rotation = angle.

What I want to do(and have stayed up all night trying to figure out) is make the transition of the object go smoothly to the joystick angle instead of just equaling it so that it isn't all jittery. The only idea I could come up with is getting a delta of the 2 and subtracting the obj.rotation from the delta/4.

That works for the most part, but when the angle from the math.atan2 goes from 359 to 0 it messes everything up.

Has anybody ever run into this and/or is willing to help me out? Is there a way to make math.atan2 spit out numbers > 360? I've been banging my head on my keyboard for too long on this.

Many thanks in advance.

local function movePaddle(event)
local obj = right
local mMin = math.min;
local mCos = math.cos;
local mSin = math.sin;
local mAtan2 = math.atan2;
local mSqrt = math.sqrt;
local mFloor = math.floor;
local mPi = math.pi;
local radToDeg = 180/mPi;
local degToRad = mPi/180;
local radius = 40
if event.phase == "began" then
display.getCurrentStage():setFocus(obj)
--startMoveX = obj.x; startMoveY = obj.y;
local parent = obj.parent;
    local posX, posY = parent:contentToLocal(event.x, event.y)
    obj.x = posX; obj.y = posY;
    local angle = (mAtan2( posX, posY )*radToDeg)-90;
    local testAngle = angle + 360

    --paddleAnchor:applyTorque(delta*100)
         if angle < 0 then angle = 360 + angle end;
         if angle > 360 then angle = angle - 360 end
         if paddleAnchor.rotation < 0 then paddleAnchor.rotation =      paddleAnchor.rotation + 360 end
         if paddleAnchor.rotation > 360 then paddleAnchor.rotation =   paddleAnchor.rotation - 360 end
         local delta = (angle)-paddleAnchor.rotation

         if delta < angle then 
            paddleAnchor.rotation = paddleAnchor.rotation + delta/5
        elseif paddleAnchor.rotation > angle then 
            paddleAnchor.rotation = paddleAnchor.rotation - delta/5
        end
            print(delta)
            local distance = mSqrt((posX*posX)+(posY*posY));
            if distance >= radius then
                local radAngle = angle*degToRad;
                distance = radius;
                obj.x, obj.y = distance*mCos(radAngle), -    distance*mSin(radAngle)
            else
                obj.x, obj.y = posX, posY;
            end

elseif event.phase == "moved" then
    local parent = obj.parent;
    local posX, posY = parent:contentToLocal(event.x, event.y)
        obj.x = (event.x - event.xStart) + posX
        obj.y = (event.y - event.yStart) + posY
    local angle = (mAtan2( posX, posY )*radToDeg)-90;
    --local testAngle = angle + 360
    --if (paddleAnchor.rotation ~= -angle - 90) then
        --if (paddleAnchor.rotation < -angle - 90) then 
            --paddleAnchor.rotation = (paddleAnchor.rotation + (-angle-90)/2)
    --  elseif

    --end
    --paddleAnchor.rotation = -angle - 90
      if angle < 0 then angle = angle +360 end;
      if angle > 360 then angle = angle - 360 end
      if paddleAnchor.rotation < 0 then paddleAnchor.rotation = paddleAnchor.rotation + 360 end
      if paddleAnchor.rotation > 360 then paddleAnchor.rotation = paddleAnchor.rotation - 360 end
      local testAngle = angle + 360

        --if (-angle-90) >= 0 then angle = 270 end



    local delta = angle-paddleAnchor.rotation
      print(delta)
         if paddleAnchor.rotation < angle then 
            paddleAnchor.rotation = paddleAnchor.rotation + delta/5
        elseif paddleAnchor.rotation > angle then 
            paddleAnchor.rotation = paddleAnchor.rotation - delta/5
        end
    --paddleAnchor:applyTorque(delta)

            local distance = mSqrt((posX*posX)+(posY*posY));
            if distance >= radius then
                local radAngle = angle*degToRad;
                distance = radius;
                obj.x, obj.y = distance*mCos(radAngle), -distance*mSin(radAngle)
            else
                obj.x, obj.y = posX, posY;
            end
elseif event.phase == "ended" or event.phase == "cancelled" then
    obj.y = obj.startMoveY
    obj.x = obj.startMoveX
    display.getCurrentStage():setFocus(nil)
end
return true
end
greatwolf
  • 20,287
  • 13
  • 71
  • 105
  • If it is seriously that simple I will be so mad at myself and grateful to you. I asked now, because it has really been racking my brain and I can't think about work with this nagging at me. I'm going to lunch here in about 20 minutes and I'll have a chance to check to see if this works. – Payton Terry Apr 22 '15 at 15:36
  • Does the same thing. Gah... this is frustrating. – Payton Terry Apr 22 '15 at 17:12
  • I have no idea what you're doing in this code. But you can just add or subtract 360° from either start or destination angle as long as they are more than 180° apart. Make sure that the angle will not increase steadily. – Nico Schertler Apr 22 '15 at 17:27

1 Answers1

1

atan2(y, x) gives the angle or argument arg of x + i * y. In the Cartesian plane with positive orientation. Screen coordinates are different.

The angle arg2 - arg1 between two points is the argument of the fraction (x2+i*y2)/(x1+i*y1). Since the argument does not depend on real positive factors, this is the same as the argument of

(x2+i*y2)*(x1-i*y1) = (x1*x2+y1*y2) + i*(x1*y2-y1*x2)

which can thus be computed as

delta_angle = atan2(x1*y2-y1*x2, x1*x2+y1*y2)

Thus compute always the angle increment from the last position (x1, y1) to the new position (x2, y2) and add it to the total angle,

angle += delta_angle. 

This should give a non-jumping angle measure.

greatwolf
  • 20,287
  • 13
  • 71
  • 105
Lutz Lehmann
  • 25,219
  • 2
  • 22
  • 51
  • First off, I'd really like to thank you for your insight. Secondly, just for clarity's sake, x1,y1 would equal my posX and posY in the code and x2,y2 would equal obj.x and obj.y accordingly? – Payton Terry Apr 22 '15 at 18:03
  • The other way around. Before assigning them, `(obj.x,obj.y)` are the old coordinates corresponding to index 1 above and `(posX, posY)` the new ones for index 2. – Lutz Lehmann Apr 22 '15 at 18:22
  • However, if, as it seems, your input are screen coordinates with `(0,0)` the upper left corner, then you need to have defined a center of the coordinate system and set `x1=obj.x-centerX; y1=centerY-obj.y` and `x2=posX-centerX; y2=centerY-posY`. – Lutz Lehmann Apr 22 '15 at 18:44
  • Well... I tried the delta_angle method.... still really sensitive. Would using transition.to cause any problems? – Payton Terry Apr 23 '15 at 15:14
  • You should not expend energy on normalizing angle, that will be between -180° and 180°. You should normalize delta to be between -180° and 180°, usually it should be closer to zero. Also the line `if( delta < angle )` seems suspicious, the first is an angle difference, the second an absolute angle, one should only compare angle differences, probably using the absolute value of them. – Lutz Lehmann Apr 23 '15 at 15:29