【问题标题】:Issue using math.atan2 when rotating an object旋转对象时使用 math.atan2 的问题
【发布时间】:2015-04-22 14:46:18
【问题描述】:

嗯...老实说,我的问题来自对生活质量的偏好。我目前在做我的日常工作,所以我不能提供具体的代码;不过,我现在可以给出伪代码,我回家后会提供实际代码。

我创建了一个虚拟操纵杆,我想将一个环绕屏幕的对象映射到 math.atan2 角度。

如果我使用obj.rotation = angle,这将非常有效。

我想要做的(并且一直熬夜试图弄清楚)是使对象的过渡平稳地过渡到操纵杆角度,而不是仅仅使其相等,这样它就不会变得紧张。我能想出的唯一想法是得到 2 的 delta 并从 delta/4 中减去 obj.rotation。

这在大多数情况下都有效,但是当 math.atan2 的角度从 359 变为 0 时,一切都会变得混乱。

有没有人遇到过这种情况和/或愿意帮助我?有没有办法让 math.atan2 吐出大于 360 的数字?我一直在敲键盘太久了。

非常感谢。

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

【问题讨论】:

  • 如果真的那么简单,我会生自己的气,并感谢你。我现在问,因为它真的让我绞尽脑汁,我无法在这种唠叨的情况下思考工作。大约 20 分钟后我将在这里吃午饭,我将有机会检查这是否有效。
  • 做同样的事情。啊……这令人沮丧。
  • 我不知道你在这段代码中做了什么。但是,只要它们相距超过 180°,您就可以从起点或终点角度添加或减去 360°。确保角度不会稳定增加。

标签: math lua rotation coronasdk joystick


【解决方案1】:

atan2(y, x) 给出x + i * y 的角度或参数arg。在具有正方向的笛卡尔平面中。屏幕坐标不同。

两点之间的角度arg2 - arg1 是分数(x2+i*y2)/(x1+i*y1) 的参数。由于论证不依赖于真正的积极因素,这与

的论证相同
(x2+i*y2)*(x1-i*y1) = (x1*x2+y1*y2) + i*(x1*y2-y1*x2)

因此可以计算为

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

因此始终计算从最后一个位置(x1, y1) 到新位置(x2, y2) 的角度增量,并将其添加到总角度中,

angle += delta_angle. 

这应该给出一个非跳跃角度测量值。

【讨论】:

  • 首先,我非常感谢您的洞察力。其次,为了清楚起见,x1,y1 在代码中会等于我的 posX 和 posY,而 x2,y2 会相应地等于 obj.x 和 obj.y?
  • 反过来。在分配它们之前,(obj.x,obj.y) 是上面索引 1 对应的旧坐标,(posX, posY) 是索引 2 对应的新坐标。
  • 但是,如果您的输入是屏幕坐标,左上角为(0,0),那么您需要定义坐标系的中心并设置x1=obj.x-centerX; y1=centerY-obj.y 和@987654335 @.
  • 嗯...我尝试了 delta_angle 方法.... 仍然非常敏感。使用 transition.to 会导致任何问题吗?
  • 你不应该在归一化角度上消耗能量,这将在 -180° 和 180° 之间。您应该将 delta 标准化为介于 -180° 和 180° 之间,通常它应该更接近于零。同样if( delta &lt; angle )这一行似乎很可疑,第一个是角度差,第二个是绝对角度,应该只比较角度差,可能使用它们的绝对值。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-02
  • 1970-01-01
  • 2015-09-07
  • 1970-01-01
  • 2011-10-28
  • 1970-01-01
相关资源
最近更新 更多