Rotation Math help needed!
firemaplegames
Member Posts: 3,211
Hey all!
I am having a math problem that I hope somebody can help me out with...
I have an Actor that the player can rotate with touch. Imagine a record that a DJ would use to scratch with, or an old iPod touch wheel.
You grab the record and can rotate it either clockwise or counterclockwise.
I have this working great.
What I need to do now is to figure out if I am rotating it clockwise or counterclockwise at any given time.
I basically need a Display Text that always reads either:
"You are currently rotating the record clockwise."
or
"You are currently rotating the record counterclockwise"
Now, the trick is that you won't be lifting your finger. You can tap and hold and rotate the record in either direction as much as you want, and the text needs to always display correctly.
I BELIEVE the answer lies in figuring out the cross product of the vectors:
http://en.wikipedia.org/wiki/Cross_product
But the math escapes me...
If anybody can help me out, I would really appreciate it!
Joe
I am having a math problem that I hope somebody can help me out with...
I have an Actor that the player can rotate with touch. Imagine a record that a DJ would use to scratch with, or an old iPod touch wheel.
You grab the record and can rotate it either clockwise or counterclockwise.
I have this working great.
What I need to do now is to figure out if I am rotating it clockwise or counterclockwise at any given time.
I basically need a Display Text that always reads either:
"You are currently rotating the record clockwise."
or
"You are currently rotating the record counterclockwise"
Now, the trick is that you won't be lifting your finger. You can tap and hold and rotate the record in either direction as much as you want, and the text needs to always display correctly.
I BELIEVE the answer lies in figuring out the cross product of the vectors:
http://en.wikipedia.org/wiki/Cross_product
But the math escapes me...
If anybody can help me out, I would really appreciate it!
Joe
Comments
on mouse down (touch inside)
timer 0
if 0 < wheel.rotation-lastRotation then
direction = clockwise
otherwise
direction = anticlockwise
lastRotation = wheel.rotation
i have not tested this. It's a bit of a guess, sorry haven't had enough sleep for this. No doubt it will come to be when i close my eyes.
@stanimation: I believe somewhere on that page it describes 2D plane vectors, but by that point, blood was dripping out of my ears!
(you can keep rotating the disc around and around... in either direction)
I read somewhere that you can always tell the direction of rotation of an object by using the cross product and was oping that I could plug in a math formula...
if abs(wheel.rotation-lastRotation) > 259 then... etc etc
But there HAS to be a better way.
http://gamesalad.com/game/play/58254
Feel free to dig through it. It's just one actor.
I stripped out all the code that I was noodling with for the past few hours, so it is clean...
And yeah, if anybody can figure out how to tell if I am rotating the disc clockwise or counterclockwise at any given moment, that would really help me. I've been fiddling with this too long and my eyes are glazing over...
There are a couple other methods that could be used that involve sampling values and then using some nested rule logic to determine the rotation direction. However, these are more susceptible to quick false readout flashed too. Once such would be a rule using the difference between touch X and previous touch X and then nested rules for both the true/false results that then use the difference between touch Y and previous touch Y. I don't really recommend it. Another would be the sampling of the dial's rotation as others have suggested, but then you get false readout flashes when you go from 0 to 360 and also from 360 to 0 [or 180 to -180 and -180 to 180 if using an angle from "vectorToAngle()].
I think a way around the sampling issue would be to have an invisible actor constrained somewhere along the outer edge of the dial (or even further out would work) using the sin/cos "circle movement" method. Instead of using the "timer" for the rotation, you would use the rotation of the dial. You would then get your first vector from the center of the dial out to the center of the invisible actor. Then your second vector would be from the center of the invisible actor to the touch. This would give you constrainable values for both vectors.
The vector from the invisible actor to the touch *may* need a ruleset around it depending on the relative position of one to another but I'm thinking not. :-| That *may* also hold true in the touch sampling method too.
"magnitude()" can give you a vector's magnitude.
"vectorToAngle()" gives you the rotation angle of the vector but not direction of the vector. I think you can compute the direction with the Y coordinate difference divided by the X coordinate difference (think "rise over run" of a line -> `y = mx + b` where "`m`" is "rise over run") but I am not 100% on this fact.
After you get your vectors, if you compute a cross product on them, you will need to leave any z coordinate values at zero. Doing this then will give you a counter-clockwise rotation when the cross product is positive and a clockwise rotation when the cross product is negative.
Now if anyone who can remember vector mathematics can chime in to help with that!!! It's been decades since I have done any of that. :-( Sorry I couldn't close the deal!
Would be nice if GS folks added some basic vector functions based on (x, y) coordinate inputs and even (x, y, z) coordinate inputs as we could always leave "z" at zero since things like cross product are three dimension based.
http://www.math.umn.edu/~nykamp/m2374/readings/crossprod/
The positive/negative aspect of the dot product appears to toggle at a 180 degree split of a circle centered on the plane at the origin.
-----
Also, for general vector reference, this is a pretty good page:
http://www.uib.no/med/avd/miapr/arvid/MOD3/Bildematematikk/vectors_nmt.pdf
Edit: Re-did the first part a bit.
Share you solution if you find one!
However, it all comes down to where the user clicks relative to another point - the other point moving or otherwise. They could click in one area that makes the thumb rule evaluate to positive (i.e. counterclockwise) and rotate counterclockwise for a bit with the rule holding true. However, they can then reverse the direction (clockwise) and since the thumb rule still holds true, it evaluates to positive even though they are now going clockwise.
The reason being, the vectors stay relative to each other throughout the mouse/touch move keeping the thumb rule consistent - that is until they rotate 180 and the relationship to each other is reversed (reversing the thumb rule). So basically you something akin to the "vectorToAngle()" value when applied to the actor's X/Y and the touch/mouse X/Y.
Hard to explain. I don't think it is going to work.
Will probably need to do the sampling thing and live with a brief incorrect report of the direction as stated above in my long post (i.e. the "flash"). You can minimize it by having the sample period very small/short and use real instead of integers to allow finer comparing between the current rotation and the previous sampled rotation. Although the integer vs. real is mainly if the user tries to "fine tune" the rotation on a large dial. It won't matter for large arc movements and/or small dials.
Grr!
If anyone can work this out, feel free. Pretty sure I am correct but it is still a tad hazy from lack of use over the years so you never know.
I ALMOST have it completely working. It now works consistently except where it switches from 0 to 360 and vice-versa. I get a momentary blip where it shows the opposite direction.
I'll dig into this again in the morning.
http://gamesalad.com/game/play/58443
i'm replicating this function to get the angle difference between the current angle and the last one
private function angleDifference(a1:Number, a2:Number):Number {
var angle:Number = a1-a2;
if (Math.abs(angle) > Math.PI) {
angle = angle > 0 ? angle-Math.PI*2 : Math.PI*2+angle;
}
return angle;
}
there's still a problem when the wheel crosses 0 angle, so i just check the diff is > -270 and < 270 etc
maybe this is actually just a more complicated version of what mrfunkleberry suggested anyway... i'll compare the two
j
Thanks for making that! I appreciate all the help!
I just figured it myself a few minutes ago...
I am actually making an old combination lock for a safe in my new game. You have to turn the dial Right-Left-Right to specific numbers to open the lock.
I now have it all working correctly. You can now open the safe!
I am pretty much doing that exact function as you have above. I am a Flash programmer too, so I always look at Actionscript code first when I am trying to figure something out!
Again, I appreciate the time!
Joe
you can just use game.diffangle = game.lastangle - self.Rotation as suggested previously
i don't use any timers though..
download here
http://gamesalad.com/game/play/58447
I need to check out how you are capturing lastangle without a Timer...
Thanks!!!
I'd be interested to see how you've used it anyway
j
does constrain cause performance issues? surely no more than timer though. I'm new to gamesalad so i'm just doing whatever seems to work
The stacking order in a Rule USUALLY happens from the top down, but sometimes certain behaviors will execute first. Just something to watch out for...
Both Constrains and Timers are resource hogs, but since they are only happening when the mouse is down, it's not so bad.
Plus, in this case you have to use them, so it doesn't really matter.
Yes, like Flash, doing whatever seems to work is often the best strategy with GameSalad!
Yeah, the only problem I see with jmp909's last "simpler" solution is what FMG alludes to in his post above this one:
"The stacking order in a Rule USUALLY happens from the top down, but sometimes certain behaviors will execute first. Just something to watch out for..."
They *usually* execute top down and they almost always execute entirely at a given logic or nest level. However, as your scene gets more and more complex, time sensitive things can start to break down so you may find you end up having to insert a timer in there and/or re-organize the order of the behaviors.
So if something you made early on in a project starts to work less as your scene gets more complex, it may be a performance thing.
Just something to watch out for as Joe mentions.