# LabelSprite rotate_by problem browsing

• posted
0

Hello everyone,

Newbie question : I am trying to create an animation of a label moving like a pendulum. I tried using a SpriteLabel rotating around an arbitrary point using Action.rotate_by, but it always rotates around the lower left corner of the screen (0, 0) and not around the top center, is there any way around this ?
Here is the exact code I am using:

``````from scene import *
from math import *

class MyScene(Scene):

def setup(self):
self.background_color = 'black'
self.anchor_point = (0.5, 0.0)
self.timelabel = LabelNode(position=self.size / 2, text='time')
self.timelabel.rotation = -pi / 8.0
self.run_action(Action.repeat(Action.sequence(Action.rotate_by(pi / 4.0, 1, TIMING_EASE_IN_OUT), Action.rotate_by(-pi / 4.0, 1, TIMING_EASE_IN_OUT), 0), 0))

run(MyScene(), PORTRAIT)
``````

Cheers
Andre

• posted
0

That is exactly what I wanted omz, thanks alot!

Cheers
Andre

• posted
0

Hi @omz,

is there a way to include a dynamic variable in an Action?

I was thinking of using the variable self.angle in the Action like this:

``````from itertools import cycle
from scene import *
from math import *

class MyScene(Scene):

def setup(self):
self.background_color = 'black'
self.time_anchor = Node(position=(self.size.w/2, 0), parent=self)
self.timelabel = LabelNode(position=(0, self.size.h/2), text='time')
self.angles = cycle([pi/4, -pi/4])
rotate_action = Action.repeat(Action.rotate_to(self.angles.next(), 1, TIMING_EASE_IN_OUT), 0)
self.time_anchor.run_action(rotate_action)

run(MyScene(), PORTRAIT)
``````

This does not seem to work it stays at the same angle all the time, is there any way around it?

Cheers
Andre

• posted
1

One way to do is to write your own 'Action.repeat".. In the following code, the angles get changed when you touch. May be others could suggest better ways to this.

``````from scene import *
from math import *

class MyScene(Scene):
def repeat(self):
self.rotate_action = Action.sequence(
Action.rotate_to(self.angles[0], 1, TIMING_EASE_IN_OUT),
Action.rotate_to(self.angles[1], 1, TIMING_EASE_IN_OUT),
Action.call(self.repeat), 0)
self.time_anchor.run_action(self.rotate_action)

def setup(self):
self.background_color = 'black'
self.time_anchor = Node(position=(self.size.w/2, 0), parent=self)
self.timelabel = LabelNode(position=(0, self.size.h/2), text='time')
self.angles = (pi/8, -pi/8)
self.rotate_action = Action.sequence(
Action.rotate_to(self.angles[0], 1, TIMING_EASE_IN_OUT),
Action.rotate_to(self.angles[1], 1, TIMING_EASE_IN_OUT),
Action.call(self.repeat), 0)
self.time_anchor.run_action(self.rotate_action)
self.toggle = True

def touch_began(self, touch):
if self.toggle:
self.angles = (pi/4, -pi/4)
else:
self.angles = (pi/8, -pi/8)
self.toggle = not self.toggle

run(MyScene(), PORTRAIT)

``````

• posted
1

Try this code, you can easily define the fps (frame per second), you work in degrees and you can define min/max, and you can have more interaction than with run_action:

``````from scene import *
from math import *

class MyScene(Scene):
def setup(self):
self.background_color = 'black'
self.timelabel = LabelNode(position=self.size/2, text='time')
self.ang = -45
self.delta = 1
def update(self):
self.ang = self.ang + self.delta
if abs(self.ang) > 45:
self.delta = -self.delta
self.ang = self.ang + self.delta
r = self.size[1]/2
self.timelabel.position = (x,y)

run(MyScene(), PORTRAIT,frame_interval=1)
``````

• posted
1

You can change the first line of the update function to the following code if you want TIMING_EASE_IN_OUT like effect

``````self.ang = self.ang + self.delta*cos(radians(2*self.ang)) +.05*self.delta
``````

Note that it assumes the maximum angle is 45. If it is different, you need to change 2*self.ang to appropriate expression.

• posted
0

Thank you @abcabc,
creating a new action is great, do I need to do a `self.time_anchor.remove_all_actions ()`before?
Cheers
Andre

• posted
0

Thanks @cvp,

I was trying to learn automatic actions so I had not considered your approach, I guess I was being lazy :-)

Cheers
Andre

• posted
0

No problem, I had never used scene thus I'm always happy to try and thus to learn something. Good luck

• posted
1

I think that it is not needed since the previous action will be complete by that time. I assume that "run_action" call spawns a thread and
the Action.call does not wait for the thread to complete and it returns immediately. I hope that run_action call overheads are not much.I do not know the internal implementation details and may be omz can answer this.

• posted
0

"run_action" may not be spawning a thread and it may just create action related data structures. which will be updated every frame. Anyway other experts ( I am just learning) could help you on this.

• posted
0

Well, it's running just fine!
Thanks to all!
Cheers
Andre

Internal error.

Oops! Looks like something went wrong!