How to smoothly rotate while dealing with rollover

General discussion about LÖVE, Lua, game development, puns, and unicorns.
Post Reply
User avatar
Skeiks
Citizen
Posts: 51
Joined: Wed Jan 28, 2015 1:51 pm

How to smoothly rotate while dealing with rollover

Post by Skeiks »

So I have a character that's going to rotate based on the ground they're on. I want the game to smoothly move the character from one angle to the next. So I wrote this simple thing.

Code: Select all

 self.rot = self.rot + (self.tRot-self.rot)/5
tRot is the "to rotation", while rot is the current rotation. This works for the most part, but if rot is 350, and tRot is 10, then it poses a problem. Instead of smoothly moving like:

350-355-360-0-5-10

it goes

350-345-340-...-20-15-10

This makes the character flip all the way around instead of taking the smaller way. Does anyone know how to fix this? I'm sure there's a really simple solution to this I'm overlooking.

Thanks!
davisdude
Party member
Posts: 1154
Joined: Sun Apr 28, 2013 3:29 am
Location: North Carolina

Re: How to smoothly rotate while dealing with rollover

Post by davisdude »

Use dt
GitHub | MLib - Math and shape intersections library | Walt - Animation library | Brady - Camera library with parallax scrolling | Vim-love-docs - Help files and syntax coloring for Vim
User avatar
Skeiks
Citizen
Posts: 51
Joined: Wed Jan 28, 2015 1:51 pm

Re: How to smoothly rotate while dealing with rollover

Post by Skeiks »

davisdude wrote:Use dt
Unless I'm missing something I don't see how including dt in this section of code would help solve the problem.
davisdude
Party member
Posts: 1154
Joined: Sun Apr 28, 2013 3:29 am
Location: North Carolina

Re: How to smoothly rotate while dealing with rollover

Post by davisdude »

Do something like:

Code: Select all

self.rot = self.rot + self.rotationSpeed * dt
I'm not really sure what you're variables mean or how they're calculated, so I can't help you more unless you upload a .love
GitHub | MLib - Math and shape intersections library | Walt - Animation library | Brady - Camera library with parallax scrolling | Vim-love-docs - Help files and syntax coloring for Vim
User avatar
Skeiks
Citizen
Posts: 51
Joined: Wed Jan 28, 2015 1:51 pm

Re: How to smoothly rotate while dealing with rollover

Post by Skeiks »

davisdude wrote:Do something like:

Code: Select all

self.rot = self.rot + self.rotationSpeed * dt
I'm not really sure what you're variables mean or how they're calculated, so I can't help you more unless you upload a .love

What I'm trying to do is pretty simple and isn't really tied to any of my other code. tRot isn't calculated, it's just set to what I want the rotation of the character sprite to be.

I have an angle I want the character to be at, and an angle that the character is currently at. I get the difference, divide the two and increment the angle the character is at to make it rotate smoothly. The problem is that this system doesn't understand that in angles, the path of least distance from 350° to 10° is through 0°. This means that the character does a full rotation when it only needs to do a 20° turn (example: http://imgur.com/ApLrP07) I bet that there's an easy way to do this mathematically so before I started writing a bunch of logic I figured I'd ask.

I've uploaded my .love but I don't think digging around my horribly written code will help much. There's a lot of problems with it but if you want to see this problem in particular open the game and hit "C". That will stick you to the ground (I'm trying to code something similar to magnet boots). Then hit right and walk up the wall. When you get to the ceiling, if the game didn't bug out before then, you should see what I mean.
Attachments
pLogic.love
Doesn't seem to be working when I tried downloading it, I'll figure out what's wrong tomorrow
(2.26 MiB) Downloaded 61 times
davisdude
Party member
Posts: 1154
Joined: Sun Apr 28, 2013 3:29 am
Location: North Carolina

Re: How to smoothly rotate while dealing with rollover

Post by davisdude »

Well, your problem is that you have a require that's capitalized, and in .love (and machines other than Windows AFAIK) it errors.
You'll also want to update Thomas.

That's a very good looking game so far! I like how the progress is going. I misunderstood your goal- my bad.
I tested your code, and this appears to work for me:

Code: Select all

-- Line 206 pLogic/magnet.lua
local function cycle( value, min, max )
    local delta = max - min
    local result = ( value - min ) % delta
    if result < 0 then result = result + max end
    return min + result
end

