This application will have two bouncing balls. It illustrates the use of attributes.
If you search for kivy, you should see the indicated image and then you may right-click on it, to download it. It is 48 by 48 pixels in size. You should save it as kivy.png, and save it to the folder where the python and kivy files will reside.
These are the imports. The balls will be based on the Widget class, as will be the root class. The ListProperty holds the ball's velocity. The importance of the Vector class lies in helping write cleaner code, instead of referring to individual components of velocity. It is imported as the alias Vec. The Clock will set the framerates for the two balls. Lastly, we require the python program run with a Kivy version of 1.8.0 or higher.
The Ball class is created, a subclass of the Widget class. It is empty, since the kv file defines its visual properties and its behavior is modified by use of attributes, ball1 and ball2, in the root class. For the root class we create 2 ListProperties holding the velocity of the balls. In the constructor, we set the balls initial positions. To set the initial positions, we had to use the ball1 and ball2 attribute. These are defined in the kv file.
There will be elastic collisions off the bounding box defined by the window size. For example if the ball bounces off a horizontal wall, its velocity in the y-direction changes sign.
The function update1 operates at 60 Hz. The ball position is updated. Then there are four conditional statements seeing if ball1 has reached either of the 4 edges. If so, it's x- or y-velocity changes sign.
We do likewise for ball2 in update2.
This is the app class. It sets the title of the window as 'Two Bouncing Balls'. It sets two clocks operating at a 60 Hz rate.
# ex29.py from kivy.uix.widget import Widget from kivy.app import App from kivy.properties import ListProperty from kivy.vector import Vector as Vec from kivy.clock import Clock import kivy kivy.require('1.8.0') class Ball(Widget): pass class Ex29(Widget): vel1 = ListProperty([4,3]) vel2 = ListProperty([3,4]) def __init__(self, **kwargs): super(Ex29, self).__init__(**kwargs) self.ball1.pos = self.width/2, self.height/2 self.ball2.pos = self.width/4, self.height/4 def update1(self,dt): self.ball1.pos = Vec(self.vel1) + self.ball1.pos if self.ball1.x<0: self.vel1[0] *= -1 if self.ball1.x>self.width-50: self.vel1[0] *= -1 if self.ball1.y<0: self.vel1[1] *= -1 if self.ball1.y>self.height-50: self.vel1[1] *= -1 def update2(self,dt): self.ball2.pos = Vec(self.vel2) + self.ball2.pos if self.ball2.x<0: self.vel2[0] *= -1 if self.ball2.x>self.width-50: self.vel2[0] *= -1 if self.ball2.y<0: self.vel2[1] *= -1 if self.ball2.y>self.height-50: self.vel2[1] *= -1 class Ex29App(App): def build(self): self.title = "Two Bouncing Balls" ex29 = Ex29() Clock.schedule_interval(ex29.update1, 1.0/60) Clock.schedule_interval(ex29.update2, 1.0/60) return ex29 if __name__=='__main__': Ex29App().run()
In the kv file, we use a directive to see if we are running Kivy 1.8.0 or higher. The Ball widget has a size of 50 by 50 pixels, and we define the canvas.after as circle of that size with the downloaded image.
For the root, the Widget size is 800 by 600. The attributes ball1 and ball2 are created. The background for the screen is green.
Then ball1 is defined. We also define canvas.before so the color of red will be applied to this ball.
The second ball will have a color of magenta. For ball1 and ball2, we created ids, we had earlier used, in defining the attributes. The attributes are the way our Python program can access ball1 and ball2.
# ex29.kv #:kivy 1.8.0 <Ball>: size: 50,50 canvas.after: Ellipse: pos: self.pos size: self.size source: 'kivy.png' <Ex29>: size: 800, 600 ball1: ball_id1 ball2: ball_id2 canvas: Color: rgb: 0,1,0 Rectangle: size: root.width,root.height pos: 0,0 Ball: id: ball_id1 canvas.before: Color: rgb: 1, 0, 0 Ball: id: ball_id2 canvas.before: Color: rgb: 1, 0, 1
Demo of App on Youtube
Is there a way to move the ball logic inside the ball class?
ReplyDeleteAnd then instantiate the object inside the main class to have n*ball?
Thanks!!
i'm thinking at something livke that:
ReplyDeleteclass Ball(Widget):
vel=ListProperty([4,3])
def __init__(self,**kwargs):
super(Ball,self).__init__(**kwargs)
self.sx=300
self.sy=300
self.vel=[3,4]
self.pos=800/self.sx,600/self.sy
def update(self,dt):
self.pos=Vec(self.vel)+self.pos
if self.x<0: self.vel[0] *= -1
if self.x>750: self.vel[0] *= -1
if self.y<0: self.vel[1] *= -1
if self.y>550: self.vel[1] *= -1
class Ex29(Widget):
ball1=Ball()
#ball2=Ball()
def update_ball(self,dt):
self.dtt=dt
self.ball1.update(self.dtt)
#self.ball2.update(self.dtt)
But it works only with one istance of the ball!!
Sorry but the system didn't retain the indentation!
DeleteThis comment has been removed by the author.
ReplyDeleteGood Post! Thank you so much for sharing this pretty post, it was so good to read and useful to improve my knowledge as updated one, keep blogging.
ReplyDeletePython Training in electronic city
I am learning kivy, Thanks for uploading this tutorials, these are very helpful to me.
ReplyDeletenice information for beginners.thank you.
ReplyDeletejavacodegeeks
welookups python