# How to apply rotation on a loop on BGE?

I have this problem, I created a while loop in my script, my intention is to rotate my object with a decreasing over time speed

My script looks like this:

def rotar(obj, sentido):
velocity = 2
while velocity > initialVelocity:
obj.applyRotation((0,0, sentido*velocity), True)
velocity = velocity/1.5
print(obj.worldOrientation.to_euler().z)


The loop isn't working as intended, as it applies the rotation after all the loop ends, how can I apply the rotation on each iteration of the while loop?

I also would love to set the limit of the rotation where the object reaches certain rotation, say 72º on the local Z axis, but for the moment it seems like a dream

You can do it with this but need more work. This example rotate a cube from 0 degrees(0.0 radians) and stop when it reached 170 degrees(2.96 radians, when distance angle of cube and angle to reach is 0) even if key still pressed (you can work on that to meet your need), it slow rotation when key is relase if the angle is not reached, but the problem is that if the rotation speed go less than 0 will start a turn to the other way (set minimun rotation speed, actual is set to 0.002) and if angle is more that 180 degrees(3.13 radians) the radians will turn negative e.g 181 degrees(-3.14 radians) so you need to work on that. Have nice a day!

from bge import logic
import math

class Rotation():

def __init__(self, owner, angle):
self.rotation = 0.01 # rotation speed
self.rotate_bool = False
self.rotating = False
self.body = owner
self.angle_to_rotate = angle
self.main = self.state

def rotate(self):
self.body.applyRotation([0,0,self.rotation], 1)
self.rotating = True

def relase(self, distance):
if self.rotation > 0.002 and self.rotating:
self.rotation -= 0.00002 #decrease rotation speed
print('rotation:',self.rotation)
if distance > 0 and self.rotation > 0:#avoid negative rotation, it will turn the other way
self.body.applyRotation([0,0,self.rotation], 1)
elif self.body.localOrientation.to_euler().z == math.radians(self.angle_to_rotate):#Stop rotation when the angles are equal
self.body.applyRotation([0,0,0], 1)
self.rotating = False

def state(self):
rotation = self.body.localOrientation.to_euler()
angle_distance = angle - rotation.z
print(rotation.z, angle, angle_distance)
if self.rotate_bool:
self.rotate()
elif not self.rotate_bool and self.rotating:
self.relase(angle_distance)

def main(cont):
key = cont.sensors['Keyboard']
if not 'init' in cont.owner:
cont.owner['rotation'] = Rotation(cont.owner, 170)
cont.owner['init'] = True
return
if key.positive:
cont.owner['rotation'].rotate_bool = True
else:
cont.owner['rotation'].rotate_bool = False
cont.owner['rotation'].main()


related: Damped Steering>Seek via Python

• I have accepted it, although I couldn't finish to implement this, but I'm so much closer thx to you – Santiago Capdevila May 3 '17 at 23:32
• what problem do you have? – Strapicarus May 3 '17 at 23:42
• related: Damped Steering>Seek via Python – Strapicarus Nov 18 '17 at 20:22

Another approach:

• Parent the object to an empty.
• Enable slow parent (with a delay > 0)
• set the empty to the target orientation

Due to the slow parent the object will smoothly turn until it matches the empties orientation.

A Python controller describes the operations within a single point in time (logic frame).

This means your code performs all turns at the same point in time. The render will take place after your look completed (regardless how long your loop takes).

Animations are (change) operations over time. That means your Python controller should perform a single turn, rather than all turns. You execute the controller as long as you want the animation to take place.

Example:

def rotar(obj, sentido):
velocity = 2
if velocity < initialVelocity:
obj.applyRotation((0,0, sentido*velocity), True)
velocity = velocity/1.5
print(obj.worldOrientation.to_euler().z)


(Replaced while with if in your sample)

# Continual animation

While the above code performs the behavior of a single frame you need behavior at an higher abstraction.

E.g. you want:

• when pressing a key
• determine the final orientation
• start turning
• when the orientation reaches the final orientation
• end turning
• while turning
• rotate on step towards the final orientation

You might discover a slight issue: what happens when the final step is too much? Means: the last step exceeds the final orientation.

As described the object will start shaking as it turns left/right all the time.

Solutions:

1. stop before the final orientation is reached (it never exceeds, but might not match the final orientation)

2. stop after exceeding the final orientation (it will exceed unless it hits the final orientation)

3. when the last step is larger than the necessary step size immediately apply the final orientation (this will always lead to the final orientation, but the steps are not necessarily of the same size).

• My intention is this: on key press rotate an object on the Z axis a predetermined amount of degrees, with a smooth rotation, could you figure out how or a tip for that? thanks – Santiago Capdevila Apr 18 '17 at 22:52
• I guess smooth means: over time. This means you turn the object just a bit at each frame until the rotation reaches the desired angle. – Monster Apr 19 '17 at 4:41
• But with an IF statement it just rotates a bit on each frame, but when I release the key it just stops, not when a predetermined orientation is reached, that's what I want to do – Santiago Capdevila Apr 20 '17 at 22:52