# animation.py # Walker M. White (wmw2) # November 8, 2012 """Module to show off how animation works. To animate in Kivy, we assign a callback function to the function Clock.schedule_interval, and instruct it the amount of time to delay. Clock.schedule_interval only works in Kivy applications. You cannot use it in general Python applications.""" from kivy.uix.floatlayout import FloatLayout from kivy.graphics.vertex_instructions import Rectangle, Ellipse from kivy.graphics.context_instructions import Color from kivy.config import Config from kivy.clock import Clock from kivy.app import App import random, math # CONSTANT TO DEFINE ANIMATION STEP SIZE ANIMATION_STEPS = 100 class AnimationPanel(FloatLayout): """Drawing canvas to animate the ellipse.""" # HIDDEN FIELDS _vx = 1 # Velocity of x-coordinate _vy = 1 # Velocity of y-coordinate _ellipse = None # Ellipse to animate # Number of steps in animation. # Invariant: If 0, ellipse is centered in the screen middle. _steps = 0 def __init__(self,**kw): """Constructor: Makes a new panel for animation.""" # Pass arguments to super class super(AnimationPanel,self).__init__(**kw) # Assign callback for animation Clock.schedule_interval(self.animate,1.0/60.0) # This weird command tells the panel what to draw. with self.canvas: Color(1,1,1) Rectangle(pos=self.pos,size=self.size) Color(1,0,0) self._ellipse = Ellipse(pos=(self.center_x-20,self.center_y-20),size=(40,40)) def animate(self,dt): """Animate the ellipse. If _steps is 0, pick a new random velocity. If _steps > ANIMATION_STEPS/2, move away using velocity (vx,vy) If _steps <= ANIMATION_STEPS/2, but > 0, move back to the center.""" if self._steps == 0: # Make velocity a unit vector self._vx = random.random()*random.choice([1,-1]) self._vy = math.sqrt(1-self._vx*self._vx)*random.choice([1,-1]) self._steps = ANIMATION_STEPS elif self._steps > ANIMATION_STEPS/2: x = self._ellipse.pos[0] y = self._ellipse.pos[1] self._ellipse.pos = (x+self._vx,y+self._vy) self._steps = self._steps - 1 # _steps is a loop counter! else: x = self._ellipse.pos[0] y = self._ellipse.pos[1] self._ellipse.pos = (x-self._vx,y-self._vy) self._steps = self._steps - 1 # _steps is a loop counter! class AnimationApp(App): """Instance is an application with animation but no user interaction.""" def build(self): """Build application with a single internal panel""" Config.set('graphics', 'width', '400') Config.set('graphics', 'height', '400') return AnimationPanel(size=(400,400)) # Application Code if __name__ == '__main__': AnimationApp().run()