0
\$\begingroup\$

I have a top down game. The player moves the avatar with WASD where W rotates the avator to 180, S rotates to 0, A rotates to 90 and D rotates to 270. I also do diagonal movement so if they hold SA it rotates to 45, WA it rotates to 135, WD it rotates to 225, and SD it rotates to 315.

I smoothly rotate from the current rotation to the hardcoded desired rotation based on those key combo's. Of course what happens is if I'm rotating from anything > 180 to 0 it goes the long way back to 0. So if I'm at 270 rotation and I press S key it sends it back to 0 but that goes from 270 to 0 vs going from 270 to 360 which would result in the same end result but how it got there would be shorter.

I was looking at this (https://answers.unity.com/questions/556480/rotate-the-shortest-way.html) and trying to translate it but it's not working. Below is my translation.

function Script:CalcShortestRot(current, target)
    --if current == target then return from end

    local dist = target - current + 180
    dist = dist - math.floor(dist / 2 / 180) * 2 * 180 - 180

    System:Print("Dist = "..dist)

    if dist < 0 then
        System:Print("Value 1 = "..target - current)
        return current - dist
    else
        System:Print("Value 2 = "..current + target)
        return current + dist
    end
end

The usage is:

-- determine the model rotation based on direction we are going
    if move > 0 then
        if strafe > 0 then
            self.targetRot = self:CalcShortestRot(self.targetRot, 225)
            --self.targetRot = 225
        elseif strafe < 0 then
            --self.targetRot = 135
            self.targetRot = self:CalcShortestRot(self.targetRot, 135)
        else
            --self.targetRot = 180
            self.targetRot = self:CalcShortestRot(self.targetRot, 180)
        end
    elseif move < 0 then
        if strafe > 0 then
            --self.targetRot = 315
            self.targetRot = self:CalcShortestRot(self.targetRot, 315)
        elseif strafe < 0 then
            --self.targetRot = 45
            self.targetRot = self:CalcShortestRot(self.targetRot, 45)
        else
            --self.targetRot = 0
            self.targetRot = self:CalcShortestRot(self.targetRot, 0)
        end
    elseif strafe > 0 then
        --self.targetRot = 270
        self.targetRot = self:CalcShortestRot(self.targetRot, 270)
    elseif strafe < 0 then
        --self.targetRot = 90
        self.targetRot = self:CalcShortestRot(self.targetRot, 90)
    end

    self.rot = Math:Curve(self.targetRot, self.rot, self.damping)

EDIT: updated my CalcShortestRot() function per comments below but still not working. It spins all around

\$\endgroup\$
  • \$\begingroup\$ You don't need if/else branching — this can be done with a simple formula. If that solves your issue, we can close this as a duplicate. Otherwise, try editing your question to explain if you're having any trouble using this type of formula. \$\endgroup\$ – DMGregory Jan 28 '18 at 17:37
  • \$\begingroup\$ Can't seem to get it to work. I use the following: function Script:CalcShortestRot(from, to) if from == to then return from end local dist = to - from + math.pi dist = dist - math.floor(dist / 2 / math.pi) * 2 * math.pi if dist < 0 then return to - from else return to + from end end \$\endgroup\$ – user441521 Jan 28 '18 at 17:47
  • \$\begingroup\$ Perhaps the issue is that I hardcode the angles to go to when I'm checking based on the keys the player pushes. I do this because I only want 8 angles to be possible to move to.So If the current is at 315 and they press the down key I say go to angle 0 when it really should go to 360 for the shortest but I hardcode 0 angle to be "going south". \$\endgroup\$ – user441521 Jan 28 '18 at 17:54
  • \$\begingroup\$ I had a small mistake in that formula, should be corrected. Also, you work in degrees, not in radians \$\endgroup\$ – Bálint Jan 28 '18 at 17:54
  • \$\begingroup\$ Updated question. Not able to get it to work. \$\endgroup\$ – user441521 Jan 28 '18 at 18:04

Browse other questions tagged or ask your own question.