This would be a long post with question in the end.
Hi I need to rotate object via player input (mouse for now) and count rotation turns (or spins). Object could be rotated in any direction - clockwise (cw) or counterclockwise (ccw).
For base for movement I’ve taken this example - britzl/defold-orthographic. Shout out to author, his examples always helps me a lot =)
In update() function of the hitman/player script I add something like this to count rotation turns when player hold “mouse button 1”:
-- [hitman.script](https://github.com/britzl/defold-orthographic/blob/master/example/shared/objects/hitman.script) local function process_spin(self, angle) -- transform angle from rad to degree and normilize to 0 - 360 angle = angle * 180/3.14159 if angle < 0 then angle = 360 + angle end -- set initial values on grab - when the player click mouse button 1 if not self.grab then self.grab = true self.initial_angle = angle end -- get the current angle of the object local current_angle = angle -- calculate the difference between the current and initial angles local angle_diff = current_angle - self.initial_angle angle_diff = math.floor(angle_diff) -- normalize the angle difference to be between -180 and 180 degrees if angle_diff > 180 then angle_diff = angle_diff - 360 elseif angle_diff < -180 then angle_diff = angle_diff + 360 end -- check and set rotation direction: cw or ccw if self.rotation_direction == 0 then if angle_diff < 0 then self.rotation_direction = 1 elseif angle_diff > 0 then self.rotation_direction = -1 end end -- normilize rotation to 0 - 360 degree if angle_diff < 0 then angle_diff = 360 + angle_diff end -- count turns if (self.rotation_direction == 1 and angle_diff <= 5 and angle_diff > 0) or (self.rotation_direction == -1 and angle_diff >= 355) then self.turn_count = self.turn_count + 1 self.initial_angle = angle end end function update(self, dt) ... -- line 27 if self.input[hash('touch')] then process_spin(self, angle) elseif self.grab then self.grab = false self.last_diff = 0 self.rotation_direction = 0 end ... end
And this code works at first. The bug is when player change rotation direction while holding “mouse button 1”. So I add check for rotation direction in process_spin function (don’t like how it looks, need to be cleared):
-- check change in dirrection -- this if statement changed a lot, but always has some bugs... if self.last_diff ~= 0 and (self.last_diff - angle_diff) ~=0 and ((angle_diff ~= 0 and self.rotation_direction == -1) or (self.rotation_direction == 1)) then local new_direction = 0 if (self.last_diff - angle_diff) > 0 then new_direction = 1 elseif (self.last_diff - angle_diff) < 0 then new_direction = -1 end if new_direction ~= self.rotation_direction then self.grab = false self.rotation_direction = 0 self.initial_angle = angle self.last_diff = 0 end if self.last_diff ~= angle_diff then self.last_diff = angle_diff end
And this part gave me a lot of issues, when player change direction on early start around 0 degree. When one start rotate in one direction from
angle_diff = 0 to
angle_diff = 1 degree and drastically changes the direction to, say,
angle_diff = 358 degree. Code go crazy on this 1 - 358 degree change, because it looks like very quick full circle =)
After some playing with if statement I thought that I’m going a wrong way and I need to deep dive into quaternion topic (never used them before). Long story short I came up with this code:
-- [hitman.script](https://github.com/britzl/defold-orthographic/blob/master/example/shared/objects/hitman.script) -- line 24 local rotation = vmath.quat_rotation_z(angle) local rot_diff = vmath.conj(go.get_rotation()) * rotation local direction = math.floor(rot_diff.z * 100) -- direction < 0 - clockwise; direction > 0 - counterclockwise. go.set_rotation(rotation)
This code seems to be working, but I’m not sure that it is optimal for such a task. Quat conjugate and multiply could be heavy to calculate… Have not done performance testing yet.
Maybe I could get rotation direction in more easy or efficient way? In fact when I set new rotation
go.set_rotation(rotation) object rotate in right direction, “closest direction”. So engine already know it would be cw or ccw. Maybe I can get this info without additional calculations?