Page 1 of 1
How to smoothly rotate while dealing with rollover
Posted: Wed Feb 18, 2015 1:32 am
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!
Re: How to smoothly rotate while dealing with rollover
Posted: Wed Feb 18, 2015 1:43 am
by davisdude
Use dt
Re: How to smoothly rotate while dealing with rollover
Posted: Wed Feb 18, 2015 1:54 am
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.
Re: How to smoothly rotate while dealing with rollover
Posted: Wed Feb 18, 2015 2:51 am
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
Re: How to smoothly rotate while dealing with rollover
Posted: Wed Feb 18, 2015 3:22 am
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.
Re: How to smoothly rotate while dealing with rollover
Posted: Wed Feb 18, 2015 5:08 am
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/
Re: How to smoothly rotate while dealing with rollover
Posted: Wed Feb 18, 2015 6:52 am
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:
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 )
Re: How to smoothly rotate while dealing with rollover
Posted: Wed Feb 18, 2015 3:34 pm
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.)
Re: How to smoothly rotate while dealing with rollover
Posted: Wed Feb 18, 2015 3:45 pm
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.
Re: How to smoothly rotate while dealing with rollover
Posted: Wed Feb 18, 2015 10:00 pm
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