local function rotateAngle( angle, target, speed )
    local diff = cycle( target - angle, -math.pi, math.pi )
    if diff < -speed then return angle - speed
    elseif diff > speed then return angle + speed
    else return target end
end
self.rot = rotateAngle( self.rot, self.tRot, math.abs( ( self.tRot - self.rot ) / 5 ) )
Although at the sharp edges the rotation is kind of choppy.
Recommended reading: http://yal.cc/angular-rotations-explained/
GitHub | MLib - Math and shape intersections library | Walt - Animation library | Brady - Camera library with parallax scrolling | Vim-love-docs - Help files and syntax coloring for Vim
User avatar
micha
Inner party member
Posts: 1083
Joined: Wed Sep 26, 2012 5:13 pm

Re: How to smoothly rotate while dealing with rollover

Post by micha »

I want to add two things to davisdudes answer:
1) Instead of using the cycle function, you could also define an angle-difference function, that takes care of the wrapping:

Code: Select all

function angleDiff(angle1,angle2)
  return (angle1-angle2+math.pi)%(2*math.pi) - math.pi
end
This function will always return an angle between -pi and pi (-180° and 180°) and gives you the difference between angle1 and angle2.
You could do this then:

Code: Select all

local change = angleDiff(self.tRot,self.rot)
self.rot = self.rot + 0.2 * change
(Using dt is advisble).

And for stability reasons you should do this from time to time:

Code: Select all

self.rot = self.rot%(2*math.pi)
It makes sure the rotation angle is between 0 and 2pi.

2) If you want to go for davisdudes solution, then the last line has to be changed (I believe. I couldn't test it, because the .love does not run on my machine)

Code: Select all

self.rot = rotateAngle( self.rot, self.tRot,  math.abs(cycle(self.tRot-self.rot,-math.pi,math.pi))/5  )
davisdude
Party member
Posts: 1154
Joined: Sun Apr 28, 2013 3:29 am
Location: North Carolina

Re: How to smoothly rotate while dealing with rollover

Post by davisdude »

micha wrote:2) If you want to go for davisdudes solution, then the last line has to be changed (I believe. I couldn't test it, because the .love does not run on my machine)

Code: Select all

self.rot = rotateAngle( self.rot, self.tRot,  math.abs(cycle(self.tRot-self.rot,-math.pi,math.pi))/5  )
I couldn't see any significant difference when I did this, but maybe I missed something. You're probably right.
Other than that, Micha's method works better. Here's a .love with all the changes:

Change main.lua 21 to: Input = require 'libs.input'
player.lua 414: Passed 'dt' as a variable to self:magnets
plogic/magnets.lua 206: Micha's stuff.

Here's a .love for whoever's interested (although it takes a really long time to load).
(PS: You have two anim8's, one in libs, and the other in gLibs)
(PPS: You have two folders called "Shaders": one in libs/Postshaders, the other in root.)
Attachments
pLogic.love
(2.5 MiB) Downloaded 47 times
GitHub | MLib - Math and shape intersections library | Walt - Animation library | Brady - Camera library with parallax scrolling | Vim-love-docs - Help files and syntax coloring for Vim
User avatar
micha
Inner party member
Posts: 1083
Joined: Wed Sep 26, 2012 5:13 pm

Re: How to smoothly rotate while dealing with rollover

Post by micha »

davisdude wrote:
micha wrote:2) If you want to go for davisdudes solution, then the last line has to be changed (I believe. I couldn't test it, because the .love does not run on my machine)

Code: Select all

self.rot = rotateAngle( self.rot, self.tRot,  math.abs(cycle(self.tRot-self.rot,-math.pi,math.pi))/5  )
I couldn't see any significant difference when I did this, but maybe I missed something. You're probably right.
Thank you for testing it. The only case where this is relevant, is when self.tRot and self.rot are close to the 2pi-gap. For example self.tRot = 0.01 and self.rot = 2pi-0.01. In all other cases, this change should not make a difference and your code is fine.
User avatar
Skeiks
Citizen
Posts: 51
Joined: Wed Jan 28, 2015 1:51 pm

Re: How to smoothly rotate while dealing with rollover

Post by Skeiks »

Thank you both! Even when I was making games in Flash this was an issue I had trouble with. I plan on using dt in some regard, I'm just not sure what kind of implementation I'm going to go with. I'm glad you like where the game is going, I hope in a few months I can come back with something more done to show ^^
Post Reply

Who is online

Users browsing this forum: No registered users and 4 guests